From 992a7ddd281746dadc60b72ab7d6023b51e2bd67 Mon Sep 17 00:00:00 2001 From: emcmanus Date: Wed, 21 Oct 2009 17:33:18 +0200 Subject: [PATCH] 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 --- make/docs/CORE_PKGS.gmk | 2 - .../com/sun/jmx/defaults/JmxProperties.java | 14 +- .../com/sun/jmx/defaults/ServiceName.java | 4 +- .../sun/jmx/event/DaemonThreadFactory.java | 77 - .../com/sun/jmx/event/EventBuffer.java | 252 --- .../com/sun/jmx/event/EventClientFactory.java | 46 - .../com/sun/jmx/event/EventConnection.java | 81 - .../com/sun/jmx/event/EventParams.java | 65 - .../com/sun/jmx/event/LeaseManager.java | 155 -- .../com/sun/jmx/event/LeaseRenewer.java | 143 -- .../com/sun/jmx/event/ReceiverBuffer.java | 97 -- .../sun/jmx/event/RepeatedSingletonJob.java | 119 -- .../DefaultMBeanServerInterceptor.java | 318 +--- .../jmx/interceptor/DispatchInterceptor.java | 551 ------- .../DomainDispatchInterceptor.java | 350 ---- .../MBeanServerInterceptorSupport.java | 127 -- .../NamespaceDispatchInterceptor.java | 297 ---- .../jmx/interceptor/SingleMBeanForwarder.java | 442 ----- .../sun/jmx/mbeanserver/ConvertingMethod.java | 12 +- .../DefaultMXBeanMappingFactory.java | 98 +- .../sun/jmx/mbeanserver/DynamicMBean2.java | 16 +- .../com/sun/jmx/mbeanserver/Introspector.java | 308 +--- .../sun/jmx/mbeanserver/JmxMBeanServer.java | 30 +- .../sun/jmx/mbeanserver/MBeanAnalyzer.java | 42 +- .../sun/jmx/mbeanserver/MBeanInjector.java | 295 ---- .../jmx/mbeanserver/MBeanInstantiator.java | 9 - .../jmx/mbeanserver/MBeanIntrospector.java | 235 +-- .../com/sun/jmx/mbeanserver/MBeanSupport.java | 16 +- .../jmx/mbeanserver/MXBeanIntrospector.java | 92 +- .../com/sun/jmx/mbeanserver/MXBeanLookup.java | 231 +-- .../sun/jmx/mbeanserver}/MXBeanMapping.java | 8 +- .../mbeanserver}/MXBeanMappingFactory.java | 47 +- .../com/sun/jmx/mbeanserver/MXBeanProxy.java | 23 +- .../sun/jmx/mbeanserver/MXBeanSupport.java | 25 +- .../mbeanserver/NotificationMBeanSupport.java | 82 - .../sun/jmx/mbeanserver/NotifySupport.java | 186 --- .../com/sun/jmx/mbeanserver/PerInterface.java | 4 +- .../jmx/mbeanserver/PerThreadGroupPool.java | 71 - .../com/sun/jmx/mbeanserver/Repository.java | 4 +- .../StandardMBeanIntrospector.java | 35 +- .../jmx/mbeanserver/StandardMBeanSupport.java | 12 +- .../classes/com/sun/jmx/mbeanserver/Util.java | 476 +----- .../sun/jmx/namespace/DomainInterceptor.java | 463 ------ .../sun/jmx/namespace/HandlerInterceptor.java | 734 --------- .../jmx/namespace/NamespaceInterceptor.java | 220 --- .../sun/jmx/namespace/ObjectNameRouter.java | 175 -- .../jmx/namespace/RoutingConnectionProxy.java | 106 -- .../RoutingMBeanServerConnection.java | 556 ------- .../com/sun/jmx/namespace/RoutingProxy.java | 395 ----- .../sun/jmx/namespace/RoutingServerProxy.java | 576 ------- .../com/sun/jmx/namespace/package.html | 45 - .../serial/DefaultRewritingProcessor.java | 150 -- .../namespace/serial/IdentityProcessor.java | 74 - .../namespace/serial/JMXNamespaceContext.java | 145 -- .../namespace/serial/RewritingProcessor.java | 362 ----- .../serial/RoutingOnlyProcessor.java | 74 - .../serial/SerialRewritingProcessor.java | 172 -- .../com/sun/jmx/namespace/serial/package.html | 44 - .../remote/internal/ServerNotifForwarder.java | 33 +- .../com/sun/jmx/remote/util/EnvHelp.java | 59 - .../remote/util/EventClientConnection.java | 469 ------ .../lang/management/PlatformComponent.java | 3 +- .../classes/java/util/logging/Logging.java | 7 +- .../classes/javax/management/AndQueryExp.java | 22 - .../javax/management/AttributeList.java | 50 - .../javax/management/AttributeValueExp.java | 53 +- .../javax/management/BetweenQueryExp.java | 5 - .../javax/management/BinaryOpValueExp.java | 4 +- .../javax/management/BinaryRelQueryExp.java | 5 - .../javax/management/ClientContext.java | 1091 ------------- .../classes/javax/management/Description.java | 180 -- .../classes/javax/management/Descriptor.java | 77 +- .../javax/management/DescriptorFields.java | 137 -- .../javax/management/DescriptorKey.java | 50 +- .../javax/management/DynamicWrapperMBean.java | 62 - .../management/GenericMBeanException.java | 276 ---- .../classes/javax/management/Impact.java | 105 -- .../management/InstanceNotFoundException.java | 14 +- .../javax/management/JMRuntimeException.java | 18 +- src/share/classes/javax/management/JMX.java | 571 +------ src/share/classes/javax/management/MBean.java | 68 - .../javax/management/MBeanAttributeInfo.java | 6 +- .../management/MBeanConstructorInfo.java | 2 +- .../javax/management/MBeanException.java | 64 +- .../classes/javax/management/MBeanInfo.java | 419 +---- .../javax/management/MBeanOperationInfo.java | 20 +- .../javax/management/MBeanPermission.java | 177 +- .../javax/management/MBeanRegistration.java | 95 +- .../classes/javax/management/MBeanServer.java | 149 +- .../management/MBeanServerConnection.java | 169 +- .../javax/management/MBeanServerDelegate.java | 93 +- .../javax/management/MBeanServerFactory.java | 320 +--- .../MBeanServerInvocationHandler.java | 76 +- .../management/MBeanServerNotification.java | 62 +- .../classes/javax/management/MXBean.java | 116 +- .../javax/management/ManagedAttribute.java | 64 - .../javax/management/ManagedOperation.java | 67 - .../classes/javax/management/NotQueryExp.java | 6 - .../javax/management/Notification.java | 34 +- .../NotificationBroadcasterSupport.java | 25 +- .../javax/management/NotificationInfo.java | 135 -- .../javax/management/NotificationInfos.java | 72 - .../classes/javax/management/ObjectName.java | 361 +--- .../javax/management/ObjectNameTemplate.java | 131 -- .../classes/javax/management/OrQueryExp.java | 20 - .../QualifiedAttributeValueExp.java | 3 +- src/share/classes/javax/management/Query.java | 381 +---- .../classes/javax/management/QueryEval.java | 6 - .../management/QueryNotificationFilter.java | 415 ----- .../classes/javax/management/QueryParser.java | 626 ------- .../javax/management/SendNotification.java | 38 - .../management/StandardEmitterMBean.java | 220 +-- .../javax/management/StandardMBean.java | 547 +------ .../javax/management/event/EventClient.java | 1104 ------------- .../management/event/EventClientDelegate.java | 824 ---------- .../event/EventClientDelegateMBean.java | 317 ---- .../event/EventClientNotFoundException.java | 79 - .../javax/management/event/EventConsumer.java | 98 -- .../management/event/EventForwarder.java | 63 - .../javax/management/event/EventReceiver.java | 77 - .../javax/management/event/EventRelay.java | 79 - .../management/event/EventSubscriber.java | 376 ----- .../event/FetchingEventForwarder.java | 151 -- .../management/event/FetchingEventRelay.java | 391 ----- .../javax/management/event/ListenerInfo.java | 169 -- .../management/event/NotificationManager.java | 136 -- .../event/RMIPushEventForwarder.java | 198 --- .../management/event/RMIPushEventRelay.java | 161 -- .../javax/management/event/RMIPushServer.java | 48 - .../javax/management/event/package-info.java | 312 ---- .../modelmbean/DescriptorSupport.java | 50 +- .../modelmbean/ModelMBeanAttributeInfo.java | 42 +- .../modelmbean/ModelMBeanConstructorInfo.java | 41 +- .../modelmbean/ModelMBeanInfoSupport.java | 7 +- .../ModelMBeanNotificationInfo.java | 19 +- .../modelmbean/ModelMBeanOperationInfo.java | 33 +- .../modelmbean/RequiredModelMBean.java | 67 +- .../monitor/MonitorNotification.java | 2 +- .../javax/management/namespace/JMXDomain.java | 378 ----- .../management/namespace/JMXNamespace.java | 666 -------- .../namespace/JMXNamespaceMBean.java | 96 -- .../namespace/JMXNamespacePermission.java | 1446 ----------------- .../namespace/JMXNamespaceView.java | 300 ---- .../management/namespace/JMXNamespaces.java | 360 ---- .../namespace/JMXRemoteNamespace.java | 809 --------- .../namespace/JMXRemoteNamespaceMBean.java | 96 -- .../MBeanServerConnectionWrapper.java | 702 -------- .../namespace/MBeanServerSupport.java | 1321 --------------- .../namespace/VirtualEventManager.java | 378 ----- .../management/namespace/package-info.java | 629 ------- .../CompositeDataInvocationHandler.java | 14 +- .../openmbean/CompositeDataSupport.java | 70 +- .../management/openmbean/CompositeType.java | 8 +- .../openmbean/MXBeanMappingClass.java | 61 - .../openmbean/MXBeanMappingFactoryClass.java | 72 - .../javax/management/openmbean/OpenType.java | 2 +- .../classes/javax/management/package.html | 200 +-- .../remote/IdentityMBeanServerForwarder.java | 303 ---- .../javax/management/remote/JMXConnector.java | 22 +- .../management/remote/JMXConnectorServer.java | 461 +----- .../remote/JMXConnectorServerMBean.java | 6 - .../management/remote/JMXServiceURL.java | 46 - .../remote/rmi/RMIConnectionImpl.java | 376 +---- .../management/remote/rmi/RMIConnector.java | 86 +- .../remote/rmi/RMIConnectorServer.java | 38 +- .../management/remote/rmi/RMIServerImpl.java | 46 - .../sun/management/ClassLoadingImpl.java | 2 +- .../sun/management/CompilationImpl.java | 2 +- .../sun/management/HotSpotDiagnostic.java | 6 +- .../sun/management/HotspotInternal.java | 2 +- .../management/ManagementFactoryHelper.java | 6 +- .../classes/sun/management/MemoryImpl.java | 10 +- .../sun/management/OperatingSystemImpl.java | 2 +- .../classes/sun/management/RuntimeImpl.java | 8 +- .../classes/sun/management/ThreadImpl.java | 6 +- src/share/classes/sun/management/Util.java | 20 +- .../Introspector/AnnotatedMBeanTest.java | 337 ---- .../AnnotatedNotificationInfoTest.java | 442 ----- .../Introspector/AnnotationTest.java | 173 +- .../ExceptionsDescriptorTest.java | 245 --- .../Introspector/MBeanDescriptionTest.java | 830 ---------- .../Introspector/ObjectNameTemplateTest.java | 343 ---- .../Introspector/ParameterNameTest.java | 116 -- .../Introspector/ResourceInjectionTest.java | 656 -------- .../MBeanServer/AttributeListMapTest.java | 115 -- .../MBeanServer/DynamicWrapperMBeanTest.java | 405 ----- .../InstanceNotFoundExceptionTest.java | 76 - .../MBeanServer/MBeanExceptionTest.java | 101 +- .../NamedMBeanServerTest.java | 441 ----- .../ObjectName/ApplyWildcardTest.java | 182 +-- .../management/ObjectName/ValueOfTest.java | 175 -- .../context/ContextForwarderTest.java | 103 -- .../javax/management/context/ContextTest.java | 534 ------ .../context/LocaleAwareBroadcasterTest.java | 328 ---- test/javax/management/context/LocaleTest.java | 140 -- .../management/context/LocalizableTest.java | 192 --- .../management/context/RemoteContextTest.java | 496 ------ .../localizable/MBeanDescriptions.properties | 9 - .../localizable/MBeanDescriptions_fr.java | 42 - .../context/localizable/Whatsit.java | 59 - .../context/localizable/WhatsitMBean.java | 53 - .../descriptor/DescriptorConstructorTest.java | 46 - .../eventService/AddRemoveListenerTest.java | 371 ----- .../eventService/CustomForwarderTest.java | 395 ----- .../eventService/EventClientExecutorTest.java | 190 --- .../eventService/EventClientThreadTest.java | 176 -- .../EventDelegateSecurityTest.java | 289 ---- .../eventService/EventManagerTest.java | 221 --- .../management/eventService/FetchingTest.java | 276 ---- .../LeaseManagerDeadlockTest.java | 98 -- .../management/eventService/LeaseTest.java | 361 ---- .../management/eventService/ListenerTest.java | 224 --- .../MyFetchingEventForwarder.java | 53 - .../NotSerializableNotifTest.java | 227 --- .../management/eventService/PublishTest.java | 184 --- .../ReconnectableConnectorTest.java | 488 ------ .../eventService/SharingThreadTest.java | 365 ----- .../management/eventService/SubUnsubTest.java | 125 -- .../eventService/SubscribeTest.java | 127 -- .../eventService/UsingEventService.java | 107 -- .../interop/MBeanExceptionInteropTest.java | 166 -- .../DefaultDescriptorFieldTest.java | 354 ---- .../AttributeArbitraryDataTypeTest.java | 41 + .../InstantiateMonitorNotificationTest.java | 52 - .../management/mxbean/CustomTypeTest.java | 642 -------- .../mxbean/ExceptionDiagnosisTest.java | 24 +- .../management/mxbean/JMXServiceURLTest.java | 216 --- .../mxbean/customtypes/CustomLongMXBean.java | 31 - .../mxbean/customtypes/CustomMXBean.java | 30 - .../customtypes/IntegerIsLongFactory.java | 74 - .../customtypes/IntegerIsStringFactory.java | 76 - .../mxbean/customtypes/package-info.java | 27 - .../namespace/DomainCreationTest.java | 330 ---- .../EventWithNamespaceControlTest.java | 94 -- .../namespace/EventWithNamespaceTest.java | 241 --- .../namespace/ExportNamespaceTest.java | 100 -- .../management/namespace/JMXDomainTest.java | 513 ------ .../namespace/JMXNamespaceSecurityTest.java | 274 ---- .../namespace/JMXNamespaceTest.java | 511 ------ .../namespace/JMXNamespaceViewTest.java | 546 ------- .../namespace/JMXNamespacesTest.java | 648 -------- .../namespace/JMXRemoteNamespaceTest.java | 190 --- .../namespace/JMXRemoteTargetNamespace.java | 216 --- .../management/namespace/LazyDomainTest.java | 790 --------- .../namespace/LeadingSeparatorsTest.java | 238 --- .../management/namespace/MXBeanRefTest.java | 181 --- .../namespace/NamespaceController.java | 405 ----- .../namespace/NamespaceControllerMBean.java | 143 -- .../namespace/NamespaceCreationTest.java | 263 --- .../namespace/NamespaceNotificationsTest.java | 381 ----- .../namespace/NullDomainObjectNameTest.java | 307 ---- .../namespace/NullObjectNameTest.java | 273 ---- .../management/namespace/QueryNamesTest.java | 473 ------ .../RemoveNotificationListenerTest.java | 377 ----- .../namespace/RoutingServerProxyTest.java | 400 ----- .../namespace/SerialParamProcessorTest.java | 572 ------- .../namespace/SourceNamespaceTest.java | 141 -- .../namespace/VirtualMBeanNotifTest.java | 569 ------- .../namespace/VirtualMBeanTest.java | 409 ----- .../namespace/VirtualNamespaceQueryTest.java | 128 -- .../namespace/VirtualPropsTest.java | 179 -- test/javax/management/namespace/Wombat.java | 259 --- .../management/namespace/WombatMBean.java | 59 - .../management/namespace/namespace.policy | 85 - .../notification/SupportClearTest.java | 80 - .../openmbean/CompositeDataToMapTest.java | 116 -- .../openmbean/GenericMBeanExceptionTest.java | 278 ---- .../management/query/QueryDottedAttrTest.java | 192 --- .../management/query/QueryExpStringTest.java | 4 - .../query/QueryNotifFilterTest.java | 347 ---- .../management/query/QueryParseTest.java | 781 --------- .../mandatory/connection/CloseServerTest.java | 75 +- .../mandatory/connection/DeadLockTest.java | 6 +- .../mandatory/connection/IdleTimeoutTest.java | 12 +- .../mandatory/connection/RMIExitTest.java | 15 +- .../mandatory/connection/ReconnectTest.java | 5 +- .../connectorServer/CloseConnectionTest.java | 217 --- .../connectorServer/ForwarderChainTest.java | 279 ---- .../StandardForwardersTest.java | 193 --- .../mandatory/loading/MissingClassTest.java | 13 +- .../remote/mandatory/notif/AddRemoveTest.java | 22 +- .../remote/mandatory/notif/DiffHBTest.java | 26 +- .../notif/EmptyDomainNotificationTest.java | 26 +- .../mandatory/notif/ListenerScaleTest.java | 13 +- .../NotifBufferSizePropertyNameTest.java | 7 +- .../notif/NotifReconnectDeadlockTest.java | 2 - .../notif/NotificationBufferCreationTest.java | 7 +- .../notif/NotificationBufferDeadlockTest.java | 18 +- .../notif/NotificationEmissionTest.java | 59 +- .../remote/mandatory/notif/RMINotifTest.java | 19 +- .../mandatory/notif/UnexpectedNotifTest.java | 17 +- .../mandatory/version/JMXSpecVersionTest.java | 308 ---- .../standardmbean/FindMethodTest.java | 384 ----- .../standardmbean/RegistrationTest.java | 91 -- 294 files changed, 1232 insertions(+), 57290 deletions(-) delete mode 100644 src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java delete mode 100644 src/share/classes/com/sun/jmx/event/EventBuffer.java delete mode 100644 src/share/classes/com/sun/jmx/event/EventClientFactory.java delete mode 100644 src/share/classes/com/sun/jmx/event/EventConnection.java delete mode 100644 src/share/classes/com/sun/jmx/event/EventParams.java delete mode 100644 src/share/classes/com/sun/jmx/event/LeaseManager.java delete mode 100644 src/share/classes/com/sun/jmx/event/LeaseRenewer.java delete mode 100644 src/share/classes/com/sun/jmx/event/ReceiverBuffer.java delete mode 100644 src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java delete mode 100644 src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java delete mode 100644 src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java delete mode 100644 src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java delete mode 100644 src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java delete mode 100644 src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java delete mode 100644 src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java rename src/share/classes/{javax/management/openmbean => com/sun/jmx/mbeanserver}/MXBeanMapping.java (97%) rename src/share/classes/{javax/management/openmbean => com/sun/jmx/mbeanserver}/MXBeanMappingFactory.java (72%) delete mode 100644 src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java delete mode 100644 src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java delete mode 100644 src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/RoutingProxy.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/package.html delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java delete mode 100644 src/share/classes/com/sun/jmx/namespace/serial/package.html delete mode 100644 src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java delete mode 100644 src/share/classes/javax/management/ClientContext.java delete mode 100644 src/share/classes/javax/management/Description.java delete mode 100644 src/share/classes/javax/management/DescriptorFields.java delete mode 100644 src/share/classes/javax/management/DynamicWrapperMBean.java delete mode 100644 src/share/classes/javax/management/GenericMBeanException.java delete mode 100644 src/share/classes/javax/management/Impact.java delete mode 100644 src/share/classes/javax/management/MBean.java delete mode 100644 src/share/classes/javax/management/ManagedAttribute.java delete mode 100644 src/share/classes/javax/management/ManagedOperation.java delete mode 100644 src/share/classes/javax/management/NotificationInfo.java delete mode 100644 src/share/classes/javax/management/NotificationInfos.java delete mode 100644 src/share/classes/javax/management/ObjectNameTemplate.java delete mode 100644 src/share/classes/javax/management/QueryNotificationFilter.java delete mode 100644 src/share/classes/javax/management/QueryParser.java delete mode 100644 src/share/classes/javax/management/SendNotification.java delete mode 100644 src/share/classes/javax/management/event/EventClient.java delete mode 100644 src/share/classes/javax/management/event/EventClientDelegate.java delete mode 100644 src/share/classes/javax/management/event/EventClientDelegateMBean.java delete mode 100644 src/share/classes/javax/management/event/EventClientNotFoundException.java delete mode 100644 src/share/classes/javax/management/event/EventConsumer.java delete mode 100644 src/share/classes/javax/management/event/EventForwarder.java delete mode 100644 src/share/classes/javax/management/event/EventReceiver.java delete mode 100644 src/share/classes/javax/management/event/EventRelay.java delete mode 100644 src/share/classes/javax/management/event/EventSubscriber.java delete mode 100644 src/share/classes/javax/management/event/FetchingEventForwarder.java delete mode 100644 src/share/classes/javax/management/event/FetchingEventRelay.java delete mode 100644 src/share/classes/javax/management/event/ListenerInfo.java delete mode 100644 src/share/classes/javax/management/event/NotificationManager.java delete mode 100644 src/share/classes/javax/management/event/RMIPushEventForwarder.java delete mode 100644 src/share/classes/javax/management/event/RMIPushEventRelay.java delete mode 100644 src/share/classes/javax/management/event/RMIPushServer.java delete mode 100644 src/share/classes/javax/management/event/package-info.java delete mode 100644 src/share/classes/javax/management/namespace/JMXDomain.java delete mode 100644 src/share/classes/javax/management/namespace/JMXNamespace.java delete mode 100644 src/share/classes/javax/management/namespace/JMXNamespaceMBean.java delete mode 100644 src/share/classes/javax/management/namespace/JMXNamespacePermission.java delete mode 100644 src/share/classes/javax/management/namespace/JMXNamespaceView.java delete mode 100644 src/share/classes/javax/management/namespace/JMXNamespaces.java delete mode 100644 src/share/classes/javax/management/namespace/JMXRemoteNamespace.java delete mode 100644 src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java delete mode 100644 src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java delete mode 100644 src/share/classes/javax/management/namespace/MBeanServerSupport.java delete mode 100644 src/share/classes/javax/management/namespace/VirtualEventManager.java delete mode 100644 src/share/classes/javax/management/namespace/package-info.java delete mode 100644 src/share/classes/javax/management/openmbean/MXBeanMappingClass.java delete mode 100644 src/share/classes/javax/management/openmbean/MXBeanMappingFactoryClass.java delete mode 100644 src/share/classes/javax/management/remote/IdentityMBeanServerForwarder.java delete mode 100644 test/javax/management/Introspector/AnnotatedMBeanTest.java delete mode 100644 test/javax/management/Introspector/AnnotatedNotificationInfoTest.java delete mode 100644 test/javax/management/Introspector/ExceptionsDescriptorTest.java delete mode 100644 test/javax/management/Introspector/MBeanDescriptionTest.java delete mode 100644 test/javax/management/Introspector/ObjectNameTemplateTest.java delete mode 100644 test/javax/management/Introspector/ParameterNameTest.java delete mode 100644 test/javax/management/Introspector/ResourceInjectionTest.java delete mode 100644 test/javax/management/MBeanServer/AttributeListMapTest.java delete mode 100644 test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java delete mode 100644 test/javax/management/MBeanServer/InstanceNotFoundExceptionTest.java delete mode 100644 test/javax/management/MBeanServerFactory/NamedMBeanServerTest.java delete mode 100644 test/javax/management/ObjectName/ValueOfTest.java delete mode 100644 test/javax/management/context/ContextForwarderTest.java delete mode 100644 test/javax/management/context/ContextTest.java delete mode 100644 test/javax/management/context/LocaleAwareBroadcasterTest.java delete mode 100644 test/javax/management/context/LocaleTest.java delete mode 100644 test/javax/management/context/LocalizableTest.java delete mode 100644 test/javax/management/context/RemoteContextTest.java delete mode 100644 test/javax/management/context/localizable/MBeanDescriptions.properties delete mode 100644 test/javax/management/context/localizable/MBeanDescriptions_fr.java delete mode 100644 test/javax/management/context/localizable/Whatsit.java delete mode 100644 test/javax/management/context/localizable/WhatsitMBean.java delete mode 100644 test/javax/management/descriptor/DescriptorConstructorTest.java delete mode 100644 test/javax/management/eventService/AddRemoveListenerTest.java delete mode 100644 test/javax/management/eventService/CustomForwarderTest.java delete mode 100644 test/javax/management/eventService/EventClientExecutorTest.java delete mode 100644 test/javax/management/eventService/EventClientThreadTest.java delete mode 100644 test/javax/management/eventService/EventDelegateSecurityTest.java delete mode 100644 test/javax/management/eventService/EventManagerTest.java delete mode 100644 test/javax/management/eventService/FetchingTest.java delete mode 100644 test/javax/management/eventService/LeaseManagerDeadlockTest.java delete mode 100644 test/javax/management/eventService/LeaseTest.java delete mode 100644 test/javax/management/eventService/ListenerTest.java delete mode 100644 test/javax/management/eventService/MyFetchingEventForwarder.java delete mode 100644 test/javax/management/eventService/NotSerializableNotifTest.java delete mode 100644 test/javax/management/eventService/PublishTest.java delete mode 100644 test/javax/management/eventService/ReconnectableConnectorTest.java delete mode 100644 test/javax/management/eventService/SharingThreadTest.java delete mode 100644 test/javax/management/eventService/SubUnsubTest.java delete mode 100644 test/javax/management/eventService/SubscribeTest.java delete mode 100644 test/javax/management/eventService/UsingEventService.java delete mode 100644 test/javax/management/interop/MBeanExceptionInteropTest.java delete mode 100644 test/javax/management/modelmbean/DefaultDescriptorFieldTest.java delete mode 100644 test/javax/management/monitor/InstantiateMonitorNotificationTest.java delete mode 100644 test/javax/management/mxbean/CustomTypeTest.java delete mode 100644 test/javax/management/mxbean/JMXServiceURLTest.java delete mode 100644 test/javax/management/mxbean/customtypes/CustomLongMXBean.java delete mode 100644 test/javax/management/mxbean/customtypes/CustomMXBean.java delete mode 100644 test/javax/management/mxbean/customtypes/IntegerIsLongFactory.java delete mode 100644 test/javax/management/mxbean/customtypes/IntegerIsStringFactory.java delete mode 100644 test/javax/management/mxbean/customtypes/package-info.java delete mode 100644 test/javax/management/namespace/DomainCreationTest.java delete mode 100644 test/javax/management/namespace/EventWithNamespaceControlTest.java delete mode 100644 test/javax/management/namespace/EventWithNamespaceTest.java delete mode 100644 test/javax/management/namespace/ExportNamespaceTest.java delete mode 100644 test/javax/management/namespace/JMXDomainTest.java delete mode 100644 test/javax/management/namespace/JMXNamespaceSecurityTest.java delete mode 100644 test/javax/management/namespace/JMXNamespaceTest.java delete mode 100644 test/javax/management/namespace/JMXNamespaceViewTest.java delete mode 100644 test/javax/management/namespace/JMXNamespacesTest.java delete mode 100644 test/javax/management/namespace/JMXRemoteNamespaceTest.java delete mode 100644 test/javax/management/namespace/JMXRemoteTargetNamespace.java delete mode 100644 test/javax/management/namespace/LazyDomainTest.java delete mode 100644 test/javax/management/namespace/LeadingSeparatorsTest.java delete mode 100644 test/javax/management/namespace/MXBeanRefTest.java delete mode 100644 test/javax/management/namespace/NamespaceController.java delete mode 100644 test/javax/management/namespace/NamespaceControllerMBean.java delete mode 100644 test/javax/management/namespace/NamespaceCreationTest.java delete mode 100644 test/javax/management/namespace/NamespaceNotificationsTest.java delete mode 100644 test/javax/management/namespace/NullDomainObjectNameTest.java delete mode 100644 test/javax/management/namespace/NullObjectNameTest.java delete mode 100644 test/javax/management/namespace/QueryNamesTest.java delete mode 100644 test/javax/management/namespace/RemoveNotificationListenerTest.java delete mode 100644 test/javax/management/namespace/RoutingServerProxyTest.java delete mode 100644 test/javax/management/namespace/SerialParamProcessorTest.java delete mode 100644 test/javax/management/namespace/SourceNamespaceTest.java delete mode 100644 test/javax/management/namespace/VirtualMBeanNotifTest.java delete mode 100644 test/javax/management/namespace/VirtualMBeanTest.java delete mode 100644 test/javax/management/namespace/VirtualNamespaceQueryTest.java delete mode 100644 test/javax/management/namespace/VirtualPropsTest.java delete mode 100644 test/javax/management/namespace/Wombat.java delete mode 100644 test/javax/management/namespace/WombatMBean.java delete mode 100644 test/javax/management/namespace/namespace.policy delete mode 100644 test/javax/management/notification/SupportClearTest.java delete mode 100644 test/javax/management/openmbean/CompositeDataToMapTest.java delete mode 100644 test/javax/management/openmbean/GenericMBeanExceptionTest.java delete mode 100644 test/javax/management/query/QueryDottedAttrTest.java delete mode 100644 test/javax/management/query/QueryNotifFilterTest.java delete mode 100644 test/javax/management/query/QueryParseTest.java delete mode 100644 test/javax/management/remote/mandatory/connectorServer/CloseConnectionTest.java delete mode 100644 test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java delete mode 100644 test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java delete mode 100644 test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java delete mode 100644 test/javax/management/standardmbean/FindMethodTest.java delete mode 100644 test/javax/management/standardmbean/RegistrationTest.java diff --git a/make/docs/CORE_PKGS.gmk b/make/docs/CORE_PKGS.gmk index 3694985b1..9369fb0c6 100644 --- a/make/docs/CORE_PKGS.gmk +++ b/make/docs/CORE_PKGS.gmk @@ -160,10 +160,8 @@ CORE_PKGS = \ 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 \ diff --git a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java index fcf769bf6..89cd5bf16 100644 --- a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java +++ b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java @@ -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 @@ -176,18 +176,6 @@ public class JmxProperties { public static final String RELATION_LOGGER_NAME = "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. */ diff --git a/src/share/classes/com/sun/jmx/defaults/ServiceName.java b/src/share/classes/com/sun/jmx/defaults/ServiceName.java index cc851e67e..7eea67f4b 100644 --- a/src/share/classes/com/sun/jmx/defaults/ServiceName.java +++ b/src/share/classes/com/sun/jmx/defaults/ServiceName.java @@ -69,9 +69,9 @@ public class ServiceName { /** * The version of the JMX specification implemented by this product. *
- * The value is 2.0. + * The value is 1.4. */ - 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. diff --git a/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java b/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java deleted file mode 100644 index ca2462b32..000000000 --- a/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java +++ /dev/null @@ -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"); -} diff --git a/src/share/classes/com/sun/jmx/event/EventBuffer.java b/src/share/classes/com/sun/jmx/event/EventBuffer.java deleted file mode 100644 index ed8047910..000000000 --- a/src/share/classes/com/sun/jmx/event/EventBuffer.java +++ /dev/null @@ -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()); - } - - public EventBuffer(int capacity, final List 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 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 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"); -} diff --git a/src/share/classes/com/sun/jmx/event/EventClientFactory.java b/src/share/classes/com/sun/jmx/event/EventClientFactory.java deleted file mode 100644 index 3cab63ccd..000000000 --- a/src/share/classes/com/sun/jmx/event/EventClientFactory.java +++ /dev/null @@ -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(); - -} diff --git a/src/share/classes/com/sun/jmx/event/EventConnection.java b/src/share/classes/com/sun/jmx/event/EventConnection.java deleted file mode 100644 index adadef193..000000000 --- a/src/share/classes/com/sun/jmx/event/EventConnection.java +++ /dev/null @@ -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); - } - } -} diff --git a/src/share/classes/com/sun/jmx/event/EventParams.java b/src/share/classes/com/sun/jmx/event/EventParams.java deleted file mode 100644 index c0e76634c..000000000 --- a/src/share/classes/com/sun/jmx/event/EventParams.java +++ /dev/null @@ -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"); -} diff --git a/src/share/classes/com/sun/jmx/event/LeaseManager.java b/src/share/classes/com/sun/jmx/event/LeaseManager.java deleted file mode 100644 index 2db6fea14..000000000 --- a/src/share/classes/com/sun/jmx/event/LeaseManager.java +++ /dev/null @@ -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; - -/** - *

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.

- * @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); - } - - /** - *

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.

- * - *

Calling this method after the lease has expired will return zero - * immediately and have no other effect.

- * - * @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; - } - - /** - *

Cancel the lease without calling the expiry callback.

- */ - 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"); - -} diff --git a/src/share/classes/com/sun/jmx/event/LeaseRenewer.java b/src/share/classes/com/sun/jmx/event/LeaseRenewer.java deleted file mode 100644 index 8ba687722..000000000 --- a/src/share/classes/com/sun/jmx/event/LeaseRenewer.java +++ /dev/null @@ -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 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 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"); -} diff --git a/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java b/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java deleted file mode 100644 index a87e2dfd6..000000000 --- a/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java +++ /dev/null @@ -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 notifList - = new ArrayList(); - private long start = 0; - private int lost = 0; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "ReceiverBuffer"); -} diff --git a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java b/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java deleted file mode 100644 index 768ed6f30..000000000 --- a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java +++ /dev/null @@ -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; - -/** - *

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()}.

- * @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"); -} diff --git a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java index faa39e765..c959120e4 100644 --- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java +++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java @@ -30,16 +30,15 @@ package com.sun.jmx.interceptor; 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.PrivilegedAction; 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.Attribute; 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.JMRuntimeException; 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.MBeanTrustPermission; 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 @@ import javax.management.namespace.JMXNamespace; * * @since 1.5 */ -public class DefaultMBeanServerInterceptor - extends MBeanServerInterceptorSupport { +public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor { /** The MBeanInstantiator object used by the * DefaultMBeanServerInterceptor */ @@ -142,14 +135,9 @@ public class DefaultMBeanServerInterceptor new WeakHashMap>(); - 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 @@ public class DefaultMBeanServerInterceptor * @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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor new HashSet(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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor new HashSet(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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor List result = new ArrayList(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 @@ public class DefaultMBeanServerInterceptor } 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 @@ public class DefaultMBeanServerInterceptor // 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 @@ public class DefaultMBeanServerInterceptor new ArrayList(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 @@ public class DefaultMBeanServerInterceptor } 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 @@ public class DefaultMBeanServerInterceptor // 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor ResourceContext context = null; try { - mbean = injectResources(mbean, server, logicalName); - if (mbean instanceof DynamicMBean2) { try { ((DynamicMBean2) mbean).preRegister2(server, logicalName); @@ -973,8 +943,7 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor // 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor } 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor } DynamicMBean instance = getMBean(name); - checkMBeanPermission(mbeanServerName, instance, null, - name, "addNotificationListener"); + checkMBeanPermission(instance, null, name, "addNotificationListener"); NotificationBroadcaster broadcaster = getNotificationBroadcaster(name, instance, @@ -1381,8 +1320,7 @@ public class DefaultMBeanServerInterceptor } 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 @@ public class DefaultMBeanServerInterceptor Class 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 class DefaultMBeanServerInterceptor } } + 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 @@ public class DefaultMBeanServerInterceptor 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 @@ public class DefaultMBeanServerInterceptor 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 = @@ -1995,56 +1955,6 @@ public class DefaultMBeanServerInterceptor } - /** - * 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 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 postQueue) { - dispatcher.removeInterceptorFor(logicalName, namespace, postQueue); - } - /** * Registers a ClassLoader with the CLR. * This method is called by the ResourceContext from within the @@ -2099,51 +2009,6 @@ public class DefaultMBeanServerInterceptor } - /** - * 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 doneTaskQueue = new LinkedList(); - 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 @@ -2180,8 +2045,7 @@ public class DefaultMBeanServerInterceptor * 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 @@ public class DefaultMBeanServerInterceptor */ 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); diff --git a/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java b/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java deleted file mode 100644 index f68e539d2..000000000 --- a/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java +++ /dev/null @@ -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. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @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 - - 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 { - abstract Set query(MBeanServer mbs, - ObjectName pattern, QueryExp query); - } - - /** - * Used to perform queryNames. A QueryInvoker that invokes - * queryNames on an MBeanServer. - **/ - final static QueryInvoker queryNamesInvoker = - new QueryInvoker() { - Set 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 queryMBeansInvoker = - new QueryInvoker() { - Set 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; - } - Set query(ObjectName pattern, QueryExp query, - QueryInvoker invoker, MBeanServer server) { - return invoker.query(server, pattern, query); - } - - public Set queryNames(ObjectName pattern, QueryExp query) { - return query(pattern,query,queryNamesInvoker,wrapped); - } - - public Set 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 handlerMap = - Collections.synchronizedMap( - new HashMap()); - - // 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 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 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 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 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 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 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); - } - -} diff --git a/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java b/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java deleted file mode 100644 index 388af6b21..000000000 --- a/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java +++ /dev/null @@ -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. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// -// See comments in DispatchInterceptor. -// -class DomainDispatchInterceptor - extends DispatchInterceptor { - - /** - * 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 - Set query(ObjectName pattern, QueryExp query, - QueryInvoker invoker, MBeanServer localNamespace) { - final Set local = invoker.query(localNamespace, pattern, query); - - // Add all matching MBeans from local namespace. - final Set 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 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 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; - } -} diff --git a/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java b/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java deleted file mode 100644 index 8e1cf681e..000000000 --- a/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java +++ /dev/null @@ -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}. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @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."); - } - -} diff --git a/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java b/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java deleted file mode 100644 index 5ab61f893..000000000 --- a/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java +++ /dev/null @@ -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. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class NamespaceDispatchInterceptor - extends DispatchInterceptor { - - /** - * 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. - *

Do not forget to call initialize(outer,delegate) - * 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: - *

-     *  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                      ->      ""
-     *
-     * 
- **/ - 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 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 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 postDeregisterQueue) { - if (handler instanceof JMXDomain) - nextInterceptor.removeInterceptorFor(name,(JMXDomain)handler, - postDeregisterQueue); - else super.removeInterceptorFor(name,handler,postDeregisterQueue); - } - - -} diff --git a/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java b/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java deleted file mode 100644 index cfb400925..000000000 --- a/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java +++ /dev/null @@ -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; - -/** - *

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.

- */ -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 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 domainSet = new TreeSet(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 queryMBeans(ObjectName name, QueryExp query) { - Set 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 queryNames(ObjectName name, QueryExp query) { - Set 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); - } -} diff --git a/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java b/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java index 62239b5a9..37596dff2 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java @@ -31,15 +31,13 @@ import java.lang.reflect.Type; 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 @@ final class ConvertingMethod { } Descriptor getDescriptor() { - return Introspector.descriptorForElement(method, false); + return Introspector.descriptorForElement(method); } Type getGenericReturnType() { @@ -206,9 +204,9 @@ final class ConvertingMethod { 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(); diff --git a/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java index 1b653c28e..99b3ce30d 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java @@ -28,8 +28,6 @@ package com.sun.jmx.mbeanserver; 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.CompositeDataInvocationHandler; 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 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { private static final class Mappings extends WeakHashMap> {} - private static final Map factoryMappings = - new WeakHashMap(); + private static final Mappings mappings = new Mappings(); - private static final Map permanentMappings = newMap(); + /** Following List simply serves to keep a reference to predefined + MXBeanMappings so they don't get garbage collected. */ + private static final List permanentMappings = newList(); - private static synchronized MXBeanMapping getMapping( - Type type, MXBeanMappingFactory factory) { - Mappings mappings = factoryMappings.get(factory); - if (mappings == null) { - mappings = new Mappings(); - factoryMappings.put(factory, mappings); - } + private static synchronized MXBeanMapping getMapping(Type type) { WeakReference 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 wr = new WeakReference(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 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { 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 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { 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 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { 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 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { MXBeanMapping mapping; - mapping = getMapping(objType, null); + mapping = getMapping(objType); if (mapping != null) return mapping; @@ -268,7 +259,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { inProgress.remove(objType); } - putMapping(objType, mapping, factory); + putMapping(objType, mapping); return mapping; } @@ -278,14 +269,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { /* 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 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { throw new OpenDataException("Cannot map type: " + objType); } - private static MXBeanMapping - makeAnnotationMapping(MXBeanMappingClass mappingClass, - Type objType, - MXBeanMappingFactory factory) - throws OpenDataException { - Class c = mappingClass.value(); - Constructor 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 or ) - * and since we don't treat this as Foo elsewhere we shouldn't here. - */ - return Object.class; - } - private static > MXBeanMapping makeEnumMapping(Class enumClass, Class fake) { return new EnumMapping(Util.>cast(enumClass)); diff --git a/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java b/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java index d67b16607..49d49ce4c 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java @@ -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 @@ import javax.management.ObjectName; * * @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(). diff --git a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java index ba27f6e83..09b5701a9 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java @@ -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.lang.reflect.UndeclaredThrowableException; 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 @@ import javax.management.openmbean.MXBeanMappingFactory; */ 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 class Introspector { 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 @@ public class Introspector { } 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); } - /** - *

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}.

- * @param mbean the object to convert to a DynamicMBean. - * @param 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 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 @@ public class Introspector { // 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 @@ public class Introspector { 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 class Introspector { */ public static Class getStandardMBeanInterface(Class baseClass) throws NotCompliantMBeanException { - if (baseClass.isAnnotationPresent(MBean.class)) - return baseClass; Class current = baseClass; Class mbeanInterface = null; while (current != null) { @@ -384,8 +318,6 @@ public class Introspector { */ public static Class getMXBeanInterface(Class baseClass) throws NotCompliantMBeanException { - if (hasMXBeanAnnotation(baseClass)) - return baseClass; try { return MXBeanSupport.findMXBeanInterface(baseClass); } catch (Exception e) { @@ -393,61 +325,12 @@ public class Introspector { } } - public static Class getStandardOrMXBeanInterface( - Class 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 @@ public class Introspector { 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 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 @@ public class Introspector { return ImmutableDescriptor.EMPTY_DESCRIPTOR; Map descriptorMap = new HashMap(); for (Annotation a : annots) { - if (a instanceof DescriptorFields) - addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a); - addAnnotationFieldsToMap(descriptorMap, a); + Class 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()) @@ -558,76 +402,6 @@ public class Introspector { return new ImmutableDescriptor(descriptorMap); } - /** - * 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 set = new LinkedHashSet(); - for(Classex : exceptions) - set.add(ex.getName()); - - String[] arr = new String[set.size()]; - return set.toArray(arr); - } - - private static void addDescriptorFieldsToMap( - Map 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 descriptorMap, Annotation a) { - Class 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 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 diff --git a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java index 4fc25e912..cffae5343 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java @@ -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 @@ public final class JmxMBeanServer /** The MBeanServerDelegate object representing the MBean Server */ private final MBeanServerDelegate mBeanServerDelegateObject; - private final String mbeanServerName; - /** * Package: Creates an MBeanServer with the * specified default domain name, outer interface, and delegate. @@ -241,10 +239,9 @@ public final class JmxMBeanServer 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 @@ public final class JmxMBeanServer throws ReflectionException, MBeanException { /* Permission check */ - checkMBeanPermission(mbeanServerName, className, null, null, - "instantiate"); + checkMBeanPermission(className, null, null, "instantiate"); return instantiator.instantiate(className); } @@ -978,8 +974,7 @@ public final class JmxMBeanServer 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 @@ public final class JmxMBeanServer 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 @@ public final class JmxMBeanServer 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 final class JmxMBeanServer **/ public ClassLoaderRepository getClassLoaderRepository() { /* Permission check */ - checkMBeanPermission(mbeanServerName, null, null, - null, "getClassLoaderRepository"); + checkMBeanPermission(null, null, null, "getClassLoaderRepository"); return secureClr; } @@ -1487,16 +1479,14 @@ public final class JmxMBeanServer // 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); diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java b/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java index e6f7e1f94..2619e29c7 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java @@ -33,10 +33,6 @@ import java.util.Comparator; 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 @@ import javax.management.NotCompliantMBeanException; */ class MBeanAnalyzer { - static interface MBeanVisitor { + static interface MBeanVisitor { public void visitAttribute(String attributeName, M getter, - M setter) throws X; + M setter); public void visitOperation(String operationName, - M operation) throws X; + M operation); } - void visit(MBeanVisitor visitor) throws X { + void visit(MBeanVisitor visitor) { // visit attributes for (Map.Entry> entry : attrMap.entrySet()) { String name = entry.getKey(); @@ -108,7 +104,10 @@ class MBeanAnalyzer { private MBeanAnalyzer(Class mbeanType, MBeanIntrospector 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 @@ class MBeanAnalyzer { 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 am = attrMap.get(attrName); @@ -165,7 +156,7 @@ class MBeanAnalyzer { 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 am = attrMap.get(attrName); @@ -178,9 +169,6 @@ class MBeanAnalyzer { } 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 cms = opMap.get(name); diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java deleted file mode 100644 index 4917d089e..000000000 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java +++ /dev/null @@ -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, List> fields; - private Map, List> 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); - } - - void inject(Object instance, Class type, T resource) - throws Exception { - List fs = fields.get(type); - if (fs != null) { - for (Field f : fs) - f.set(instance, resource); - } - List 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, List> entry : methods.entrySet()) { - List 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() { - 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() { - public Void run() { - member.setAccessible(true); - return null; - } - }); - addToMap(fields, injectedClass, field); - addToMap(methods, injectedClass, method); - } - } - } - } - } - - private static void addToMap(Map> map, K key, V value) { - if (value == null) - return; - List list = map.get(key); - if (list == null) - list = Collections.singletonList(value); - else { - if (list.size() == 1) - list = new ArrayList(list); - list.add(value); - } - map.put(key, list); - } - } - - private static synchronized ClassInjector injectorForClass(Class c) - throws NotCompliantMBeanException { - WeakReference wr = injectorMap.get(c); - ClassInjector ci = (wr == null) ? null : wr.get(); - if (ci == null) { - ci = new ClassInjector(c); - injectorMap.put(c, new WeakReference(ci)); - } - return ci; - } - - private static Map, WeakReference> injectorMap = - new WeakHashMap, WeakReference>(); -} diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java index f3bd67e2f..992eba314 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java @@ -613,15 +613,6 @@ public class MBeanInstantiator { return clr; } - /** - * 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. diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java b/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java index e98b41bba..9edde66fa 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java @@ -36,28 +36,20 @@ import java.lang.reflect.Method; 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 @@ import javax.management.ReflectionException; * ancestor with ConvertingMethod. But that would mean an extra object * for every Method in every Standard MBean interface. */ -public abstract class MBeanIntrospector { +abstract class MBeanIntrospector { static final class PerInterfaceMap extends WeakHashMap, WeakReference>> {} @@ -159,27 +151,7 @@ public abstract class MBeanIntrospector { * 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. @@ -200,37 +172,11 @@ public abstract class MBeanIntrospector { */ 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 getMethods(final Class mbeanType) throws Exception { - if (mbeanType.isInterface()) - return Arrays.asList(mbeanType.getMethods()); - - final List methods = newList(); - getAnnotatedMethods(mbeanType, methods); - return methods; + return Arrays.asList(mbeanType.getMethods()); } final PerInterface getPerInterface(Class mbeanInterface) @@ -265,14 +211,11 @@ public abstract class MBeanIntrospector { * the MBeanInfo's Descriptor. */ private MBeanInfo makeInterfaceMBeanInfo(Class mbeanInterface, - MBeanAnalyzer analyzer) throws IntrospectionException { + MBeanAnalyzer 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 @@ public abstract class MBeanIntrospector { /** A visitor that constructs the per-interface MBeanInfo. */ private class MBeanInfoMaker - implements MBeanAnalyzer.MBeanVisitor { + implements MBeanAnalyzer.MBeanVisitor { public void visitAttribute(String attributeName, M getter, - M setter) throws IntrospectionException { + M setter) { MBeanAttributeInfo mbai = getMBeanAttributeInfo(attributeName, getter, setter); @@ -403,7 +346,7 @@ public abstract class MBeanIntrospector { 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 @@ public abstract class MBeanIntrospector { * Return the MBeanInfo for the given resource, based on the given * per-interface data. */ - final MBeanInfo getMBeanInfo(Object resource, PerInterface perInterface) - throws NotCompliantMBeanException { + final MBeanInfo getMBeanInfo(Object resource, PerInterface 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 @@ public abstract class MBeanIntrospector { } } - /* - * 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 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); - } - } - return findNotificationsFromAnnotations(moi.getClass()); - } - - public static MBeanNotificationInfo[] findNotificationsFromAnnotations( - Class mbeanClass) { - Class c = getAnnotatedNotificationInfoClass(mbeanClass); - if (c == null) + if (!(moi instanceof NotificationBroadcaster)) return null; - NotificationInfo ni = c.getAnnotation(NotificationInfo.class); - NotificationInfos nis = c.getAnnotation(NotificationInfos.class); - List list = newList(); - if (ni != null) - list.add(ni); - if (nis != null) - list.addAll(Arrays.asList(nis.value())); - if (list.isEmpty()) + MBeanNotificationInfo[] mbn = + ((NotificationBroadcaster) moi).getNotificationInfo(); + if (mbn == null) return null; - List 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, WeakReference>> - annotatedNotificationInfoClasses = newWeakHashMap(); - - private static Class getAnnotatedNotificationInfoClass(Class baseClass) { - synchronized (annotatedNotificationInfoClasses) { - WeakReference> 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>(c)); - return c; + MBeanNotificationInfo[] result = + new MBeanNotificationInfo[mbn.length]; + for (int i = 0; i < mbn.length; i++) { + MBeanNotificationInfo ni = mbn[i]; + if (ni.getClass() != MBeanNotificationInfo.class) + ni = (MBeanNotificationInfo) ni.clone(); + result[i] = ni; } + return result; } private static MBeanConstructorInfo[] findConstructors(Class c) { Constructor[] cons = c.getConstructors(); MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length]; for (int i = 0; i < cons.length; i++) { - 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; diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java index 20a776534..c5ad4e735 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java @@ -37,7 +37,7 @@ import javax.management.MBeanServer; 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 @@ import javax.management.openmbean.MXBeanMappingFactory; public abstract class MBeanSupport implements DynamicMBean2, MBeanRegistration { - MBeanSupport(T resource, Class mbeanInterfaceType, - MXBeanMappingFactory mappingFactory) + MBeanSupport(T resource, Class mbeanInterfaceType) throws NotCompliantMBeanException { if (mbeanInterfaceType == null) throw new NotCompliantMBeanException("Null MBean interface"); @@ -133,14 +132,13 @@ public abstract class MBeanSupport throw new NotCompliantMBeanException(msg); } this.resource = resource; - MBeanIntrospector introspector = getMBeanIntrospector(mappingFactory); + MBeanIntrospector introspector = getMBeanIntrospector(); this.perInterface = introspector.getPerInterface(mbeanInterfaceType); this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface); } /** Return the appropriate introspector for this type of MBean. */ - abstract MBeanIntrospector - getMBeanIntrospector(MXBeanMappingFactory mappingFactory); + abstract MBeanIntrospector getMBeanIntrospector(); /** * Return a cookie for this MBean. This cookie will be passed to @@ -262,14 +260,10 @@ public abstract class MBeanSupport 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(); } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java index fb9b3ccb0..ea326f394 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java @@ -28,26 +28,18 @@ package com.sun.jmx.mbeanserver; import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap; import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap; import java.lang.annotation.Annotation; -import java.lang.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 @@ import javax.management.openmbean.OpenType; * @since 1.6 */ class MXBeanIntrospector extends MBeanIntrospector { - /* 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> map = - new WeakHashMap>(); - - static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) { - if (factory == null) - factory = MXBeanMappingFactory.DEFAULT; - synchronized (map) { - MXBeanIntrospector intro; - WeakReference wr = map.get(factory); - if (wr != null) { - intro = wr.get(); - if (intro != null) - return intro; - } - intro = new MXBeanIntrospector(factory); - wr = new WeakReference(intro); - map.put(factory, wr); - return intro; - } - } + private static final MXBeanIntrospector instance = new MXBeanIntrospector(); - private MXBeanIntrospector(MXBeanMappingFactory factory) { - this.mappingFactory = factory; + static MXBeanIntrospector getInstance() { + return instance; } @Override @@ -115,7 +81,7 @@ class MXBeanIntrospector extends MBeanIntrospector { @Override ConvertingMethod mFrom(Method m) { - return ConvertingMethod.from(m, mappingFactory); + return ConvertingMethod.from(m); } @Override @@ -176,17 +142,13 @@ class MXBeanIntrospector extends MBeanIntrospector { @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 @@ class MXBeanIntrospector extends MBeanIntrospector { 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 @@ class MXBeanIntrospector extends MBeanIntrospector { 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 @@ class MXBeanIntrospector extends MBeanIntrospector { 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 @@ class MXBeanIntrospector extends MBeanIntrospector { 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 @@ class MXBeanIntrospector extends MBeanIntrospector { private final PerInterfaceMap perInterfaceMap = new PerInterfaceMap(); - private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); - - private final MXBeanMappingFactory mappingFactory; + private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java index 605c67f16..9034cdb48 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java @@ -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 @@ import javax.management.openmbean.OpenDataException; * * 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 objectNameToMXBean(ObjectName name, Class 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 weakLookup = mbscToLookup.get(mbsc); - Plain lookup = (weakLookup == null) ? null : weakLookup.get(); - if (lookup == null) { - lookup = new Plain(mbsc); - mbscToLookup.put(mbsc, new WeakReference(lookup)); - } - return lookup; - } - } - - @Override - synchronized T objectNameToMXBean(ObjectName name, Class type) { - WeakReference 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(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 weakLookup = mbscToLookup.get(mbsc); + MXBeanLookup lookup = (weakLookup == null) ? null : weakLookup.get(); + if (lookup == null) { + lookup = new MXBeanLookup(mbsc); + mbscToLookup.put(mbsc, new WeakReference(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. + return lookup; } + } - 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 T objectNameToMXBean(ObjectName name, Class type) { + WeakReference 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(proxy)); + return proxy; + } - synchronized boolean removeReference(ObjectName name, Object mxbean) { - if (name.equals(mxbeanToObjectName.get(mxbean))) { - mxbeanToObjectName.remove(mxbean); - return true; + 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 - return false; - /* removeReference can be called when the above condition fails, - * notably if you try to register the same MXBean twice. - */ + wrong = "not a JMX proxy"; + } else { + ObjectName name = mxbeanToObjectName.get(mxbean); + if (name != null) + return name; + wrong = "not an MXBean registered in this MBeanServer"; } - - private final WeakIdentityHashMap - mxbeanToObjectName = WeakIdentityHashMap.make(); - private final Map> - objectNameToProxy = newMap(); - private static WeakIdentityHashMap> - mbscToLookup = WeakIdentityHashMap.make(); + 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. } - private static class Prefix extends MXBeanLookup { - private final String prefix; - - Prefix(MBeanServerConnection mbsc, String prefix) { - super(mbsc); - this.prefix = prefix; - } - - @Override - T objectNameToMXBean(ObjectName name, Class 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); + 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); } - return name; } + mxbeanToObjectName.put(mxbean, name); } - 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(); - } - return null; + 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 @@ public abstract class MXBeanLookup { private static final ThreadLocal currentLookup = new ThreadLocal(); - final MBeanServerConnection mbsc; + private final MBeanServerConnection mbsc; + private final WeakIdentityHashMap + mxbeanToObjectName = WeakIdentityHashMap.make(); + private final Map> + objectNameToProxy = newMap(); + private static final WeakIdentityHashMap> + mbscToLookup = WeakIdentityHashMap.make(); } diff --git a/src/share/classes/javax/management/openmbean/MXBeanMapping.java b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java similarity index 97% rename from src/share/classes/javax/management/openmbean/MXBeanMapping.java rename to src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java index 339fbb21c..5fb0e0fa3 100644 --- a/src/share/classes/javax/management/openmbean/MXBeanMapping.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java @@ -23,10 +23,12 @@ * have any questions. */ -package javax.management.openmbean; +package com.sun.jmx.mbeanserver; import java.io.InvalidObjectException; import java.lang.reflect.Type; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; /** *

A custom mapping between Java types and Open types for use in MXBeans. @@ -166,12 +168,10 @@ public abstract class MXBeanMapping { if (javaType instanceof Class && ((Class) javaType).isPrimitive()) return (Class) javaType; try { - String className = OpenType.validClassName(openType.getClassName()); + String className = openType.getClassName(); return Class.forName(className, false, null); } catch (ClassNotFoundException e) { throw new RuntimeException(e); // should not happen - } catch (OpenDataException e) { - throw new IllegalArgumentException("Bad OpenType: " + openType, e); } } diff --git a/src/share/classes/javax/management/openmbean/MXBeanMappingFactory.java b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java similarity index 72% rename from src/share/classes/javax/management/openmbean/MXBeanMappingFactory.java rename to src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java index f1dc6bcc0..7aab85555 100644 --- a/src/share/classes/javax/management/openmbean/MXBeanMappingFactory.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java @@ -23,8 +23,10 @@ * have any questions. */ -package javax.management.openmbean; +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; @@ -100,49 +102,6 @@ public abstract class MXBeanMappingFactory { public static final MXBeanMappingFactory DEFAULT = new DefaultMXBeanMappingFactory(); - /** - *

Determine the appropriate MXBeanMappingFactory to use for the given - * MXBean interface, based on its annotations. If the interface has an - * {@link MXBeanMappingFactoryClass @MXBeanMappingFactoryClass} annotation, - * that is used to determine the MXBeanMappingFactory. Otherwise, if the - * package containing the interface has such an annotation, that is used. - * Otherwise the MXBeanMappingFactory is the {@linkplain #DEFAULT default} - * one.

- * - * @param intf the MXBean interface for which to determine the - * MXBeanMappingFactory. - * - * @return the MXBeanMappingFactory for the given MXBean interface. - * - * @throws IllegalArgumentException if {@code intf} is null, or if an - * exception occurs while trying constructing an MXBeanMappingFactory - * based on an annotation. In the second case, the exception will appear - * in the {@linkplain Throwable#getCause() cause chain} of the - * {@code IllegalArgumentException}. - */ - public static MXBeanMappingFactory forInterface(Class intf) { - if (intf == null) - throw new IllegalArgumentException("Null interface"); - MXBeanMappingFactoryClass annot = - intf.getAnnotation(MXBeanMappingFactoryClass.class); - if (annot == null) { - Package p = intf.getPackage(); - if (p != null) - annot = p.getAnnotation(MXBeanMappingFactoryClass.class); - } - if (annot == null) - return MXBeanMappingFactory.DEFAULT; - Class factoryClass = annot.value(); - try { - return annot.value().newInstance(); - } catch (Exception e) { - throw new IllegalArgumentException( - "Could not instantiate MXBeanMappingFactory " + - factoryClass.getName() + - " from @MXBeanMappingFactoryClass", e); - } - } - /** *

Return the mapping for the given Java type. Typically, a * mapping factory will return mappings for types it handles, and diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java index 1ad7598f1..1f2f19ad6 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java @@ -32,10 +32,8 @@ import java.util.Map; 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; /**

Helper class for an {@link InvocationHandler} that forwards methods from an @@ -47,7 +45,7 @@ import javax.management.openmbean.MXBeanMappingFactory; @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 @@ public class MXBeanProxy { final MBeanAnalyzer analyzer; try { analyzer = - MXBeanIntrospector.getInstance(factory).getAnalyzer(mxbeanInterface); + MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } @@ -63,7 +61,7 @@ public class MXBeanProxy { } private class Visitor - implements MBeanAnalyzer.MBeanVisitor { + implements MBeanAnalyzer.MBeanVisitor { public void visitAttribute(String attributeName, ConvertingMethod getter, ConvertingMethod setter) { @@ -161,8 +159,7 @@ public class MXBeanProxy { 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 @@ public class MXBeanProxy { } } - 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 handlerMap = newMap(); } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java index 7a9c5d2e7..9f8b6bebd 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java @@ -35,7 +35,6 @@ import javax.management.JMX; 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 @@ public class MXBeanSupport extends MBeanSupport { if it does not implement the class {@code mxbeanInterface} or if that class is not a valid MXBean interface. */ - public MXBeanSupport(T resource, Class mxbeanInterface, - MXBeanMappingFactory mappingFactory) + public MXBeanSupport(T resource, Class mxbeanInterface) throws NotCompliantMBeanException { - super(resource, mxbeanInterface, mappingFactory); + super(resource, mxbeanInterface); } @Override - MBeanIntrospector - getMBeanIntrospector(MXBeanMappingFactory mappingFactory) { - return MXBeanIntrospector.getInstance(mappingFactory); + MBeanIntrospector getMBeanIntrospector() { + return MXBeanIntrospector.getInstance(); } @Override @@ -159,8 +156,8 @@ public class MXBeanSupport extends MBeanSupport { // 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 class MXBeanSupport extends MBeanSupport { 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; } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java b/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java deleted file mode 100644 index 08964f7dc..000000000 --- a/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java +++ /dev/null @@ -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; - -/** - *

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 NotificationMBeanSupport(T n) - throws NotCompliantMBeanException { - super(n, Util.>cast(n.getClass())); - } - - @Override - MBeanIntrospector getMBeanIntrospector(MXBeanMappingFactory ignored) { - return introspector; - } - - private static class Introspector extends StandardMBeanIntrospector { - @Override - void checkCompliance(Class mbeanType) {} - - @Override - List getMethods(final Class mbeanType) - throws Exception { - List methods = new ArrayList(); - 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 introspector = - new Introspector(); -} diff --git a/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java b/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java deleted file mode 100644 index 00fbb0273..000000000 --- a/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java +++ /dev/null @@ -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; - } -} diff --git a/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java b/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java index 59fd71cdb..d20fe5f52 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java @@ -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 @@ final class PerInterface { /** * Visitor that sets up the method maps (operations, getters, setters). */ - private class InitMaps implements MBeanAnalyzer.MBeanVisitor { + private class InitMaps implements MBeanAnalyzer.MBeanVisitor { public void visitAttribute(String attributeName, M getter, M setter) { diff --git a/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java b/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java deleted file mode 100644 index 2946f16fa..000000000 --- a/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java +++ /dev/null @@ -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; - -/** - *

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.

- */ -// 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 { - private final WeakIdentityHashMap> map = - WeakIdentityHashMap.make(); - - public static interface Create { - public T createThreadPool(ThreadGroup group); - } - - private PerThreadGroupPool() {} - - public static PerThreadGroupPool make() { - return new PerThreadGroupPool(); - } - - public synchronized T getThreadPoolExecutor(Create 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 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(executor)); - } - return executor; - } -} diff --git a/src/share/classes/com/sun/jmx/mbeanserver/Repository.java b/src/share/classes/com/sun/jmx/mbeanserver/Repository.java index 03f3e5277..e35ac65c9 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/Repository.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/Repository.java @@ -396,7 +396,7 @@ public class Repository { // 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 @@ public class Repository { // 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 moiTb = domainTb.get(dom); if (allNames) result.addAll(moiTb.values()); diff --git a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java index 87aa9301d..2237a5192 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java @@ -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.IntrospectionException; 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 @@ class StandardMBeanIntrospector extends MBeanIntrospector { @Override MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, - Method getter, Method setter) throws IntrospectionException { - - String description = getAttributeDescription( - attributeName, "Attribute exposed for management", - getter, setter); - return new MBeanAttributeInfo(attributeName, description, - getter, setter); + Method getter, Method setter) { + + final String description = "Attribute exposed for management"; + try { + return new MBeanAttributeInfo(attributeName, description, + getter, setter); + } catch (IntrospectionException e) { + throw new RuntimeException(e); // should not happen + } } @Override MBeanOperationInfo getMBeanOperationInfo(String operationName, Method operation) { - final String 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 diff --git a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java index 4b9963eee..3deeb168c 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java @@ -31,7 +31,6 @@ import javax.management.MBeanInfo; 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 class StandardMBeanSupport extends MBeanSupport { */ public StandardMBeanSupport(T resource, Class mbeanInterfaceType) throws NotCompliantMBeanException { - super(resource, mbeanInterfaceType, (MXBeanMappingFactory) null); + super(resource, mbeanInterfaceType); } @Override - MBeanIntrospector getMBeanIntrospector(MXBeanMappingFactory ignored) { + MBeanIntrospector getMBeanIntrospector() { return StandardMBeanIntrospector.getInstance(); } @@ -84,14 +83,13 @@ public class StandardMBeanSupport extends MBeanSupport { @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()); } } diff --git a/src/share/classes/com/sun/jmx/mbeanserver/Util.java b/src/share/classes/com/sun/jmx/mbeanserver/Util.java index 1e575e419..b0a8eeb84 100644 --- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java +++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java @@ -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.List; 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 Map newMap() { return new HashMap(); @@ -89,10 +80,6 @@ public class Util { return new LinkedHashMap(); } - static WeakHashMap newWeakHashMap() { - return new WeakHashMap(); - } - static Set newSet() { return new HashSet(); } @@ -251,451 +238,4 @@ public class Util { 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 ////...// matches ////...// - * 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 filterMatchingNames(ObjectName pattern, - Set 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 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 - filterMatchingInstances(ObjectName pattern, - Set 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 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=[;*]]} 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=[;*]]} - * @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 Set cloneSet(Set set) { - if (set instanceof SortedSet) { - @SuppressWarnings("unchecked") - SortedSet sset = (SortedSet) set; - set = new TreeSet(sset.comparator()); - set.addAll(sset); - } else - set = new HashSet(set); - return set; - } - - public static Set equivalentEmptySet(Set set) { - if (set instanceof SortedSet) { - @SuppressWarnings("unchecked") - SortedSet sset = (SortedSet) set; - set = new TreeSet(sset.comparator()); - } else - set = new HashSet(); - 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); - } } diff --git a/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java b/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java deleted file mode 100644 index 6e56c8385..000000000 --- a/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java +++ /dev/null @@ -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. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class DomainInterceptor extends HandlerInterceptor { - - // 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 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 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 processOutputInstances(Set sources) { - if (sources == null || sources.isEmpty() || !checkOn()) - return sources; - final Set 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 processOutputNames(Set sourceNames) { - if (sourceNames == null || sourceNames.isEmpty() || !checkOn()) - return sourceNames; - final Set 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 queryNames(ObjectName name, QueryExp query) { - try { - // We don't trust the wrapped JMXDomain... - final ObjectName pattern = getPatternFor(name); - final Set 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 queryMBeans(ObjectName name, QueryExp query) { - try { - // We don't trust the wrapped JMXDomain... - final ObjectName pattern = getPatternFor(name); - final Set 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 res = new ArrayList(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 - * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class HandlerInterceptor - extends RoutingMBeanServerConnection - 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 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 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 //}. - * @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 //}. - * @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 //}. - * @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 //}. - * @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. - *

- * 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); - } - - - -} diff --git a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java b/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java deleted file mode 100644 index df03ed5ec..000000000 --- a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java +++ /dev/null @@ -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. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class NamespaceInterceptor extends HandlerInterceptor { - - - // 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; - final SecurityManager sm = System.getSecurityManager(); - if (sm == null) return attributes; - final List res = new ArrayList(attributes.length); - for (String at : attributes) { - try { - check(routingName,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) { - // in principle, this method is never called because - // getDomains() will never be called - since there's - // no way that MBeanServer.getDomains() can be routed - // to a NamespaceInterceptor. - // - // This is also why there's no getDomains() in a - // JMXNamespacePermission... - // - return super.checkDomains(domains, action); - } - - // - // Implements permission filters for queries... - // - @Override - boolean checkQuery(ObjectName routingName, String action) { - try { - check(routingName,null,action); - return true; - } catch (SecurityException x) { // DLS: OK - return false; - } - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java b/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java deleted file mode 100644 index 55a646540..000000000 --- a/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java +++ /dev/null @@ -1,175 +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 static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * The ObjectNameRouter is used to rewrite routing object names. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class ObjectNameRouter { - - private static final int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - - final String targetPrefix; - final String sourcePrefix; - final int slen; - final int tlen; - final boolean identity; - - /** Creates a new instance of ObjectNameRouter */ - public ObjectNameRouter(final String remove, final String add) { - this.targetPrefix = (remove==null?"":remove); - this.sourcePrefix = (add==null?"":add); - tlen = targetPrefix.length(); - slen = sourcePrefix.length(); - identity = targetPrefix.equals(sourcePrefix); - } - - public final ObjectName toTargetContext(ObjectName sourceName, - boolean removeLeadingSeparators) { - if (sourceName == null) return null; - if (identity) return sourceName; - String srcDomain = sourceName.getDomain(); - - // if the ObjectName starts with // and removeLeadingSeparators is - // true, then recursively strip leading //. - // Otherwise, do not rewrite ObjectName. - // - if (srcDomain.startsWith(NAMESPACE_SEPARATOR)) { - if (!removeLeadingSeparators) return sourceName; - else srcDomain = normalizeDomain(srcDomain,true); - } - if (slen != 0) { - if (!srcDomain.startsWith(sourcePrefix) || - !srcDomain.startsWith(NAMESPACE_SEPARATOR,slen)) - throw new IllegalArgumentException( - "ObjectName does not start with expected prefix " - + sourcePrefix + ": " + - String.valueOf(sourceName)); - srcDomain = srcDomain.substring(slen+NAMESPACE_SEPARATOR_LENGTH); - } - final String targetDomain = - (tlen>0?targetPrefix+NAMESPACE_SEPARATOR+srcDomain:srcDomain); - return sourceName.withDomain(targetDomain); - } - - public final ObjectName toSourceContext(ObjectName targetName, - boolean removeLeadingSeparators) { - if (targetName == null) return null; - if (identity) return targetName; - String targetDomain = targetName.getDomain(); - if (targetDomain.startsWith(NAMESPACE_SEPARATOR)) { - if (!removeLeadingSeparators) return targetName; - else targetDomain = - normalizeDomain(targetDomain,true); - } - if (tlen != 0) { - if (!targetDomain.startsWith(targetPrefix) || - !targetDomain.startsWith(NAMESPACE_SEPARATOR,tlen)) - throw new IllegalArgumentException( - "ObjectName does not start with expected prefix " - + targetPrefix + ": " + - String.valueOf(targetName)); - targetDomain = targetDomain. - substring(tlen+NAMESPACE_SEPARATOR_LENGTH); - } - final String sourceDomain = - (slen>0?sourcePrefix+NAMESPACE_SEPARATOR+targetDomain: - targetDomain); - return targetName.withDomain(sourceDomain); - } - - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi, - boolean removeLeadingSeparators) { - if (sourceMoi == null) return null; - if (identity) return sourceMoi; - return new ObjectInstance( - toTargetContext(sourceMoi.getObjectName(), - removeLeadingSeparators), - sourceMoi.getClassName()); - } - - /** - * Removes leading, trailing, or duplicate // in a name space path. - **/ - public static String normalizeDomain(String domain, - boolean removeLeadingSep) { - return normalizeNamespacePath(domain,removeLeadingSep,false,true); - } - - /** - * Removes leading, trailing, or duplicate // in a name space path. - **/ - public static String normalizeNamespacePath(String namespacePath, - boolean removeLeadingSep, - boolean removeTrailingSep, - boolean endsWithDomain) { - if (namespacePath.equals("")) - return ""; - final String[] components = namespacePath.split(NAMESPACE_SEPARATOR); - final StringBuilder b = - new StringBuilder(namespacePath.length()+NAMESPACE_SEPARATOR_LENGTH); - String sep = null; - if (!removeLeadingSep && namespacePath.startsWith(NAMESPACE_SEPARATOR)) - b.append(NAMESPACE_SEPARATOR); - int count = 0; - for (int i=0; i 0) - b.append(NAMESPACE_SEPARATOR); - return b.toString(); - } -} diff --git a/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java b/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java deleted file mode 100644 index b09bc8436..000000000 --- a/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java +++ /dev/null @@ -1,106 +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 java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServerConnection; - - -/** - * A RoutingConnectionProxy is an MBeanServerConnection proxy that proxies a - * source name space in a source MBeanServerConnection. - * It wraps a source MBeanServerConnection, and rewrites routing - * ObjectNames. It is used to implement - * {@code JMXNamespaces.narrowToNamespace(MBeanServerConnection)}. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// See class hierarchy and detailled explanations in RoutingProxy in this -// package. -// -public class RoutingConnectionProxy - extends RoutingProxy { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - - /** - * Creates a new instance of RoutingConnectionProxy - */ - public RoutingConnectionProxy(MBeanServerConnection source, - String sourceDir, - String targetDir, - boolean probe) { - super(source, sourceDir, targetDir, probe); - - if (LOG.isLoggable(Level.FINER)) - LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() + - " created"); - } - - @Override - public String toString() { - final String targetNs = getTargetNamespace(); - final String sourceNs = getSourceNamespace(); - String wrapped = String.valueOf(source()); - if ("".equals(targetNs)) { - return "JMXNamespaces.narrowToNamespace("+ - wrapped+", \""+ - sourceNs+"\")"; - } - return this.getClass().getSimpleName()+"("+wrapped+", \""+ - sourceNs+"\", \""+ - targetNs+"\")"; - } - - static final RoutingProxyFactory - - FACTORY = new RoutingProxyFactory - () { - - public RoutingConnectionProxy newInstance(MBeanServerConnection source, - String sourcePath, String targetPath, boolean probe) { - return new RoutingConnectionProxy(source,sourcePath, - targetPath, probe); - } - }; - - public static MBeanServerConnection cd( - MBeanServerConnection source, String sourcePath, boolean probe) { - return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY, - source, sourcePath, probe); - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java b/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java deleted file mode 100644 index 49b829004..000000000 --- a/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java +++ /dev/null @@ -1,556 +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.io.IOException; -import java.lang.reflect.UndeclaredThrowableException; -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.JMRuntimeException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServerConnection; -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.RuntimeMBeanException; -import javax.management.RuntimeOperationsException; - -/** - * A RoutingMBeanServerConnection wraps a MBeanServerConnection, defining - * abstract methods that can be implemented by subclasses to rewrite - * routing ObjectNames. It is used to implement - * HandlerInterceptors (wrapping JMXNamespace instances) and routing - * proxies (used to implement cd operations). - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class RoutingMBeanServerConnection - implements MBeanServerConnection { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - /** - * Creates a new instance of RoutingMBeanServerConnection - */ - public RoutingMBeanServerConnection() { - } - - /** - * Returns the wrapped source connection. The {@code source} connection - * is a connection to the MBeanServer that contains the actual MBean. - * In the case of cascading, that would be a connection to the sub - * agent. - **/ - protected abstract T source() throws IOException; - - /** - * Converts a target ObjectName to a source ObjectName. - * The target ObjectName is the name of the MBean in the mount point - * target. In the case of cascading, that would be the name of the - * MBean in the master agent. So if a subagent S containing an MBean - * named "X" is mounted in the target namespace "foo//" of a master agent M, - * the source is S, the target is "foo//" in M, the source name is "X", and - * the target name is "foo//X". - * In the case of cascading - such as in NamespaceInterceptor, this method - * will convert "foo//X" (the targetName) into "X", the source name. - * @throws IllegalArgumentException if the name cannot be converted. - **/ - protected abstract ObjectName toSource(ObjectName targetName); - /** - * Converts a source ObjectName to a target ObjectName. - * (see description of toSource above for explanations) - * In the case of cascading - such as in NamespaceInterceptor, this method - * will convert "X" (the sourceName) into "foo//X", the target name. - * @throws IllegalArgumentException if the name cannot be converted. - **/ - protected abstract ObjectName toTarget(ObjectName sourceName); - - /** - * Can be overridden by subclasses to check the validity of a new - * ObjectName used in createMBean or registerMBean. - * This method is typically used by subclasses which might require - * special handling for "null"; - **/ - protected ObjectName newSourceMBeanName(ObjectName targetName) - throws MBeanRegistrationException { - try { - return toSource(targetName); - } catch (Exception x) { - throw new MBeanRegistrationException(x,"Illegal MBean Name"); - } - } - - // Calls toSource(), Wraps IllegalArgumentException. - ObjectName toSourceOrRuntime(ObjectName targetName) { - try { - return toSource(targetName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - - // Wraps given exception if needed. - RuntimeException makeCompliantRuntimeException(Exception x) { - if (x instanceof SecurityException) return (SecurityException)x; - if (x instanceof JMRuntimeException) return (JMRuntimeException)x; - if (x instanceof RuntimeException) - return new RuntimeOperationsException((RuntimeException)x); - if (x instanceof IOException) - return Util.newRuntimeIOException((IOException)x); - // shouldn't come here... - final RuntimeException x2 = new UndeclaredThrowableException(x); - return new RuntimeOperationsException(x2); - } - - // from MBeanServerConnection - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().getAttributes(sourceName, attributes); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, MBeanException, ReflectionException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - final Object result = - source().invoke(sourceName,operationName,params, - signature); - return result; - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().unregisterMBean(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().getMBeanInfo(sourceName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return processOutputInstance( - source().getObjectInstance(sourceName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public boolean isRegistered(ObjectName name) throws IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().isRegistered(sourceName); - } catch (RuntimeMBeanException x) { - throw new RuntimeOperationsException(x.getTargetException()); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - // from MBeanServerConnection - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().setAttribute(sourceName,attribute); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, - ObjectName name, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - // Loader Name is already a sourceLoaderName. - final ObjectName sourceLoaderName = loaderName; - try { - final ObjectInstance instance = - source().createMBean(className,sourceName, - sourceLoaderName, - params,signature); - return processOutputInstance(instance); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - return processOutputInstance(source().createMBean(className, - sourceName,params,signature)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - // Loader Name is already a source Loader Name. - final ObjectName sourceLoaderName = loaderName; - try { - return processOutputInstance(source().createMBean(className, - sourceName,sourceLoaderName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, IOException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - return processOutputInstance(source(). - createMBean(className,sourceName)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().getAttribute(sourceName,attribute); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().isInstanceOf(sourceName,className); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public AttributeList setAttributes(ObjectName name, AttributeList attributes) - throws InstanceNotFoundException, ReflectionException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source(). - setAttributes(sourceName,attributes); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // Return names in the target's context. - Set processOutputInstances(Set sources) { - - final Set result = Util.equivalentEmptySet(sources); - for (ObjectInstance i : sources) { - try { - final ObjectInstance target = processOutputInstance(i); - if (excludesFromResult(target.getObjectName(), "queryMBeans")) - continue; - result.add(target); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Skiping returned item: " + - "Unexpected exception while processing " + - "ObjectInstance: " + x); - } - continue; - } - } - return result; - } - - - // Return names in the target's context. - ObjectInstance processOutputInstance(ObjectInstance source) { - if (source == null) return null; - final ObjectName sourceName = source.getObjectName(); - try { - final ObjectName targetName = toTarget(sourceName); - return new ObjectInstance(targetName,source.getClassName()); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - // Returns names in the target's context. - Set processOutputNames(Set sourceNames) { - - final Set names = Util.equivalentEmptySet(sourceNames); - for (ObjectName n : sourceNames) { - try { - final ObjectName targetName = toTarget(n); - if (excludesFromResult(targetName, "queryNames")) continue; - names.add(targetName); - } catch (Exception x) { - if (LOG.isLoggable(Level.FINE)) { - LOG.fine("Skiping returned item: " + - "Unexpected exception while processing " + - "ObjectInstance: " + x); - } - continue; - } - } - return names; - } - - // from MBeanServerConnection - public Set queryMBeans(ObjectName name, - QueryExp query) throws IOException { - if (name == null) name=ObjectName.WILDCARD; - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return processOutputInstances( - source().queryMBeans(sourceName,query)); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - - public Set queryNames(ObjectName name, QueryExp query) - throws IOException { - if (name == null) name=ObjectName.WILDCARD; - final ObjectName sourceName = toSourceOrRuntime(name); - try { - final Set tmp = source().queryNames(sourceName,query); - final Set out = processOutputNames(tmp); - //System.err.println("queryNames: out: "+out); - return out; - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, - ListenerNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().removeNotificationListener(sourceName,listener); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - // Listener name is already a source listener name. - try { - source().addNotificationListener(sourceName,listener, - filter,handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void addNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) throws InstanceNotFoundException, IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().addNotificationListener(sourceName, listener, filter, - handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().removeNotificationListener(sourceName,listener,filter, - handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - source().removeNotificationListener(sourceName,listener, - filter,handback); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - final ObjectName sourceName = toSourceOrRuntime(name); - // listener name is already a source name... - final ObjectName sourceListener = listener; - try { - source().removeNotificationListener(sourceName,sourceListener); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public Integer getMBeanCount() throws IOException { - try { - return source().getMBeanCount(); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public String[] getDomains() throws IOException { - try { - return source().getDomains(); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // from MBeanServerConnection - public String getDefaultDomain() throws IOException { - try { - return source().getDefaultDomain(); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - /** - * Returns true if the given targetName must be excluded from the - * query result. - * In this base class, always return {@code false}. - * By default all object names returned by the sources are - * transmitted to the caller - there is no filtering. - * - * @param name A target object name expressed in the caller's - * context. In the case of cascading, where the source - * is a sub agent mounted on e.g. namespace "foo", - * that would be a name prefixed by "foo//"... - * @param queryMethod either "queryNames" or "queryMBeans". - * @return true if the name must be excluded. - */ - boolean excludesFromResult(ObjectName targetName, String queryMethod) { - return false; - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java b/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java deleted file mode 100644 index 03531200c..000000000 --- a/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java +++ /dev/null @@ -1,395 +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 java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanRegistrationException; - -import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; - - -/** - * A RoutingProxy narrows on a given name space in a - * source object implementing MBeanServerConnection. - * It is used to implement - * {@code JMXNamespaces.narrowToNamespace(...)}. - * This abstract class has two concrete subclasses: - *

{@link RoutingConnectionProxy}: to narrow down into an - * MBeanServerConnection.

- *

{@link RoutingServerProxy}: to narrow down into an MBeanServer.

- * - *

This class can also be used to "broaden" from a namespace. The same - * class is used for both purposes because in both cases all that happens - * is that ObjectNames are rewritten in one way on the way in (e.g. the - * parameter of getMBeanInfo) and another way on the way out (e.g. the - * return value of queryNames).

- * - *

Specifically, if you narrow into "a//" then you want to add the - * "a//" prefix to ObjectNames on the way in and subtract it on the way - * out. But ClientContext uses this class to subtract the - * "jmx.context//foo=bar//" prefix on the way in and add it back on the - * way out.

- * - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// -// RoutingProxies are client side objects which are used to narrow down -// into a namespace. They are used to perform ObjectName translation, -// adding the namespace to the routing ObjectName before sending it over -// to the source connection, and removing that prefix from results of -// queries, createMBean, registerMBean, and getObjectInstance. -// This translation is the opposite to that which is performed by -// NamespaceInterceptors. -// -// There is however a special case where routing proxies are used on the -// 'server' side to remove a namespace - rather than to add it: -// This the case of ClientContext. -// When an ObjectName like "jmx.context//c1=v1,c2=v2//D:k=v" reaches the -// jmx.context namespace, a routing proxy is used to remove the prefix -// c1=v1,c2=v2// from the routing objectname. -// -// For a RoutingProxy used in a narrowDownToNamespace operation, we have: -// targetNs="" // targetNS is the namespace 'to remove' -// sourceNS= // namespace 'to add' -// -// For a RoutingProxy used in a ClientContext operation, we have: -// targetNs= // context must be removed from object name -// sourceNs="" // nothing to add... -// -// Finally, in order to avoid too many layers of wrapping, -// RoutingConnectionProxy and RoutingServerProxy can be created through a -// factory method that can concatenate namespace paths in order to -// return a single RoutingProxy - rather than wrapping a RoutingProxy inside -// another RoutingProxy. See RoutingConnectionProxy.cd and -// RoutingServerProxy.cd -// -// The class hierarchy is as follows: -// -// RoutingMBeanServerConnection -// [abstract class for all routing interceptors, -// such as RoutingProxies and HandlerInterceptors] -// / \ -// / \ -// RoutingProxy HandlerInterceptor -// [base class for [base class for server side -// client-side objects used objects, created by -// in narrowDownTo] DispatchInterceptors] -// / \ | \ -// RoutingConnectionProxy \ | NamespaceInterceptor -// [wraps MBeanServerConnection \ | [used to remove -// objects] \ | namespace prefix and -// RoutingServerProxy | wrap JMXNamespace] -// [wraps MBeanServer | -// Objects] | -// DomainInterceptor -// [used to wrap JMXDomain] -// -// RoutingProxies also differ from HandlerInterceptors in that they transform -// calls to MBeanServerConnection operations that do not have any parameters -// into a call to the underlying JMXNamespace MBean. -// So for instance a call to: -// JMXNamespaces.narrowDownToNamespace(conn,"foo").getDomains() -// is transformed into -// conn.getAttribute("foo//type=JMXNamespace","Domains"); -// -public abstract class RoutingProxy - extends RoutingMBeanServerConnection { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - // The source MBeanServerConnection - private final T source; - - // The name space we're narrowing to (usually some name space in - // the source MBeanServerConnection), e.g. "a" for the namespace - // "a//". This is empty in the case of ClientContext described above. - private final String sourceNs; - - // The name space we pretend to be mounted in. This is empty except - // in the case of ClientContext described above (where it will be - // something like "jmx.context//foo=bar". - private final String targetNs; - - // The name of the JMXNamespace that handles the source name space - private final ObjectName handlerName; - private final ObjectNameRouter router; - private volatile String defaultDomain = null; - - /** - * Creates a new instance of RoutingProxy - */ - protected RoutingProxy(T source, - String sourceNs, - String targetNs, - boolean probe) { - if (source == null) throw new IllegalArgumentException("null"); - this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs); - - // Usually sourceNs is not null, except when implementing - // Client Contexts - // - if (sourceNs.equals("")) { - this.handlerName = null; - } else { - // System.err.println("sourceNs: "+sourceNs); - this.handlerName = - JMXNamespaces.getNamespaceObjectName(this.sourceNs); - if (probe) { - try { - if (!source.isRegistered(handlerName)) { - InstanceNotFoundException infe = - new InstanceNotFoundException(handlerName); - throw new IllegalArgumentException(sourceNs + - ": no such name space", infe); - } - } catch (IOException x) { - throw new IllegalArgumentException("source stale: "+x,x); - } - } - } - this.source = source; - this.targetNs = (targetNs==null?"": - JMXNamespaces.normalizeNamespaceName(targetNs)); - this.router = - new ObjectNameRouter(this.targetNs,this.sourceNs); - - if (LOG.isLoggable(Level.FINER)) - LOG.finer("RoutingProxy for " + this.sourceNs + " created"); - } - - @Override - public T source() { return source; } - - @Override - public ObjectName toSource(ObjectName targetName) { - if (targetName == null) return null; - if (targetName.getDomain().equals("") && targetNs.equals("")) { - try { - if (defaultDomain == null) - defaultDomain = getDefaultDomain(); - } catch(Exception x) { - LOG.log(Level.FINEST,"Failed to get default domain",x); - } - if (defaultDomain != null) - targetName = targetName.withDomain(defaultDomain); - } - return router.toSourceContext(targetName,true); - } - - @Override - protected ObjectName newSourceMBeanName(ObjectName targetName) - throws MBeanRegistrationException { - if (targetName != null) return super.newSourceMBeanName(targetName); - - // OK => we can accept null if sourceNs is empty. - if (sourceNs.equals("")) return null; - - throw new MBeanRegistrationException( - new IllegalArgumentException( - "Can't use null ObjectName with namespaces")); - } - - @Override - public ObjectName toTarget(ObjectName sourceName) { - if (sourceName == null) return null; - return router.toTargetContext(sourceName,false); - } - - private Object getAttributeFromHandler(String attributeName) - throws IOException { - - try { - return source().getAttribute(handlerName,attributeName); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } catch (IOException x) { - throw x; - } catch (MBeanException ex) { - throw new IOException("Failed to get "+attributeName+": "+ - ex.getCause(), - ex.getCause()); - } catch (Exception ex) { - throw new IOException("Failed to get "+attributeName+": "+ - ex,ex); - } - } - - // We cannot call getMBeanCount() on the underlying - // MBeanServerConnection, because it would return the number of - // 'top-level' MBeans, not the number of MBeans in the name space - // we are narrowing to. Instead we're calling getMBeanCount() on - // the JMXNamespace that handles the source name space. - // - // There is however one particular case when the sourceNs is empty. - // In that case, there's no handler - and the 'source' is the top - // level namespace. In that particular case, handlerName will be null, - // and we directly invoke the top level source(). - // This later complex case is only used when implementing ClientContexts. - // - @Override - public Integer getMBeanCount() throws IOException { - try { - if (handlerName == null) return source().getMBeanCount(); - return (Integer) getAttributeFromHandler("MBeanCount"); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // We cannot call getDomains() on the underlying - // MBeanServerConnection, because it would return the domains of - // 'top-level' MBeans, not the domains of MBeans in the name space - // we are narrowing to. Instead we're calling getDomains() on - // the JMXNamespace that handles the source name space. - // - // There is however one particular case when the sourceNs is empty. - // In that case, there's no handler - and the 'source' is the top - // level namespace. In that particular case, handlerName will be null, - // and we directly invoke the top level source(). - // This later complex case is only used when implementing ClientContexts. - // - @Override - public String[] getDomains() throws IOException { - try { - if (handlerName == null) return source().getDomains(); - return (String[]) getAttributeFromHandler("Domains"); - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - // We cannot call getDefaultDomain() on the underlying - // MBeanServerConnection, because it would return the default domain of - // 'top-level' namespace, not the default domain in the name space - // we are narrowing to. Instead we're calling getDefaultDomain() on - // the JMXNamespace that handles the source name space. - // - // There is however one particular case when the sourceNs is empty. - // In that case, there's no handler - and the 'source' is the top - // level namespace. In that particular case, handlerName will be null, - // and we directly invoke the top level source(). - // This later complex case is only used when implementing ClientContexts. - // - @Override - public String getDefaultDomain() throws IOException { - try { - if (handlerName == null) { - defaultDomain = source().getDefaultDomain(); - } else { - defaultDomain =(String) - getAttributeFromHandler("DefaultDomain"); - } - return defaultDomain; - } catch (RuntimeException ex) { - throw makeCompliantRuntimeException(ex); - } - } - - public String getSourceNamespace() { - return sourceNs; - } - - public String getTargetNamespace() { - return targetNs; - } - - @Override - public String toString() { - return super.toString()+", sourceNs="+ - sourceNs + (targetNs.equals("")?"": - (" mounted on targetNs="+targetNs)); - } - - // Creates an instance of a subclass 'R' of RoutingProxy - // RoutingServerProxy and RoutingConnectionProxy have their own factory - // instance. - static interface RoutingProxyFactory> { - public R newInstance( - T source, String sourcePath, String targetPath, boolean probe); - } - - // Performs a narrowDownToNamespace operation. - // This method will attempt to merge two RoutingProxies in a single - // one if they are of the same class. - // - // This method is never called directly - it should be called only by - // subclasses of RoutingProxy. - // - // As for now it is called by: - // RoutingServerProxy.cd and RoutingConnectionProxy.cd. - // - static > - R cd(Class routingProxyClass, - RoutingProxyFactory factory, - T source, String sourcePath, boolean probe) { - if (source == null) throw new IllegalArgumentException("null"); - if (source.getClass().equals(routingProxyClass)) { - // cast is OK here, but findbugs complains unless we use class.cast - final R other = routingProxyClass.cast(source); - final String target = other.getTargetNamespace(); - - // Avoid multiple layers of serialization. - // - // We construct a new proxy from the original source instead of - // stacking a new proxy on top of the old one. - // - that is we replace - // cd ( cd ( x, dir1), dir2); - // by - // cd (x, dir1//dir2); - // - // We can do this only when the source class is exactly - // RoutingServerProxy. - // - if (target == null || target.equals("")) { - final String path = - JMXNamespaces.concat(other.getSourceNamespace(), - sourcePath); - return factory.newInstance(other.source(), path, "", probe); - } - // Note: we could do possibly something here - but it would involve - // removing part of targetDir, and possibly adding - // something to sourcePath. - // Too complex to bother! => simply default to stacking... - } - return factory.newInstance(source, sourcePath, "", probe); - } -} diff --git a/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java b/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java deleted file mode 100644 index a11b0eccb..000000000 --- a/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java +++ /dev/null @@ -1,576 +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.mbeanserver.Util; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.Collections; -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.OperationsException; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.loading.ClassLoaderRepository; - -/** - * A RoutingServerProxy is an MBeanServer proxy that proxies a - * source name space in a source MBeanServer. - * It wraps a source MBeanServer, and rewrites routing ObjectNames. - * It is typically use for implementing 'cd' operations, and - * will add the source name space to routing ObjectNames at input, - * and remove it at output. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * - * @since 1.7 - */ -// See class hierarchy and detailled explanations in RoutingProxy in this -// package. -// -public class RoutingServerProxy - extends RoutingProxy - implements MBeanServer { - - public RoutingServerProxy(MBeanServer source, - String sourceNs, - String targetNs, - boolean probe) { - super(source, sourceNs, targetNs, probe); - } - - /** - * This method is called each time an IOException is raised when - * trying to forward an operation to the underlying - * MBeanServerConnection, as a result of calling - * {@link #getMBeanServerConnection()} or as a result of invoking the - * operation on the returned connection. - * Subclasses may redefine this method if they need to perform any - * specific handling of IOException (logging etc...). - * @param x The raised IOException. - * @param method The name of the method in which the exception was - * raised. This is one of the methods of the MBeanServer - * interface. - * @return A RuntimeException that should be thrown by the caller. - * In this default implementation, this is an - * {@link UndeclaredThrowableException} wrapping x. - **/ - protected RuntimeException handleIOException(IOException x, - String method) { - return Util.newRuntimeIOException(x); - } - - - //-------------------------------------------- - //-------------------------------------------- - // - // Implementation of the MBeanServer interface - // - //-------------------------------------------- - //-------------------------------------------- - @Override - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - try { - super.addNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"addNotificationListener"); - } - } - - @Override - public void addNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - try { - super.addNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"addNotificationListener"); - } - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - try { - return super.createMBean(className, name); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - @Override - public ObjectInstance createMBean(String className, ObjectName name, - Object params[], String signature[]) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - try { - return super.createMBean(className, name, - params, signature); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - @Override - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - try { - return super.createMBean(className, name, loaderName); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - @Override - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName, - Object params[], - String signature[]) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - try { - return super.createMBean(className, name, loaderName, - params, signature); - } catch (IOException x) { - throw handleIOException(x,"createMBean"); - } - } - - /** - * @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[]) - * MBeanServer} - **/ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - final ObjectName sourceName = toSourceOrRuntime(name); - try { - return source().deserialize(sourceName,data); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - /** - * @deprecated see {@link MBeanServer#deserialize(String,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - try { - return source().deserialize(className,data); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - /** - * @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, - byte[] data) - throws - InstanceNotFoundException, - OperationsException, - ReflectionException { - try { - return source().deserialize(className,loaderName,data); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public Object getAttribute(ObjectName name, String attribute) - throws - MBeanException, - AttributeNotFoundException, - InstanceNotFoundException, - ReflectionException { - try { - return super.getAttribute(name, attribute); - } catch (IOException x) { - throw handleIOException(x,"getAttribute"); - } - } - - @Override - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - try { - return super.getAttributes(name, attributes); - } catch (IOException x) { - throw handleIOException(x,"getAttributes"); - } - } - - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(loaderName); - try { - return source().getClassLoader(sourceName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - final ObjectName sourceName = toSourceOrRuntime(mbeanName); - try { - return source().getClassLoaderFor(sourceName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public ClassLoaderRepository getClassLoaderRepository() { - try { - return source().getClassLoaderRepository(); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public String getDefaultDomain() { - try { - return super.getDefaultDomain(); - } catch (IOException x) { - throw handleIOException(x,"getDefaultDomain"); - } - } - - @Override - public String[] getDomains() { - try { - return super.getDomains(); - } catch (IOException x) { - throw handleIOException(x,"getDomains"); - } - } - - @Override - public Integer getMBeanCount() { - try { - return super.getMBeanCount(); - } catch (IOException x) { - throw handleIOException(x,"getMBeanCount"); - } - } - - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws - InstanceNotFoundException, - IntrospectionException, - ReflectionException { - try { - return super.getMBeanInfo(name); - } catch (IOException x) { - throw handleIOException(x,"getMBeanInfo"); - } - } - - @Override - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - try { - return super.getObjectInstance(name); - } catch (IOException x) { - throw handleIOException(x,"getObjectInstance"); - } - } - - public Object instantiate(String className) - throws ReflectionException, MBeanException { - try { - return source().instantiate(className); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public Object instantiate(String className, - Object params[], - String signature[]) - throws ReflectionException, MBeanException { - try { - return source().instantiate(className, - params,signature); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - final ObjectName srcLoaderName = toSourceOrRuntime(loaderName); - try { - return source().instantiate(className,srcLoaderName); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - public Object instantiate(String className, ObjectName loaderName, - Object params[], String signature[]) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - final ObjectName srcLoaderName = toSourceOrRuntime(loaderName); - try { - return source().instantiate(className,srcLoaderName, - params,signature); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public Object invoke(ObjectName name, String operationName, - Object params[], String signature[]) - throws - InstanceNotFoundException, - MBeanException, - ReflectionException { - try { - return super.invoke(name,operationName,params,signature); - } catch (IOException x) { - throw handleIOException(x,"invoke"); - } - } - - @Override - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - try { - return super.isInstanceOf(name, className); - } catch (IOException x) { - throw handleIOException(x,"isInstanceOf"); - } - } - - @Override - public boolean isRegistered(ObjectName name) { - try { - return super.isRegistered(name); - } catch (IOException x) { - throw handleIOException(x,"isRegistered"); - } - } - - @Override - public Set queryMBeans(ObjectName name, QueryExp query) { - try { - return super.queryMBeans(name, query); - } catch (IOException x) { - handleIOException(x,"queryMBeans"); - return Collections.emptySet(); - } - } - - @Override - public Set queryNames(ObjectName name, QueryExp query) { - try { - return super.queryNames(name, query); - } catch (IOException x) { - handleIOException(x,"queryNames"); - return Collections.emptySet(); - } - } - - public ObjectInstance registerMBean(Object object, ObjectName name) - throws - InstanceAlreadyExistsException, - MBeanRegistrationException, - NotCompliantMBeanException { - final ObjectName sourceName = newSourceMBeanName(name); - try { - return processOutputInstance( - source().registerMBean(object,sourceName)); - } catch (RuntimeException x) { - throw makeCompliantRuntimeException(x); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void removeNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - super.removeNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw handleIOException(x,"removeNotificationListener"); - } - } - - @Override - public void setAttribute(ObjectName name, Attribute attribute) - throws - InstanceNotFoundException, - AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - try { - super.setAttribute(name, attribute); - } catch (IOException x) { - throw handleIOException(x,"setAttribute"); - } - } - - @Override - public AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - try { - return super.setAttributes(name, attributes); - } catch (IOException x) { - throw handleIOException(x,"setAttributes"); - } - } - - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - try { - super.unregisterMBean(name); - } catch (IOException x) { - throw handleIOException(x,"unregisterMBean"); - } - } - - static final RoutingProxyFactory - FACTORY = new RoutingProxyFactory() { - - public RoutingServerProxy newInstance(MBeanServer source, - String sourcePath, String targetPath, boolean probe) { - return new RoutingServerProxy( - source, sourcePath, targetPath, probe); - } - }; - - public static MBeanServer cd( - MBeanServer source, String sourcePath, boolean probe) { - return RoutingProxy.cd(RoutingServerProxy.class, FACTORY, - source, sourcePath, probe); - } -} diff --git a/src/share/classes/com/sun/jmx/namespace/package.html b/src/share/classes/com/sun/jmx/namespace/package.html deleted file mode 100644 index 6677288ca..000000000 --- a/src/share/classes/com/sun/jmx/namespace/package.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - The <code>com.sun.jmx.namespace</code> package - - - -

The com.sun.jmx.namespace package contains - sun specific implementation classes used to implement the - JMX namespaces. -

-

DO NOT USE THESE CLASSES DIRECTLY

-

- This API is a Sun internal API and is subject to changes without notice. -

-

The public API through wich these proprietary classes can be - invoked is located in javax.management.namespace - package. -

- - diff --git a/src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java b/src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java deleted file mode 100644 index f458378cb..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java +++ /dev/null @@ -1,150 +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.serial; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * Class DefaultRewritingProcessor. Rewrite ObjectName in input & output - * parameters. - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -// We know that rewriting using serialization is costly. -// This object tries to determine whether an object needs rewriting prior -// to rewriting, and rewrites by creating a new object in those cases -// where we know how to recreate a new object (e.g. a Notification). -// Rewriting is however usually not used - so this object is just a -// skeleton that eventually uses serialization... -// -class DefaultRewritingProcessor extends RewritingProcessor { - - - private static enum RewriteMode { - INPUT, // Input from target to source (parameters) - OUTPUT // Output from source to target (results) - }; - - private final boolean identity; - - public DefaultRewritingProcessor(String targetDirName) { - this(targetDirName,null); - } - - /** Creates a new instance of SerialParamProcessor */ - public DefaultRewritingProcessor(final String remove, final String add) { - super(new SerialRewritingProcessor(remove, add)); - identity = remove.equals(add); - } - - private ObjectName rewriteObjectName(RewriteMode mode, - ObjectName name) { - return changeContext(mode, name); - } - - private ObjectInstance rewriteObjectInstance(RewriteMode mode, - ObjectInstance moi) { - final ObjectName srcName = moi.getObjectName(); - final ObjectName targetName = changeContext(mode,srcName); - if (targetName == srcName) return moi; - return new ObjectInstance(targetName,moi.getClassName()); - } - - - private Object processObject(RewriteMode mode, Object obj) { - if (obj == null) return null; - - // Some things which will always needs rewriting: - // ObjectName, ObjectInstance, and Notifications. - // Take care of those we can handle here... - // - if (obj instanceof ObjectName) - return rewriteObjectName(mode,(ObjectName) obj); - else if (obj instanceof ObjectInstance) - return rewriteObjectInstance(mode,(ObjectInstance) obj); - - // TODO: add other standard JMX classes - like e.g. MBeanInfo... - // - - // Well, the object may contain an ObjectName => pass it to - // our serial rewriting delegate... - // - return processAnyObject(mode,obj); - } - - - private Object processAnyObject(RewriteMode mode, Object obj) { - switch (mode) { - case INPUT: - return super.rewriteInput(obj); - case OUTPUT: - return super.rewriteOutput(obj); - default: // can't happen. - throw new AssertionError(); - } - } - - private ObjectName changeContext(RewriteMode mode, ObjectName name) { - switch (mode) { - case INPUT: - return toSourceContext(name); - case OUTPUT: - return toTargetContext(name); - default: // can't happen. - throw new AssertionError(); - } - } - - @Override - public ObjectName toTargetContext(ObjectName srcName) { - if (identity) return srcName; - return super.toTargetContext(srcName); - } - - @Override - public ObjectName toSourceContext(ObjectName targetName) { - if (identity) return targetName; - return super.toSourceContext(targetName); - } - - @SuppressWarnings("unchecked") - @Override - public T rewriteInput(T input) { - if (identity) return input; - return (T) processObject(RewriteMode.INPUT,input); - } - - @SuppressWarnings("unchecked") - @Override - public T rewriteOutput(T result) { - if (identity) return result; - return (T) processObject(RewriteMode.OUTPUT,result); - } -} diff --git a/src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java b/src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java deleted file mode 100644 index 32cca2d2d..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java +++ /dev/null @@ -1,74 +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.serial; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * Class RoutingOnlyProcessor. A RewritingProcessor that uses - * Java Serialization to rewrite ObjectNames contained in - * input & results... - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * - * @since 1.7 - */ -class IdentityProcessor extends RewritingProcessor { - - - /** Creates a new instance of SerialRewritingProcessor */ - public IdentityProcessor() { - } - - @Override - public T rewriteOutput(T result) { - return result; - } - - @Override - public T rewriteInput(T input) { - return input; - } - - @Override - public final ObjectName toTargetContext(ObjectName sourceName) { - return sourceName; - } - - @Override - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) { - return sourceMoi; - } - - @Override - public final ObjectName toSourceContext(ObjectName targetName) { - return targetName; - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java b/src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java deleted file mode 100644 index 6416bfb96..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java +++ /dev/null @@ -1,145 +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.serial; - -import com.sun.jmx.defaults.JmxProperties; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; - - -/** - * The JMXNamespaceContext class is used to implement a thread local - * serialization / deserialization context for namespaces. - *

- * This class is consulted by {@link javax.management.ObjectName} at - * serialization / deserialization time. - * The serialization or deserialization context is established by - * by the {@link SerialRewritingProcessor} defined in this package. - *

- * These classes are Sun proprietary APIs, subject to change without - * notice. Do not use these classes directly. - * The public API to rewrite ObjectNames embedded in parameters is - * defined in {@link javax.management.namespace.JMXNamespaces}. - * - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public class JMXNamespaceContext { - - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - public final String prefixToRemove; - public final String prefixToAdd; - - private JMXNamespaceContext(String add, String remove) { - prefixToRemove = (remove==null?"":remove); - prefixToAdd = (add==null?"":add); - } - - private final static class SerialContext { - private JMXNamespaceContext serializationContext; - private JMXNamespaceContext deserializationContext; - public SerialContext(){ - serializationContext = new JMXNamespaceContext("",""); - deserializationContext = new JMXNamespaceContext("",""); - } - } - - private final static ThreadLocal prefix = - new ThreadLocal() { - @Override - protected SerialContext initialValue() { - return new SerialContext(); - } - }; - - public static JMXNamespaceContext getSerializationContext() { - return prefix.get().serializationContext; - } - - public static JMXNamespaceContext getDeserializationContext() { - return prefix.get().deserializationContext; - } - - private static String[] setSerializationContext(String oldPrefix, - String newPrefix) { - final SerialContext c = prefix.get(); - JMXNamespaceContext dc = c.serializationContext; - String[] old = {dc.prefixToRemove, dc.prefixToAdd}; - c.serializationContext = new JMXNamespaceContext(newPrefix,oldPrefix); - return old; - } - - private static String[] setDeserializationContext(String oldPrefix, - String newPrefix) { - final SerialContext c = prefix.get(); - JMXNamespaceContext dc = c.deserializationContext; - String[] old = {dc.prefixToRemove, dc.prefixToAdd}; - c.deserializationContext = new JMXNamespaceContext(newPrefix,oldPrefix); - return old; - } - - static void serialize(ObjectOutputStream stream, Object obj, - String prefixToRemove, String prefixToAdd) - throws IOException { - final String[] old = - setSerializationContext(prefixToRemove,prefixToAdd); - try { - stream.writeObject(obj); - } finally { - try { - setSerializationContext(old[0],old[1]); - } catch (Exception x) { - LOG.log(Level.FINEST, - "failed to restore serialization context",x); - } - } - } - - static Object deserialize(ObjectInputStream stream, - String prefixToRemove, - String prefixToAdd) - throws IOException, ClassNotFoundException { - final String[] old = - setDeserializationContext(prefixToRemove,prefixToAdd); - try { - return stream.readObject(); - } finally { - try { - setDeserializationContext(old[0],old[1]); - } catch (Exception x) { - LOG.log(Level.FINEST, - "failed to restore serialization context",x); - } - } - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java b/src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java deleted file mode 100644 index 2c81be934..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java +++ /dev/null @@ -1,362 +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.serial; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * An object that can rewrite ObjectNames contained in input/output - * parameters when entering/leaving a {@link javax.management.namespace - * namespace}. - *

When entering a {@link javax.management.namespace - * namespace}, the {@code namespace} prefix is stripped from - * ObjectNames contained in input parameters. When leaving a - * {@code namespace}, - * the {@code namespace} prefix is prepended to the ObjectNames contained in - * the result parameters returned from that {@code namespace}. - *

- *

Objects that need to perform these operations usually use a - * {@code RewritingProcessor} for that purpose.
- * The {@code RewritingProcessor} allows a somewhat larger - * transformation in which part of a prefix {@link #newRewritingProcessor - * remove} can be replaced by another prefix {@link #newRewritingProcessor - * add}. The transformation described above correspond to the case where - * {@code remove} is the stripped {@link javax.management.namespace - * namespace} prefix (removed when entering the {@code namespace}) and - * {@code add} is the empty String {@code ""}. - *
- * It is interesting to note that {@link - * javax.management.JMXNamespaces#narrowToNamespace narrowToNamespace} - * operations use the inverse transformation (that is, {@code remove} is - * the empty String {@code ""} and {@code add} is the {@link - * javax.management.namespace namespace} prefix). - *
- * On a more general scale, {@link #rewriteInput rewriteInput} removes - * {@link #newRewritingProcessor remove} and the prepend {@link - * #newRewritingProcessor add}, and {@link #rewriteOutput rewriteOutput} - * does the opposite, removing {@link #newRewritingProcessor add}, and - * then adding {@link #newRewritingProcessor remove}. - *
- * An implementation of {@code RewritingProcessor} should make sure that - * rewriteInput(rewriteOutput(x,clp),clp) and - * rewriteOutput(rewriteInput(x,clp),clp) always return - * {@code x} or an exact clone of {@code x}. - *

- *

A default implementation of {@code RewritingProcessor} based on - * Java Object Serialization can be - * obtained from {@link #newRewritingProcessor newRewritingProcessor}. - *

- *

- * By default, the instances of {@code RewritingProcessor} returned by - * {@link #newRewritingProcessor newRewritingProcessor} will rewrite - * ObjectNames contained in instances of classes they don't know about by - * serializing and then deserializing such object instances. This will - * happen even if such instances don't - or can't contain ObjectNames, - * because the default implementation of {@code RewritingProcessor} will - * not be able to determine whether instances of such classes can/do contain - * instance of ObjectNames before serializing/deserializing them. - *

- *

If you are using custom classes that the default implementation of - * {@code RewritingProcessor} don't know about, it can be interesting to - * prevent an instance of {@code RewritingProcessor} to serialize/deserialize - * instances of such classes for nothing. In that case, you could customize - * the behavior of such a {@code RewritingProcessor} by wrapping it in a - * custom subclass of {@code RewritingProcessor} as shown below: - *

- * public class MyRewritingProcessor extends RewritingProcessor {
- *      MyRewritingProcessor(String remove, String add) {
- *          this(RewritingProcessor.newRewritingProcessor(remove,add));
- *      }
- *      MyRewritingProcessor(RewritingProcessor delegate) {
- *          super(delegate);
- *      }
- *
- *   T rewriteInput(T input) {
- *          if (input == null) return null;
- *          if (MyClass.equals(input.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) input;
- *          }
- *          return super.rewriteInput(input);
- *      }
- *   T rewriteOutput(T result) {
- *          if (result == null) return null;
- *          if (MyClass.equals(result.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) result;
- *          }
- *          return super.rewriteOutput(result);
- *      }
- * }
- * 
- *

- *

Such a subclass may also provide an alternate way of rewriting - * custom subclasses for which rewriting is needed - for instance: - *

- * public class MyRewritingProcessor extends RewritingProcessor {
- *      MyRewritingProcessor(String remove, String add) {
- *          this(RewritingProcessor.newRewritingProcessor(remove,add));
- *      }
- *      MyRewritingProcessor(RewritingProcessor delegate) {
- *          super(delegate);
- *      }
- *
- *   T rewriteInput(T input) {
- *          if (input == null) return null;
- *          if (MyClass.equals(input.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) input;
- *          } else if (MyOtherClass.equals(input.getClass())) {
- *              // Returns a new instance in which ObjectNames have been
- *              // replaced.
- *              final ObjectName aname = ((MyOtherClass)input).getName();
- *              return (T) (new MyOtherClass(super.rewriteInput(aname)));
- *          }
- *          return super.rewriteInput(input,clp);
- *      }
- *   T rewriteOutput(T result) {
- *          if (result == null) return null;
- *          if (MyClass.equals(result.getClass())) {
- *              // I know that MyClass doesn't contain any ObjectName
- *              return (T) result;
- *          } else if (MyOtherClass.equals(result.getClass())) {
- *              // Returns a new instance in which ObjectNames have been
- *              // replaced.
- *              final ObjectName aname = ((MyOtherClass)result).getName();
- *              return (T) (new MyOtherClass(super.rewriteOutput(aname)));
- *          }
- *          return super.rewriteOutput(result,clp);
- *      }
- * }
- * 
- *

- *

If your application only uses {@link javax.management.MXBean MXBeans}, - * or MBeans using simple types, and doesn't define any custom subclass of - * {@link javax.management.Notification}, you should never write such - * such {@code RewitingProcessor} implementations. - *

- *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -public abstract class RewritingProcessor { - /** - * A logger for this class. - **/ - private final RewritingProcessor delegate; - - /** - * Creates a new instance of RewritingProcessor. - *

This is equivalent to calling {@link - * #RewritingProcessor(RewritingProcessor) RewritingProcessor(null)}. - *

- **/ - protected RewritingProcessor() { - this(null); - } - - /** - * Creates a new instance of RewritingProcessor, with a delegate. - * @param delegate a {@code RewritingProcessor} to which all the - * calls will be delegated. When implementing a subclass - * of {@code RewritingProcessor}, calling {@link - * #rewriteInput super.rewriteInput} will invoke - * {@code delegate.rewriteInput} and calling {@link - * #rewriteOutput super.rewriteOutput} will invoke - * {@code delegate.rewriteOutput}. - * - **/ - protected RewritingProcessor(RewritingProcessor delegate) { - this.delegate = delegate; - } - - /** - * Rewrites ObjectNames when {@link RewritingProcessor leaving} a {@link - * javax.management.namespace namespace}. - *

- * Returns {@code obj}, if it is known that {@code obj} doesn't contain - * any ObjectName, or a new copied instance of {@code obj} in which - * ObjectNames (if any) will have been rewritten, if {@code obj} contains - * ObjectNames, or if it is not known whether {@code obj} contains - * ObjectNames or not. - *

- *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.rewriteOutput(obj)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param obj The result to be rewritten if needed. - * - * @return {@code obj}, or a clone of {@code obj} in which ObjectNames - * have been rewritten. See this class {@link RewritingProcessor - * description} for more details. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public T rewriteOutput(T obj) { - if (obj == null) return null; - if (delegate != null) - return delegate.rewriteOutput(obj); - throw new IllegalArgumentException("can't rewrite "+ - obj.getClass().getName()); - } - - /** - * Rewrites ObjectNames when {@link RewritingProcessor entering} a {@link - * javax.management.namespace namespace}. - *

- * Returns {@code obj}, if it is known that {@code obj} doesn't contain - * any ObjectName, or a new copied instance of {@code obj} in which - * ObjectNames (if any) will have been rewritten, if {@code obj} contains - * ObjectNames, or if it is not known whether {@code obj} contains - * ObjectNames or not. - *

- *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.rewriteInput(obj)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param obj The result to be rewritten if needed. - * @return {@code obj}, or a clone of {@code obj} in which ObjectNames - * have been rewritten. See this class {@link RewritingProcessor - * description} for more details. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public T rewriteInput(T obj) { - if (obj == null) return null; - if (delegate != null) - return delegate.rewriteInput(obj); - throw new IllegalArgumentException("can't rewrite "+ - obj.getClass().getName()); - } - - /** - * Translate a routing ObjectName from the target (calling) context to - * the source (called) context when {@link RewritingProcessor entering} a - * {@link javax.management.namespace namespace}. - *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.toSourceContext(targetName)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param targetName The routing target ObjectName to translate. - * @return The ObjectName translated to the source context. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public ObjectName toSourceContext(ObjectName targetName) { - if (delegate != null) - return delegate.toSourceContext(targetName); - throw new IllegalArgumentException("can't rewrite targetName: "+ - " no delegate."); - } - - /** - * Translate an ObjectName returned from the source context into - * the target (calling) context when {@link RewritingProcessor leaving} a - * {@link javax.management.namespace namespace}. - *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.toTargetContext(sourceName)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param sourceName The routing source ObjectName to translate to the - * target context. - * @return The ObjectName translated to the target context. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public ObjectName toTargetContext(ObjectName sourceName) { - if (delegate != null) - return delegate.toTargetContext(sourceName); - throw new IllegalArgumentException("can't rewrite sourceName: "+ - " no delegate."); - } - - /** - * Translate an ObjectInstance returned from the source context into - * the target (calling) context when {@link RewritingProcessor leaving} a - * {@link javax.management.namespace namespace}. - *

- * The default implementation of this method is as follows: if the - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code - * null}, throws an {@link IllegalArgumentException}. Otherwise, - * returns {@code delegate.toTargetContext(sourceMoi)}. - *

- *

This behavior can be overridden by subclasses as shown in this - * class {@link RewritingProcessor description}. - *

- * @param sourceMoi The routing source ObjectInstance to translate. - * @return The ObjectInstance translated to the target context. - * @throws IllegalArgumentException if this implementation does not know - * how to rewrite the object. - **/ - public ObjectInstance toTargetContext(ObjectInstance sourceMoi) { - if (delegate != null) - return delegate.toTargetContext(sourceMoi); - throw new IllegalArgumentException("can't rewrite sourceName: "+ - " no delegate."); - } - - /** - * Creates a new default instance of {@link RewritingProcessor}. - * @param remove The prefix to remove from {@link ObjectName ObjectNames} - * when {@link RewritingProcessor entering} the {@link - * javax.management.namespace namespace}. - * @param add The prefix to add to {@link ObjectName ObjectNames} - * when {@link RewritingProcessor entering} the {@link - * javax.management.namespace namespace} (this is performed - * after having removed the {@code remove} prefix. - * @return A new {@link RewritingProcessor} processor object that will - * perform the requested operation, using Java serialization if - * necessary. - **/ - public static RewritingProcessor newRewritingProcessor(String remove, - String add) { - return new DefaultRewritingProcessor(remove,add); - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java b/src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java deleted file mode 100644 index 1df2e26a9..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java +++ /dev/null @@ -1,74 +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.serial; - -import com.sun.jmx.namespace.ObjectNameRouter; - - -import javax.management.ObjectInstance; -import javax.management.ObjectName; - -/** - * Class RoutingOnlyProcessor. A RewritingProcessor that uses - * Java Serialization to rewrite ObjectNames contained in - * input and results... - * - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -class RoutingOnlyProcessor extends RewritingProcessor { - - final ObjectNameRouter router; - - public RoutingOnlyProcessor(String targetDirName) { - this(targetDirName,null); - } - - /** Creates a new instance of RoutingOnlyProcessor */ - public RoutingOnlyProcessor(final String remove, final String add) { - super(new IdentityProcessor()); - if (remove == null || add == null) - throw new IllegalArgumentException("Null argument"); - router = new ObjectNameRouter(remove,add); - } - - @Override - public final ObjectName toTargetContext(ObjectName sourceName) { - return router.toTargetContext(sourceName,false); - } - - @Override - public final ObjectName toSourceContext(ObjectName targetName) { - return router.toSourceContext(targetName,false); - } - - @Override - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) { - return router.toTargetContext(sourceMoi,false); - } -} diff --git a/src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java b/src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java deleted file mode 100644 index d7e879822..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java +++ /dev/null @@ -1,172 +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.serial; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InvalidClassException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.ObjectStreamClass; -import java.io.OutputStream; -import java.util.LinkedList; -import java.util.Queue; - -import javax.management.ObjectName; - -/** - * Class SerialRewritingProcessor. A RewritingProcessor that uses - * Java Serialization to rewrite ObjectNames contained in - * input & results... - *

- * This API is a Sun internal API and is subject to changes without notice. - *

- * @since 1.7 - */ -class SerialRewritingProcessor extends RewritingProcessor { - - - private static class CloneOutput extends ObjectOutputStream { - Queue> classQueue = new LinkedList>(); - - CloneOutput(OutputStream out) throws IOException { - super(out); - } - - @Override - protected void annotateClass(Class c) { - classQueue.add(c); - } - - @Override - protected void annotateProxyClass(Class c) { - classQueue.add(c); - } - } - - private static class CloneInput extends ObjectInputStream { - private final CloneOutput output; - - CloneInput(InputStream in, CloneOutput output) throws IOException { - super(in); - this.output = output; - } - - @Override - protected Class resolveClass(ObjectStreamClass osc) - throws IOException, ClassNotFoundException { - Class c = output.classQueue.poll(); - String expected = osc.getName(); - String found = (c == null) ? null : c.getName(); - if (!expected.equals(found)) { - throw new InvalidClassException("Classes desynchronized: " + - "found " + found + " when expecting " + expected); - } - return c; - } - - @Override - protected Class resolveProxyClass(String[] interfaceNames) - throws IOException, ClassNotFoundException { - return output.classQueue.poll(); - } - } - - - final String targetPrefix; - final String sourcePrefix; - final boolean identity; - - - public SerialRewritingProcessor(String targetDirName) { - this(targetDirName,null); - } - - /** Creates a new instance of SerialRewritingProcessor */ - public SerialRewritingProcessor(final String remove, final String add) { - super(new RoutingOnlyProcessor(remove,add)); - this.targetPrefix = remove; - this.sourcePrefix = add; - identity = targetPrefix.equals(sourcePrefix); - } - - private T switchContext(T result, String from,String to) - throws IOException, ClassNotFoundException { - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final CloneOutput ostream = new CloneOutput(baos); - - JMXNamespaceContext.serialize(ostream,result,from,null); - ostream.flush(); - - final byte[] bytes = baos.toByteArray(); - final ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - final CloneInput istream = new CloneInput(bais, ostream); - @SuppressWarnings("unchecked") - final T clone = (T) JMXNamespaceContext.deserialize(istream,null,to); - return clone; - } - - @Override - @SuppressWarnings("unchecked") - public T rewriteOutput(T result) { - if (identity) return result; - return (T) processOutput(result); - } - - private Object processOutput(Object result) { - try { - if (result instanceof ObjectName) - return toTargetContext((ObjectName) result); - return switchContext(result,sourcePrefix,targetPrefix); - } catch (ClassNotFoundException x) { - throw new IllegalArgumentException("Can't process result: "+x,x); - } catch (IOException x) { - throw new IllegalArgumentException("Can't process result: "+x,x); - } - } - - @Override - @SuppressWarnings("unchecked") - public T rewriteInput(T input) { - if (identity) return input; - return (T) processInput(input); - } - - private Object processInput(Object input) { - try { - if (input instanceof ObjectName) - return toSourceContext((ObjectName) input); - return switchContext(input,targetPrefix,sourcePrefix); - } catch (ClassNotFoundException x) { - throw new IllegalArgumentException("Can't process input: "+x,x); - } catch (IOException x) { - throw new IllegalArgumentException("Can't process input: "+x,x); - } - } - -} diff --git a/src/share/classes/com/sun/jmx/namespace/serial/package.html b/src/share/classes/com/sun/jmx/namespace/serial/package.html deleted file mode 100644 index fe2e8c64b..000000000 --- a/src/share/classes/com/sun/jmx/namespace/serial/package.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - The <code>com.sun.jmx.namespace.serial</code> package - - - -

The com.sun.jmx.namespace.serial package contains - sun specific implementation classes used to switch namespace - prefixes in ObjectName during serialization. -

-

NEVER USE THESE CLASSES DIRECTLY

-

- This API is a Sun internal API and is subject to changes without notice. -

-

The public API through which these proprietary classes can be invoked is - located in javax.management.namespace.JMXNamespaces -

- - diff --git a/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java b/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java index dab9b872d..14b2f5d82 100644 --- a/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java +++ b/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java @@ -86,8 +86,7 @@ public class ServerNotifForwarder { // Explicitly check MBeanPermission for addNotificationListener // - checkMBeanPermission(getMBeanServerName(), - mbeanServer, name, "addNotificationListener"); + checkMBeanPermission(name, "addNotificationListener"); if (notificationAccessController != null) { notificationAccessController.addNotificationListener( connectionId, name, getSubject()); @@ -157,8 +156,7 @@ public class ServerNotifForwarder { // Explicitly check MBeanPermission for removeNotificationListener // - checkMBeanPermission(getMBeanServerName(), - mbeanServer, name, "removeNotificationListener"); + checkMBeanPermission(name, "removeNotificationListener"); if (notificationAccessController != null) { notificationAccessController.removeNotificationListener( connectionId, name, getSubject()); @@ -333,8 +331,8 @@ public class ServerNotifForwarder { * Explicitly check the MBeanPermission for * the current access control context. */ - public static void checkMBeanPermission(String serverName, - final MBeanServer mbs, final ObjectName name, final String actions) + public void checkMBeanPermission( + final ObjectName name, final String actions) throws InstanceNotFoundException, SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) { @@ -345,7 +343,7 @@ public class ServerNotifForwarder { new PrivilegedExceptionAction() { public ObjectInstance run() throws InstanceNotFoundException { - return mbs.getObjectInstance(name); + return mbeanServer.getObjectInstance(name); } }); } catch (PrivilegedActionException e) { @@ -353,7 +351,6 @@ public class ServerNotifForwarder { } String classname = oi.getClassName(); MBeanPermission perm = new MBeanPermission( - serverName, classname, null, name, @@ -369,8 +366,7 @@ public class ServerNotifForwarder { TargetedNotification tn) { try { if (checkNotificationEmission) { - checkMBeanPermission(getMBeanServerName(), - mbeanServer, name, "addNotificationListener"); + checkMBeanPermission(name, "addNotificationListener"); } if (notificationAccessController != null) { notificationAccessController.fetchNotification( @@ -432,27 +428,12 @@ public class ServerNotifForwarder { } } - private String getMBeanServerName() { - if (mbeanServerName != null) return mbeanServerName; - else return (mbeanServerName = getMBeanServerName(mbeanServer)); - } - - private static String getMBeanServerName(final MBeanServer server) { - final PrivilegedAction action = new PrivilegedAction() { - public String run() { - return Util.getMBeanServerSecurityName(server); - } - }; - return AccessController.doPrivileged(action); - } - //------------------ // PRIVATE VARIABLES //------------------ private MBeanServer mbeanServer; - private volatile String mbeanServerName; private final String connectionId; @@ -462,7 +443,7 @@ public class ServerNotifForwarder { private final static int[] listenerCounterLock = new int[0]; private NotificationBuffer notifBuffer; - private Map> listenerMap = + private final Map> listenerMap = new HashMap>(); private boolean terminated = false; diff --git a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java index e95c1e049..daee2d121 100644 --- a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java +++ b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java @@ -780,25 +780,6 @@ public class EnvHelp { return new Hashtable(m); } - /** - * Returns true if the parameter JMXConnector.USE_EVENT_SERVICE is set to a - * String equals "true" by ignoring case in the map or in the System. - */ - public static boolean eventServiceEnabled(Map env) { - return computeBooleanFromString(env, JMXConnector.USE_EVENT_SERVICE, true); - } - - /** - * Returns true if the parameter JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE - * is set to a String equals "true" (ignores case). - * If the property DELEGATE_TO_EVENT_SERVICE is not set, returns - * a default value of "true". - */ - public static boolean delegateToEventService(Map env) { - return computeBooleanFromString(env, - JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE, true, true); - } - /** *

Name of the attribute that specifies whether a connector server * should not prevent the VM from exiting @@ -817,46 +798,6 @@ public class EnvHelp { ("true".equalsIgnoreCase((String)env.get(JMX_SERVER_DAEMON))); } -// /** -// *

Name of the attribute that specifies an EventRelay object to use. -// */ -// public static final String EVENT_RELAY = -// "jmx.remote.x.event.relay"; -// -// -// /** -// * Returns an EventRelay object. The default one is FetchingEventRelay. -// * If {@code EVENT_RELAY} is specified in {@code env} as a key, -// * its value will be returned as an EventRelay object, if the value is -// * not of type {@code EventRelay}, the default {@code FetchingEventRelay} -// * will be returned. -// * If {@code EVENT_RELAY} is not specified but {@code ENABLE_EVENT_RELAY} -// * is specified as a key and its value is , the default {@code FetchingEventRelay} -// * will be returned. -// */ -// public static EventRelay getEventRelay(Map env) { -// Map info = env == null ? -// Collections.EMPTY_MAP : env; -// -// Object o = env.get(EVENT_RELAY); -// if (o instanceof EventRelay) { -// return (EventRelay)o; -// } else if (o != null) { -// logger.warning("getEventRelay", -// "The user specified object is not an EventRelay object, " + -// "using the default class FetchingEventRelay."); -// -// return new FetchingEventRelay(); -// } -// -// if (enableEventRelay(env)) { -// return new FetchingEventRelay(); -// } -// -// return null; -// } - - private static final class SinkOutputStream extends OutputStream { public void write(byte[] b, int off, int len) {} public void write(int b) {} diff --git a/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java b/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java deleted file mode 100644 index d02da69c0..000000000 --- a/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java +++ /dev/null @@ -1,469 +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.remote.util; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.event.EventClientFactory; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.MBeanServerConnection; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.namespace.JMXNamespaces; - -/** - * Class EventClientConnection - a {@link Proxy} that wraps an - * {@link MBeanServerConnection} and an {@link EventClient}. - * All methods are routed to the underlying {@code MBeanServerConnection}, - * except add/remove notification listeners which are routed to the - * {@code EventClient}. - * The caller only sees an {@code MBeanServerConnection} which uses an - * {@code EventClient} behind the scenes. - * - * @author Sun Microsystems, Inc. - */ -public class EventClientConnection implements InvocationHandler, - EventClientFactory { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER; - - private static final int NAMESPACE_SEPARATOR_LENGTH = - JMXNamespaces.NAMESPACE_SEPARATOR.length(); - - /** - * Creates a new {@code EventClientConnection}. - * @param connection The underlying MBeanServerConnection. - */ - public EventClientConnection(MBeanServerConnection connection) { - this(connection,null); - } - - /** - * Creates a new {@code EventClientConnection}. - * @param connection The underlying MBeanServerConnection. - * @param eventClientFactory a factory object that will be invoked - * to create an {@link EventClient} when needed. - * The {@code EventClient} is created lazily, when it is needed - * for the first time. If null, a default factory will be used - * (see {@link #createEventClient}). - */ - public EventClientConnection(MBeanServerConnection connection, - Callable eventClientFactory) { - - if (connection == null) { - throw new IllegalArgumentException("Null connection"); - } - this.connection = connection; - if (eventClientFactory == null) { - eventClientFactory = new Callable() { - public final EventClient call() throws Exception { - return createEventClient(EventClientConnection.this.connection); - } - }; - } - this.eventClientFactory = eventClientFactory; - this.lock = new ReentrantLock(); - } - - /** - *

The MBean server connection through which the methods of - * a proxy using this handler are forwarded.

- * - * @return the MBean server connection. - * - * @since 1.6 - */ - public MBeanServerConnection getMBeanServerConnection() { - return connection; - } - - - - - /** - * Creates a new EventClientConnection proxy instance. - * - * @param The underlying {@code MBeanServerConnection} - which should - * not be using the Event Service itself. - * @param interfaceClass {@code MBeanServerConnection.class}, or a subclass. - * @param eventClientFactory a factory used to create the EventClient. - * If null, a default factory is used (see {@link - * #createEventClient}). - * @return the new proxy instance, which will route add/remove notification - * listener calls through an {@code EventClient}. - * - */ - private static T - newProxyInstance(T connection, - Class interfaceClass, Callable eventClientFactory) { - final InvocationHandler handler = - new EventClientConnection(connection,eventClientFactory); - final Class[] interfaces = - new Class[] {interfaceClass, EventClientFactory.class}; - - Object proxy = - Proxy.newProxyInstance(interfaceClass.getClassLoader(), - interfaces, - handler); - return interfaceClass.cast(proxy); - } - - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - final String methodName = method.getName(); - - // add/remove notification listener are routed to the EventClient - if (methodName.equals("addNotificationListener") - || methodName.equals("removeNotificationListener")) { - final Class[] sig = method.getParameterTypes(); - if (sig.length>1 && - NotificationListener.class.isAssignableFrom(sig[1])) { - return invokeBroadcasterMethod(proxy,method,args); - } - } - - // subscribe/unsubscribe are also routed to the EventClient. - final Class clazz = method.getDeclaringClass(); - if (clazz.equals(EventClientFactory.class)) { - return invokeEventClientSubscriberMethod(proxy,method,args); - } - - // local or not: equals, toString, hashCode - if (shouldDoLocally(proxy, method)) - return doLocally(proxy, method, args); - - return call(connection,method,args); - } - - // The purpose of this method is to unwrap InvocationTargetException, - // in order to avoid throwing UndeclaredThrowableException for - // declared exceptions. - // - // When calling method.invoke(), any exception thrown by the invoked - // method will be wrapped in InvocationTargetException. If we don't - // unwrap this exception, the proxy will always throw - // UndeclaredThrowableException, even for runtime exceptions. - // - private Object call(final Object obj, final Method m, - final Object[] args) - throws Throwable { - try { - return m.invoke(obj,args); - } catch (InvocationTargetException x) { - final Throwable xx = x.getTargetException(); - if (xx == null) throw x; - else throw xx; - } - } - - /** - * Route add/remove notification listener to the event client. - **/ - private Object invokeBroadcasterMethod(Object proxy, Method method, - Object[] args) throws Exception { - final String methodName = method.getName(); - final int nargs = (args == null) ? 0 : args.length; - - if (nargs < 1) { - final String msg = - "Bad arg count: " + nargs; - throw new IllegalArgumentException(msg); - } - - final ObjectName mbean = (ObjectName) args[0]; - final EventClient evtClient = getEventClient(); - - // Fails if evtClient is null AND the MBean we try to listen to is - // in a subnamespace. We fail here because we know this will not - // work. - // - // Note that if the wrapped MBeanServerConnection points to a an - // earlier agent (JDK 1.6 or earlier), then the EventClient will - // be null (we can't use the event service with earlier JDKs). - // - // In principle a null evtClient indicates that the remote VM is of - // an earlier version, in which case it shouldn't contain any namespace. - // - // So having a null evtClient AND an MBean contained in a namespace is - // clearly an error case. - // - if (evtClient == null) { - final String domain = mbean.getDomain(); - final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR); - if (index > -1 && index < - (domain.length()-NAMESPACE_SEPARATOR_LENGTH)) { - throw new UnsupportedOperationException(method.getName()+ - " on namespace "+domain.substring(0,index+ - NAMESPACE_SEPARATOR_LENGTH)); - } - } - - if (methodName.equals("addNotificationListener")) { - /* The various throws of IllegalArgumentException here - should not happen, since we know what the methods in - NotificationBroadcaster and NotificationEmitter - are. */ - if (nargs != 4) { - final String msg = - "Bad arg count to addNotificationListener: " + nargs; - throw new IllegalArgumentException(msg); - } - /* Other inconsistencies will produce ClassCastException - below. */ - - final NotificationListener listener = (NotificationListener) args[1]; - final NotificationFilter filter = (NotificationFilter) args[2]; - final Object handback = args[3]; - - if (evtClient != null) { - // general case - evtClient.addNotificationListener(mbean,listener,filter,handback); - } else { - // deprecated case. Only works for mbean in local namespace. - connection.addNotificationListener(mbean,listener,filter, - handback); - } - return null; - - } else if (methodName.equals("removeNotificationListener")) { - - /* NullPointerException if method with no args, but that - shouldn't happen because removeNL does have args. */ - NotificationListener listener = (NotificationListener) args[1]; - - switch (nargs) { - case 2: - if (evtClient != null) { - // general case - evtClient.removeNotificationListener(mbean,listener); - } else { - // deprecated case. Only works for mbean in local namespace. - connection.removeNotificationListener(mbean, listener); - } - return null; - - case 4: - NotificationFilter filter = (NotificationFilter) args[2]; - Object handback = args[3]; - if (evtClient != null) { - evtClient.removeNotificationListener(mbean, - listener, - filter, - handback); - } else { - connection.removeNotificationListener(mbean, - listener, - filter, - handback); - } - return null; - - default: - final String msg = - "Bad arg count to removeNotificationListener: " + nargs; - throw new IllegalArgumentException(msg); - } - - } else { - throw new IllegalArgumentException("Bad method name: " + - methodName); - } - } - - private boolean shouldDoLocally(Object proxy, Method method) { - final String methodName = method.getName(); - if ((methodName.equals("hashCode") || methodName.equals("toString")) - && method.getParameterTypes().length == 0 - && isLocal(proxy, method)) - return true; - if (methodName.equals("equals") - && Arrays.equals(method.getParameterTypes(), - new Class[] {Object.class}) - && isLocal(proxy, method)) - return true; - return false; - } - - private Object doLocally(Object proxy, Method method, Object[] args) { - final String methodName = method.getName(); - - if (methodName.equals("equals")) { - - if (this == args[0]) { - return true; - } - - if (!(args[0] instanceof Proxy)) { - return false; - } - - final InvocationHandler ihandler = - Proxy.getInvocationHandler(args[0]); - - if (ihandler == null || - !(ihandler instanceof EventClientConnection)) { - return false; - } - - final EventClientConnection handler = - (EventClientConnection)ihandler; - - return connection.equals(handler.connection) && - proxy.getClass().equals(args[0].getClass()); - } else if (methodName.equals("hashCode")) { - return connection.hashCode(); - } - - throw new RuntimeException("Unexpected method name: " + methodName); - } - - private static boolean isLocal(Object proxy, Method method) { - final Class[] interfaces = proxy.getClass().getInterfaces(); - if(interfaces == null) { - return true; - } - - final String methodName = method.getName(); - final Class[] params = method.getParameterTypes(); - for (Class intf : interfaces) { - try { - intf.getMethod(methodName, params); - return false; // found method in one of our interfaces - } catch (NoSuchMethodException nsme) { - // OK. - } - } - - return true; // did not find in any interface - } - - /** - * Return the EventClient used by this object. Can be null if the - * remote VM is of an earlier JDK version which doesn't have the - * event service.
- * This method will invoke the event client factory the first time - * it is called. - **/ - public final EventClient getEventClient() { - if (initialized) return client; - try { - if (!lock.tryLock(TRYLOCK_TIMEOUT,TimeUnit.SECONDS)) - throw new IllegalStateException("can't acquire lock"); - try { - client = eventClientFactory.call(); - initialized = true; - } finally { - lock.unlock(); - } - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new IllegalStateException("Can't create EventClient: "+x,x); - } - return client; - } - - /** - * Returns an event client for the wrapped {@code MBeanServerConnection}. - * This is the method invoked by the default event client factory. - * @param connection the wrapped {@code MBeanServerConnection}. - **/ - protected EventClient createEventClient(MBeanServerConnection connection) - throws Exception { - final ObjectName name = - EventClientDelegate.OBJECT_NAME; - if (connection.isRegistered(name)) { - return new EventClient(connection); - } - return null; - } - - /** - * Creates a new {@link MBeanServerConnection} that goes through an - * {@link EventClient} to receive/subscribe to notifications. - * @param connection the underlying {@link MBeanServerConnection}. - * The given connection shouldn't be already - * using an {@code EventClient}. - * @param eventClientFactory a factory object that will be invoked - * to create an {@link EventClient} when needed. - * The {@code EventClient} is created lazily, when it is needed - * for the first time. If null, a default factory will be used - * (see {@link #createEventClient}). - * @return the MBeanServerConnection. - **/ - public static MBeanServerConnection getEventConnectionFor( - MBeanServerConnection connection, - Callable eventClientFactory) { - if (connection instanceof EventClientFactory - && eventClientFactory != null) - throw new IllegalArgumentException("connection already uses EventClient"); - - if (connection instanceof EventClientFactory) - return connection; - - // create a new proxy using an event client. - // - if (LOG.isLoggable(Level.FINE)) - LOG.fine("Creating EventClient for: "+connection); - return newProxyInstance(connection, - MBeanServerConnection.class, - eventClientFactory); - } - - private Object invokeEventClientSubscriberMethod(Object proxy, - Method method, Object[] args) throws Throwable { - return call(this,method,args); - } - - // Maximum lock timeout in seconds. Obviously arbitrary. - // - private final static short TRYLOCK_TIMEOUT = 3; - - private final MBeanServerConnection connection; - private final Callable eventClientFactory; - private final Lock lock; - private volatile EventClient client = null; - private volatile boolean initialized = false; - -} diff --git a/src/share/classes/java/lang/management/PlatformComponent.java b/src/share/classes/java/lang/management/PlatformComponent.java index 3dc5a6840..fbf930e67 100644 --- a/src/share/classes/java/lang/management/PlatformComponent.java +++ b/src/share/classes/java/lang/management/PlatformComponent.java @@ -40,6 +40,7 @@ import com.sun.management.HotSpotDiagnosticMXBean; import com.sun.management.UnixOperatingSystemMXBean; import sun.management.ManagementFactoryHelper; +import sun.management.Util; /** * This enum class defines the list of platform components @@ -384,7 +385,7 @@ enum PlatformComponent { // if there are more than 1 key properties (i.e. other than "type") domainAndType += ",*"; } - ObjectName on = ObjectName.valueOf(domainAndType); + ObjectName on = Util.newObjectName(domainAndType); Set set = mbs.queryNames(on, null); for (PlatformComponent pc : subComponents) { set.addAll(pc.getObjectNames(mbs)); diff --git a/src/share/classes/java/util/logging/Logging.java b/src/share/classes/java/util/logging/Logging.java index d99782407..f70c2cffb 100644 --- a/src/share/classes/java/util/logging/Logging.java +++ b/src/share/classes/java/util/logging/Logging.java @@ -29,6 +29,7 @@ import java.util.Enumeration; import java.util.List; import java.util.ArrayList; +import javax.management.MalformedObjectNameException; import javax.management.ObjectName; /** @@ -118,6 +119,10 @@ class Logging implements LoggingMXBean { } public ObjectName getObjectName() { - return ObjectName.valueOf(LogManager.LOGGING_MXBEAN_NAME); + try { + return ObjectName.getInstance(LogManager.LOGGING_MXBEAN_NAME); + } catch (MalformedObjectNameException e) { + throw new IllegalArgumentException(e); + } } } diff --git a/src/share/classes/javax/management/AndQueryExp.java b/src/share/classes/javax/management/AndQueryExp.java index b40cb7473..b09774270 100644 --- a/src/share/classes/javax/management/AndQueryExp.java +++ b/src/share/classes/javax/management/AndQueryExp.java @@ -104,26 +104,4 @@ class AndQueryExp extends QueryEval implements QueryExp { public String toString() { return "(" + exp1 + ") and (" + exp2 + ")"; } - - @Override - String toQueryString() { - // Parentheses are only added if needed to disambiguate. - return parens(exp1) + " and " + parens(exp2); - } - - // Add parens if needed to disambiguate an expression such as - // Query.and(Query.or(a, b), c). We need to return - // (a or b) and c - // in such a case, because - // a or b and c - // would mean - // a or (b and c) - private static String parens(QueryExp exp) { - String s = Query.toString(exp); - if (exp instanceof OrQueryExp) - return "(" + s + ")"; - else - return s; - } - } diff --git a/src/share/classes/javax/management/AttributeList.java b/src/share/classes/javax/management/AttributeList.java index a629d57cc..b7bcf70a0 100644 --- a/src/share/classes/javax/management/AttributeList.java +++ b/src/share/classes/javax/management/AttributeList.java @@ -137,56 +137,6 @@ public class AttributeList extends ArrayList { super.addAll(list); } - /** - *

Constructs an {@code AttributeList} containing the elements of - * the {@code Map} specified, in the order in which they appear in the - * {@code Map}'s {@link Map#entrySet entrySet}. For each {@code - * key} and {@code value} in the {@code Map}, the constructed - * {@code AttributeList} will contain {@link Attribute#Attribute - * Attribute(key, value)}.

- * - * @param map the {@code Map} defining the elements of the new - * {@code AttributeList}. - */ - public AttributeList(Map map) { - for (Map.Entry entry : map.entrySet()) - add(new Attribute(entry.getKey(), entry.getValue())); - typeSafe = true; - } - - /** - *

Return a {@code Map} that is a snapshot of the values in this - * {@code AttributeList}. Each key in the {@code Map} is the {@linkplain - * Attribute#getName() name} of an {@code Attribute} in the list, and each - * value is the corresponding {@linkplain Attribute#getValue() value} of - * that {@code Attribute}. The {@code AttributeList} and the {@code Map} - * are unrelated after the call, that is, changes to one do not affect the - * other.

- * - *

If the {@code AttributeList} contains more than one {@code Attribute} - * with the same name, then the {@code Map} will contain an entry - * for that name where the value is that of the last of those {@code - * Attribute}s.

- * - * @return the new {@code Map}. - * - * @throws IllegalArgumentException if this {@code AttributeList} contains - * an element that is not an {@code Attribute}. - */ - public Map toMap() { - Map map = new LinkedHashMap(); - - // We can't call adding(this) because we're not necessarily typeSafe - if (tainted) - throw new IllegalArgumentException("AttributeList contains non-Attribute"); - - for (Object x : this) { - Attribute a = (Attribute) x; - map.put(a.getName(), a.getValue()); - } - return map; - } - /** * Return a view of this list as a {@code List}. * Changes to the returned value are reflected by changes diff --git a/src/share/classes/javax/management/AttributeValueExp.java b/src/share/classes/javax/management/AttributeValueExp.java index e2ea10aef..c4ff21291 100644 --- a/src/share/classes/javax/management/AttributeValueExp.java +++ b/src/share/classes/javax/management/AttributeValueExp.java @@ -51,8 +51,6 @@ public class AttributeValueExp implements ValueExp { */ private String attr; - private transient int dotIndex; - /** * An AttributeValueExp with a null attribute. * @deprecated An instance created with this constructor cannot be @@ -71,18 +69,6 @@ public class AttributeValueExp implements ValueExp { */ public AttributeValueExp(String attr) { this.attr = attr; - setDotIndex(); - } - - private void setDotIndex() { - if (attr != null) - dotIndex = attr.indexOf('.'); - } - - private void readObject(ObjectInputStream in) - throws ClassNotFoundException, IOException { - in.defaultReadObject(); - setDotIndex(); } /** @@ -134,7 +120,7 @@ public class AttributeValueExp implements ValueExp { */ @Override public String toString() { - return QueryParser.quoteId(attr); + return attr; } @@ -160,18 +146,6 @@ public class AttributeValueExp implements ValueExp { * If the attempt to access the attribute generates an exception, * return null.

* - *

Let n be the {@linkplain #getAttributeName attribute - * name}. Then this method proceeds as follows. First it calls - * {@link MBeanServer#getAttribute getAttribute(name, n)}. If that - * generates an {@link AttributeNotFoundException}, and if n - * contains at least one dot ({@code .}), then the method calls {@code - * getAttribute(name, }n{@code .substring(0, }n{@code - * .indexOf('.')))}; in other words it calls {@code getAttribute} - * with the substring of n before the first dot. Then it - * extracts a component from the retrieved value, as described in the documentation for the {@code - * monitor} package.

- * *

The MBean Server used is the one returned by {@link * QueryEval#getMBeanServer()}.

* @@ -186,34 +160,9 @@ public class AttributeValueExp implements ValueExp { MBeanServer server = QueryEval.getMBeanServer(); - try { return server.getAttribute(name, attr); - } catch (AttributeNotFoundException e) { - if (dotIndex < 0) - throw e; - } - - String toGet = attr.substring(0, dotIndex); - - Object value = server.getAttribute(name, toGet); - - return extractElement(value, attr.substring(dotIndex + 1)); } catch (Exception re) { return null; } } - - private Object extractElement(Object value, String elementWithDots) - throws AttributeNotFoundException { - while (true) { - int dot = elementWithDots.indexOf('.'); - String element = (dot < 0) ? - elementWithDots : elementWithDots.substring(0, dot); - value = Introspector.elementFromComplex(value, element); - if (dot < 0) - return value; - elementWithDots = elementWithDots.substring(dot + 1); - } - } - } diff --git a/src/share/classes/javax/management/BetweenQueryExp.java b/src/share/classes/javax/management/BetweenQueryExp.java index 0c823a5f8..67b59facf 100644 --- a/src/share/classes/javax/management/BetweenQueryExp.java +++ b/src/share/classes/javax/management/BetweenQueryExp.java @@ -139,9 +139,4 @@ class BetweenQueryExp extends QueryEval implements QueryExp { public String toString() { return "(" + exp1 + ") between (" + exp2 + ") and (" + exp3 + ")"; } - - @Override - String toQueryString() { - return exp1 + " between " + exp2 + " and " + exp3; - } } diff --git a/src/share/classes/javax/management/BinaryOpValueExp.java b/src/share/classes/javax/management/BinaryOpValueExp.java index 6d251abe5..cc6886579 100644 --- a/src/share/classes/javax/management/BinaryOpValueExp.java +++ b/src/share/classes/javax/management/BinaryOpValueExp.java @@ -253,7 +253,5 @@ class BinaryOpValueExp extends QueryEval implements ValueExp { @Deprecated public void setMBeanServer(MBeanServer s) { super.setMBeanServer(s); - } - - + } } diff --git a/src/share/classes/javax/management/BinaryRelQueryExp.java b/src/share/classes/javax/management/BinaryRelQueryExp.java index 2f5bd9b21..05d01208b 100644 --- a/src/share/classes/javax/management/BinaryRelQueryExp.java +++ b/src/share/classes/javax/management/BinaryRelQueryExp.java @@ -192,11 +192,6 @@ class BinaryRelQueryExp extends QueryEval implements QueryExp { return "(" + exp1 + ") " + relOpString() + " (" + exp2 + ")"; } - @Override - String toQueryString() { - return exp1 + " " + relOpString() + " " + exp2; - } - private String relOpString() { switch (relOp) { case Query.GT: diff --git a/src/share/classes/javax/management/ClientContext.java b/src/share/classes/javax/management/ClientContext.java deleted file mode 100644 index f37fb6e77..000000000 --- a/src/share/classes/javax/management/ClientContext.java +++ /dev/null @@ -1,1091 +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 javax.management; - -import com.sun.jmx.interceptor.SingleMBeanForwarder; -import com.sun.jmx.namespace.RoutingConnectionProxy; -import com.sun.jmx.namespace.RoutingProxy; -import com.sun.jmx.namespace.RoutingServerProxy; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; -import java.util.concurrent.Callable; -import java.util.logging.Level; -import java.util.logging.Logger; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaceMBean; -import javax.management.namespace.MBeanServerSupport; -import javax.management.remote.IdentityMBeanServerForwarder; -import javax.management.remote.MBeanServerForwarder; - -/** - *

Methods to communicate a client context to MBeans. A context is - * a {@literal Map} that is provided by the client and - * that an MBean can consult using the {@link #getContext()} method. - * The context is set on a per-thread basis and can be consulted by any - * code that the target MBean calls within the thread.

- * - *

One common usage of client context is to communicate the client's - * {@link Locale} to MBeans. For example, if an MBean has a String attribute - * {@code LastProblemDescription}, the value of that attribute could be - * a description of the last problem encountered by the MBean, translated - * into the client's locale. Different clients accessing this attribute - * from different locales would each see the appropriate version for their - * locale.

- * - *

The locale case is sufficiently important that it has a special - * shorthand, the {@link #getLocale()} method. This method calls - * {@link #getContext()}.get({@link #LOCALE_KEY}) and converts the - * resultant String into a Locale object.

- * - *

Here is what an MBean with a localized {@code LastProblemDescription} - * attribute might look like:

- * - *
- * public class LocaleSensitive implements LocaleSensitiveMBean {
- *     ...
- *     public String getLastProblemDescription() {
- *         Locale loc = {@link #getLocale() ClientContext.getLocale()};
- *         ResourceBundle rb = ResourceBundle.getBundle("MyResources", loc);
- *         String resourceKey = getLastProblemResourceKey();
- *         return rb.getString(resourceKey);
- *     }
- *     ...
- * }
- * 
- * - *

Here is how a client can communicate its locale to the target - * MBean:

- * - *
- * JMXConnector connector = JMXConnectorFactory.connect(url);
- * MBeanServerConnection connection = connector.getMBeanServerConnection();
- * MBeanServerConnection localizedConnection =
- *     {@link #withLocale(MBeanServerConnection, Locale)
- *      ClientContext.withLocale}(connection, Locale.getDefault());
- * String problem = localizedConnection.getAttribute(
- *          objectName, "LastProblemDescription");
- * 
- * - *

In the more general case where the client wants to communicate context - * other than the locale, it can use {@link #withContext(MBeanServerConnection, - * String, String) withContext} instead of {@code withLocale}, and the target - * MBean can retrieve the context using {@link #getContext()}.

- * - * - *

Remote use of contexts

- * - *

The various {@code with*} methods, for example {@link - * #withLocale(javax.management.MBeanServer, java.util.Locale) withLocale}, - * transmit the context of each request by encoding it in the ObjectName of - * the request. For example, if a client creates a connection in the - * French locale like this...

- * - *
- * MBeanServerConnection mbsc = ...;
- * Locale french = new Locale("fr");
- * MBeanServerConnection localizedConnection = ClientContext.withLocale(mbsc, french);
- * 
- * - *

...or, equivalently, like this...

- * - *
- * MBeanServerConnection localizedConnection =
- *     ClientContext.withContext(mbsc, {@link #LOCALE_KEY "jmx.locale"}, "fr");
- * 
- * - *

...then the context associates {@code "jmx.locale"} with {@code "fr"} - * and a request such as
- * {@code localizedConnection.getAttribute("java.lang:type=Runtime", "Name")}
- * is translated into
- * {@code mbsc.getAttribute("jmx.context//jmx.locale=fr//java.lang:Runtime", "Name")}.
- * A special {@linkplain javax.management.namespace namespace} {@code jmx.context//} - * extracts the context from the string {@code jmx.locale=fr} and establishes - * it in the thread that will do
- * {@code getAttribute("java.lang:Runtime", "Name")}.

- * - *

The details of how contexts are encoded into ObjectNames are explained - * in the {@link #encode encode} method.

- * - *

The namespace {@code jmx.context//} just mentioned is only needed by - * remote clients, since local clients can set the context directly using - * {@link #doWithContext doWithContext}. Accordingly, this namespace is not - * present by default in the {@code MBeanServer}. Instead, it is - * simulated by the standard RMI connector using a special - * {@link MBeanServerForwarder}. If you are using this connector, you do not - * need to do anything special. Other connectors may or may not simulate this - * namespace in the same way. If the connector server returns true from the - * method {@link - * javax.management.remote.JMXConnectorServer#supportsSystemMBeanServerForwarder() - * supportsSystemMBeanServerForwarder} then it does simulate the namespace. - * If you are using another connector, or if you want to be able to use the - * {@code with*} methods locally, then you can install the {@code - * MBeanServerForwarder} yourself as described in the method {@link - * #newContextForwarder newContextForwarder}.

- */ -public class ClientContext { - /** - *

The context key for the client locale. The string associated with - * this key is an encoded locale such as {@code en_US} which could be - * returned by {@link Locale#toString()}.

- */ - public static final String LOCALE_KEY = "jmx.locale"; - - private static final Logger LOG = - Logger.getLogger("javax.management.context"); - - /** - *

The namespace that implements contexts, {@value}.

- */ - public static final String - NAMESPACE = "jmx.context"; - private static final String NAMESPACE_PLUS_SEP = - NAMESPACE + NAMESPACE_SEPARATOR; - static final ObjectName CLIENT_CONTEXT_NAMESPACE_HANDLER = - ObjectName.valueOf(NAMESPACE_PLUS_SEP + ":" + - JMXNamespace.TYPE_ASSIGNMENT); - private static final ObjectName NAMESPACE_HANDLER_WITHOUT_NAMESPACE = - ObjectName.valueOf(":" + JMXNamespace.TYPE_ASSIGNMENT); - - private static final ThreadLocal> contextThreadLocal = - new InheritableThreadLocal>() { - @Override - protected Map initialValue() { - return Collections.emptyMap(); - } - }; - - /** There are no instances of this class. */ - private ClientContext() { - } - - /** - *

Get the client context associated with the current thread. - * - * @return the client context associated with the current thread. - * This may be an empty Map, but it cannot be null. The returned - * Map cannot be modified. - */ - public static Map getContext() { - return Collections.unmodifiableMap(contextThreadLocal.get()); - } - - /** - *

Get the client locale associated with the current thread. - * If the client context includes the {@value #LOCALE_KEY} key - * then the returned value is the Locale encoded in that key. - * Otherwise the returned value is the {@linkplain Locale#getDefault() - * default locale}. - * - * @return the client locale. - */ - public static Locale getLocale() { - String localeS = getContext().get(LOCALE_KEY); - if (localeS == null) - return Locale.getDefault(); - // Parse the locale string. Why isn't there a method in Locale for this? - String language, country, variant; - int ui = localeS.indexOf('_'); - if (ui < 0) { - language = localeS; - country = variant = ""; - } else { - language = localeS.substring(0, ui); - localeS = localeS.substring(ui + 1); - ui = localeS.indexOf('_'); - if (ui < 0) { - country = localeS; - variant = ""; - } else { - country = localeS.substring(0, ui); - variant = localeS.substring(ui + 1); - } - } - return new Locale(language, country, variant); - } - - /** - *

Execute the given {@code task} with the client context set to - * the given Map. This Map will be the result of {@link #getContext()} - * within the {@code task}.

- * - *

The {@code task} may include nested calls to {@code doWithContext}. - * The value returned by {@link #getContext} at any point is the Map - * provided to the most recent {@code doWithContext} (in the current thread) - * that has not yet returned.

- * - *

The {@link #getContext()} method returns the same value immediately - * after a call to this method as immediately before. In other words, - * {@code doWithContext} only affects the context during the execution of - * the {@code task}.

- * - *

As an example, suppose you want to get an attribute with whatever - * context has already been set, plus the locale set to "fr". You could - * write this:

- * - *
-     * {@code Map} context =
-     *     new {@code HashMap}(ClientContext.getContext());
-     * context.put(ClientContext.LOCALE_KEY, "fr");
-     * String lastProblemDescription =
-     *     ClientContext.doWithContext(context, new {@code Callable}() {
-     *         public String call() {
-     *             return (String) mbeanServer.getAttribute(mbean, "LastProblemDescription");
-     *         }
-     *     });
-     * 
- * - * @param the type of value that the task will return. This type - * parameter is usually inferred from the type of the {@code task} - * parameter. For example, if {@code task} is a {@code Callable} - * then {@code T} is {@code String}. If the task does not return a value, - * use a {@code Callable} and return null from its - * {@link Callable#call call} method. - * @param context the context to use while executing {@code task}. - * @param task the task to run with the {@code key}={@code value} - * binding. - * @return the result of {@link Callable#call() task.call()}. - * @throws IllegalArgumentException if either parameter is null, or - * if any key in {@code context} is null or empty, or if any value - * in {@code context} is null. - * @throws Exception If {@link Callable#call() task.call()} throws an - * exception, {@code doWithContext} throws the same exception. - */ - public static T doWithContext(Map context, Callable task) - throws Exception { - if (context == null || task == null) - throw new IllegalArgumentException("Null parameter"); - Map contextCopy = new TreeMap(context); - validateContext(contextCopy); - Map oldContextMap = contextThreadLocal.get(); - try { - contextThreadLocal.set(contextCopy); - return task.call(); - } finally { - contextThreadLocal.set(oldContextMap); - } - } - - private static void validateContext(Map context) { - for (Map.Entry entry : context.entrySet()) { - // If the user passes a raw Map rather than a Map, - // entries could contain objects other than Strings. If so, - // we'll get a ClassCastException here. - String key = entry.getKey(); - String value = entry.getValue(); - if (key == null || value == null) - throw new IllegalArgumentException("Null key or value in context"); - if (key.equals("")) - throw new IllegalArgumentException("Empty key in context"); - } - } - - /** - *

Return an MBeanServer object that is equivalent to the given - * MBeanServer object except that operations on MBeans run with - * the given Locale in their {@linkplain #getContext() thread context}. - * Note that this will only work if the given MBeanServer supports - * contexts, as described above.

- * - *

This method is equivalent to {@link #withContext(MBeanServer, - * String, String) withContext}(mbs, {@value LOCALE_KEY}, - * locale.toString()).

- * - * @throws IllegalArgumentException if either parameter is null, or if - * {@code mbs} does not support contexts. In the second case only, - * the cause of the {@code IllegalArgumentException} will be an {@link - * InstanceNotFoundException}. - */ - public static MBeanServer withLocale(MBeanServer mbs, Locale locale) { - return withLocale(mbs, MBeanServer.class, locale); - } - - /** - *

Return an MBeanServerConnection object that is equivalent to the given - * MBeanServerConnection object except that operations on MBeans run with - * the given Locale in their {@linkplain #getContext() thread context}. - * Note that this will only work if the given MBeanServerConnection supports - * contexts, as described above.

- * - *

This method is equivalent to {@link #withContext(MBeanServerConnection, - * String, String) withContext}(mbs, {@value LOCALE_KEY}, - * locale.toString()).

- * - * @throws IllegalArgumentException if either parameter is null, or if - * the communication with {@code mbsc} fails, or if {@code mbsc} does not - * support contexts. If the communication with {@code mbsc} fails, the - * {@linkplain Throwable#getCause() cause} of this exception will be an - * {@code IOException}. If {@code mbsc} does not support contexts, the - * cause will be an {@link InstanceNotFoundException}. - */ - public static MBeanServerConnection withLocale( - MBeanServerConnection mbsc, Locale locale) { - return withLocale(mbsc, MBeanServerConnection.class, locale); - } - - private static T withLocale( - T mbsc, Class mbscClass, Locale locale) { - if (locale == null) - throw new IllegalArgumentException("Null locale"); - return withContext(mbsc, mbscClass, LOCALE_KEY, locale.toString()); - } - - /** - *

Return an MBeanServer object that is equivalent to the given - * MBeanServer object except that operations on MBeans run with - * the given key bound to the given value in their {@linkplain - * #getContext() thread context}. - * Note that this will only work if the given MBeanServer supports - * contexts, as described above.

- * - * @param mbs the original MBeanServer. - * @param key the key to bind in the context of MBean operations - * in the returned MBeanServer object. - * @param value the value to bind to the key in the context of MBean - * operations in the returned MBeanServer object. - * @throws IllegalArgumentException if any parameter is null, or - * if {@code key} is the empty string, or if {@code mbs} does not support - * contexts. In the last case only, the cause of the {@code - * IllegalArgumentException} will be an {@link InstanceNotFoundException}. - */ - public static MBeanServer withContext( - MBeanServer mbs, String key, String value) { - return withContext(mbs, MBeanServer.class, key, value); - } - - /** - *

Return an MBeanServerConnection object that is equivalent to the given - * MBeanServerConnection object except that operations on MBeans run with - * the given key bound to the given value in their {@linkplain - * #getContext() thread context}. - * Note that this will only work if the given MBeanServerConnection supports - * contexts, as described above.

- * - * @param mbsc the original MBeanServerConnection. - * @param key the key to bind in the context of MBean operations - * in the returned MBeanServerConnection object. - * @param value the value to bind to the key in the context of MBean - * operations in the returned MBeanServerConnection object. - * @throws IllegalArgumentException if any parameter is null, or - * if {@code key} is the empty string, or if the communication with {@code - * mbsc} fails, or if {@code mbsc} does not support contexts. If - * the communication with {@code mbsc} fails, the {@linkplain - * Throwable#getCause() cause} of this exception will be an {@code - * IOException}. If {@code mbsc} does not support contexts, the cause will - * be an {@link InstanceNotFoundException}. - */ - public static MBeanServerConnection withContext( - MBeanServerConnection mbsc, String key, String value) { - return withContext(mbsc, MBeanServerConnection.class, key, value); - } - - - /** - *

Returns an MBeanServerConnection object that is equivalent to the - * given MBeanServerConnection object except that remote operations on - * MBeans run with the context that has been established by the client - * using {@link #doWithContext doWithContext}. Note that this will - * only work if the remote system supports contexts, as described above.

- * - *

For example, suppose the remote system does support contexts, and you - * have created a {@code JMXConnector} like this:

- * - *
-     * JMXServiceURL url = ...;
-     * JMXConnector client = JMXConnectorFactory.connect(url);
-     * MBeanServerConnection mbsc = client.getMBeanServerConnection();
-     * mbsc = ClientContext.withDynamicContext(mbsc);
-     * 
- * - *

Then if you do this...

- * - *
-     * MBeanInfo mbi = ClientContext.doWithContext(
-     *     Collections.singletonMap(ClientContext.LOCALE_KEY, "fr"),
-     *     new {@code Callable}() {
-     *         public MBeanInfo call() {
-     *             return mbsc.getMBeanInfo(objectName);
-     *         }
-     *     });
-     * 
- * - *

...then the context with the locale set to "fr" will be in place - * when the {@code getMBeanInfo} is executed on the remote MBean Server.

- * - * @param mbsc the original MBeanServerConnection. - * - * @throws IllegalArgumentException if the {@code mbsc} parameter is null, - * or if the communication with {@code mbsc} fails, or if {@code mbsc} - * does not support contexts. If the communication with {@code mbsc} - * fails, the {@linkplain Throwable#getCause() cause} of this exception - * will be an {@code IOException}. If {@code mbsc} does not support - * contexts, the cause will be an {@link InstanceNotFoundException}. - */ - public static MBeanServerConnection withDynamicContext( - MBeanServerConnection mbsc) { - // Probe mbsc to get the right exception if it's incommunicado or - // doesn't support namespaces. - JMXNamespaces.narrowToNamespace(mbsc, NAMESPACE); - return (MBeanServerConnection) Proxy.newProxyInstance( - MBeanServerConnection.class.getClassLoader(), - new Class[] {MBeanServerConnection.class}, - new DynamicContextIH(mbsc)); - } - - private static class DynamicContextIH implements InvocationHandler { - private final MBeanServerConnection mbsc; - - public DynamicContextIH(MBeanServerConnection mbsc) { - this.mbsc = mbsc; - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - MBeanServerConnection dynMBSC = withContext( - mbsc, MBeanServerConnection.class, getContext(), false); - try { - return method.invoke(dynMBSC, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static T withContext( - T mbsc, Class mbscClass, String key, String value) { - return withContext( - mbsc, mbscClass, Collections.singletonMap(key, value), true); - } - - private static T withContext( - T mbsc, Class mbscClass, Map context, - boolean probe) { - if (mbsc == null || context == null) - throw new IllegalArgumentException("Null parameter"); - if (context.isEmpty()) - return mbsc; - validateContext(context); - Map contextMap = null; - if (mbsc.getClass() == RoutingServerProxy.class || - mbsc.getClass() == RoutingProxy.class) { - RoutingProxy nsp = (RoutingProxy) mbsc; - String where = nsp.getSourceNamespace(); - if (where.startsWith(NAMESPACE_PLUS_SEP)) { - /* Try to merge the existing context namespace with the - * new one. If it doesn't work, we fall back to just - * prefixing jmx.context//key=value, which - * might lead to a name like jmx.c//k1=v1//jmx.c//k2=v2//d:k=v. - */ - String encodedContext = - where.substring(NAMESPACE_PLUS_SEP.length()); - if (encodedContext.indexOf(NAMESPACE_SEPARATOR) < 0) { - contextMap = stringToMapOrNull(encodedContext); - if (contextMap != null) { - contextMap.putAll(context); - mbsc = mbscClass.cast(nsp.source()); - } - } - } - } - if (contextMap == null) - contextMap = context; - String contextDir = NAMESPACE_PLUS_SEP + mapToString(contextMap); - if (mbscClass == MBeanServer.class) { - return mbscClass.cast(RoutingServerProxy.cd( - (MBeanServer) mbsc, contextDir, probe)); - } else if (mbscClass == MBeanServerConnection.class) { - return mbscClass.cast(RoutingConnectionProxy.cd( - mbsc, contextDir, probe)); - } else - throw new AssertionError("Bad MBSC: " + mbscClass); - } - - /** - *

Returns an encoded context prefix for ObjectNames. - * If the given context is empty, {@code ""} is returned. - * Otherwise, this method returns a string of the form - * {@code "jmx.context//key=value;key=value;..."}. - * For example, if the context has keys {@code "jmx.locale"} - * and {@code "xid"} with respective values {@code "fr"} - * and {@code "1234"}, this method will return - * {@code "jmx.context//jmx.locale=fr;xid=1234"} or - * {@code "jmx.context//xid=1234;jmx.locale=fr"}.

- * - *

Each key and each value in the encoded string is subject to - * encoding as if by the method {@link URLEncoder#encode(String, String)} - * with a character encoding of {@code "UTF-8"}, but with the additional - * encoding of any {@code *} character as {@code "%2A"}. This ensures - * that keys and values can contain any character. Without encoding, - * characters such as {@code =} and {@code :} would pose problems.

- * - * @param context the context to encode. - * - * @return the context in encoded form. - * - * @throws IllegalArgumentException if the {@code context} parameter - * is null or if it contains a null key or value. - **/ - public static String encode(Map context) { - if (context == null) - throw new IllegalArgumentException("Null context"); - if (context.isEmpty()) - return ""; - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : context.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - if (key == null || value == null) - throw new IllegalArgumentException("Null key or value"); - if (sb.length() > 0) - sb.append(";"); - sb.append(encode(key)).append("=").append(encode(value)); - } - sb.insert(0, NAMESPACE_PLUS_SEP); - return sb.toString(); - } - - /** - *

Create a new {@link MBeanServerForwarder} that applies the context - * received from a client to the current thread. A client using - * one of the various {@code with*} methods (for example {@link - * #withContext(MBeanServerConnection, String, String) withContext}) will - * encode that context into the {@code ObjectName} of each - * {@code MBeanServer} request. The object returned by this method - * decodes the context from that {@code ObjectName} and applies it - * as described for {@link #doWithContext doWithContext} while performing - * the {@code MBeanServer} request using the {@code ObjectName} without - * the encoded context.

- * - *

This forwarder can be used in a number of ways:

- * - *
    - *
  • - *

    To add context decoding to a local {@code MBeanServer}, you can - * write:

    - *
    -     * MBeanServer mbs = {@link
    -     * java.lang.management.ManagementFactory#getPlatformMBeanServer()
    -     * ManagementFactory.getPlatformMBeanServer()};  // for example
    -     * mbs = ClientContext.newContextForwarder(mbs, null);
    -     * 
    - * - *
  • - *

    To add context decoding to a {@linkplain - * javax.management.remote.JMXConnectorServer connector server}:

    - *
    -     * JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(...);
    -     * MBeanServer nextMBS = cs.getMBeanServer();
    -     * MBeanServerForwarder mbsf = ClientContext.newContextForwarder(nextMBS, null);
    -     * cs.{@link
    -     * javax.management.remote.JMXConnectorServer#setMBeanServerForwarder
    -     * setMBeanServerForwarder}(mbsf);
    -     * 
    - * - *
  • - *

    For connectors, such as the standard RMI connector, that support - * a {@linkplain - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder - * system chain} of {@code MBeanServerForwarder}s, this forwarder will - * be installed in that chain by default. See - * {@link javax.management.remote.JMXConnectorServer#CONTEXT_FORWARDER - * JMXConnectorServer.CONTEXT_FORWARDER}. - *

    - * - *
- * - * @param nextMBS the next {@code MBeanServer} in the chain of - * forwarders, which might be another {@code MBeanServerForwarder} or - * a plain {@code MBeanServer}. This is the object to which {@code - * MBeanServer} requests that do not include a context are sent. It - * will be the value of {@link MBeanServerForwarder#getMBeanServer() - * getMBeanServer()} on the returned object, and can be changed with {@link - * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but - * must be set to a non-null value before any {@code MBeanServer} requests - * arrive. - * - * @param loopMBS the {@code MBeanServer} to which requests that contain - * an encoded context should be sent once the context has been decoded. - * For example, if the request is {@link MBeanServer#getAttribute - * getAttribute}{@code ("jmx.context//jmx.locale=fr//java.lang:type=Runtime", - * "Name")}, then the {@linkplain #getContext() context} of the thread - * executing that request will have {@code "jmx.locale"} set to {@code "fr"} - * while executing {@code loopMBS.getAttribute("java.lang:type=Runtime", - * "Name")}. If this parameter is null, then these requests will be - * sent to the newly-created {@code MBeanServerForwarder}. Usually - * the parameter will either be null or will be the result of {@link - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder - * getSystemMBeanServerForwarder()} for the connector server in which - * this forwarder will be installed. - * - * @return a new {@code MBeanServerForwarder} that decodes client context - * from {@code ObjectName}s. - */ - /* - * What we're building here is confusing enough to need a diagram. - * The MBSF that we return is actually the composition of two forwarders: - * the first one simulates the existence of the MBean - * jmx.context//:type=JMXNamespace, and the second one simulates the - * existence of the namespace jmx.context//. Furthermore, that namespace - * loops back to the composed forwarder, so that something like - * jmx.context//foo=bar//jmxcontext//baz=buh will work. And the loopback - * goes through yet another forwarder, which simulates the existence of - * (e.g.) jmx.context//foo=bar//:type=JMXNamespace, which is needed - * notably so that narrowToNamespace will work. - * - * | +--------------------------------------------------+ - * v v | - * +----------------+ | - * | Handler MBSF |->accesses to jmx.context//:type=JMXNamespace | - * +----------------+ (handled completely here) +-------------------+ - * | | 2nd Handler MBSF | - * v +-------------------+ - * +----------------+ ^ - * | Namespace MBSF |->accesses to jmx.context//**-------------------+ - * +----------------+ (after attaching context to thread) - * | - * v accesses to anything else - * - * And finally, we need to ensure that from the outside the composed object - * looks like a single forwarder, so that its get/setMBeanServer methods - * will do the expected thing. That's what the anonymous subclass is for. - */ - public static MBeanServerForwarder newContextForwarder( - MBeanServer nextMBS, MBeanServer loopMBS) { - final MBeanServerForwarder mbsWrapper = - new IdentityMBeanServerForwarder(nextMBS); - DynamicMBean handlerMBean = new StandardMBean( - new JMXNamespace(mbsWrapper), JMXNamespaceMBean.class, false); - SingleMBeanForwarder handlerForwarder = new SingleMBeanForwarder( - CLIENT_CONTEXT_NAMESPACE_HANDLER, handlerMBean, true) { - @Override - public MBeanServer getMBeanServer() { - return ((MBeanServerForwarder) super.getMBeanServer()).getMBeanServer(); - } - - @Override - public void setMBeanServer(MBeanServer mbs1) { - MBeanServerForwarder mbsf1 = (MBeanServerForwarder) - super.getMBeanServer(); - if (mbsf1 != null) - mbsf1.setMBeanServer(mbs1); - else - super.setMBeanServer(mbs1); - mbsWrapper.setMBeanServer(mbs1); - } - }; - if (loopMBS == null) - loopMBS = handlerForwarder; - ContextInvocationHandler contextIH = - new ContextInvocationHandler(nextMBS, loopMBS); - MBeanServerForwarder contextForwarder = newForwarderProxy(contextIH); - handlerForwarder.setMBeanServer(contextForwarder); - return handlerForwarder; - } - - /** - *

Create a new {@link MBeanServerForwarder} that localizes - * descriptions in {@code MBeanInfo} instances returned by - * {@link MBeanServer#getMBeanInfo getMBeanInfo}. The {@code - * MBeanServerForwarder} returned by this method passes all {@code - * MBeanServer} methods through unchanged to the supplied object, {@code - * mbs}, with the exception of {@code getMBeanInfo}. To handle {@code - * getMBeanInfo(objectName)}, it calls {@code mbs.getMBeanInfo(objectName)} - * to get an {@code MBeanInfo}, {@code mbi}; it calls {@link - * MBeanServer#getClassLoaderFor mbs.getClassLoaderFor(objectName)} to - * get a {@code ClassLoader}, {@code cl}; and it calls {@link - * #getLocale} to get a {@code Locale}, {@code locale}. The order - * of these three calls is not specified. Then the result is {@code - * mbi.localizeDescriptions(locale, loader)}.

- * - *

This forwarder can be used in a number of ways:

- * - *
    - *
  • - *

    To add description localization to a local {@code MBeanServer}, you - * can write:

    - * - *
    -     * MBeanServer mbs = {@link
    -     * java.lang.management.ManagementFactory#getPlatformMBeanServer()
    -     * ManagementFactory.getPlatformMBeanServer()};  // for example
    -     * mbs = ClientContext.newLocalizeMBeanInfoForwarder(mbs);
    -     * 
    - * - *
  • - *

    To add description localization to a {@linkplain - * javax.management.remote.JMXConnectorServer connector server}, you will - * need to add both a {@linkplain #newContextForwarder context forwarder} - * and a localization forwarder, for example like this:

    - * - *
    -     * JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(...);
    -     * MBeanServer nextMBS = cs.getMBeanServer();
    -     * MBeanServerForwarder localizeMBSF =
    -     *     ClientContext.newLocalizeMBeanInfoForwarder(nextMBS);
    -     * MBeanServerForwarder contextMBSF =
    -     *     ClientContext.newContextForwarder(localizeMBSF, null);
    -     * cs.{@link
    -     * javax.management.remote.JMXConnectorServer#setMBeanServerForwarder
    -     * setMBeanServerForwarder}(contextMBSF);
    -     * 
    - * - *

    Notice that the context forwarder must run before the localization - * forwarder, so that the locale is correctly established when the latter - * runs. So the {@code nextMBS} parameter of the context forwarder must - * be the localization forwarder, and not vice versa.

    - * - *
  • - *

    For connectors, such as the standard RMI connector, that support - * a {@linkplain - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder - * system chain} of {@code MBeanServerForwarder}s, the context forwarder and - * the localization forwarder will be installed in that chain, in the right - * order, if you include - * {@link - * javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER - * LOCALIZE_MBEAN_INFO_FORWARDER} in the environment {@code Map} with - * the value {@code "true"}, for example like this:

    - *

    - *
    -     * MBeanServer mbs = ...;
    -     * JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://...");
    -     * {@code Map} env = new {@code HashMap}();
    -     * env.put(JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER, "true");
    -     * JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
    -     *     url, env, mbs);
    -     * 
    - * - *
- * - * @param mbs the next {@code MBeanServer} in the chain of - * forwarders, which might be another {@code MBeanServerForwarder} - * or a plain {@code MBeanServer}. It will be the value of - * {@link MBeanServerForwarder#getMBeanServer() getMBeanServer()} - * on the returned object, and can be changed with {@link - * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but - * must be set to a non-null value before any {@code MBeanServer} requests - * arrive. - * - * @return a new {@code MBeanServerForwarder} that localizes descriptions - * in the result of {@code getMBeanInfo}. - */ - public static MBeanServerForwarder newLocalizeMBeanInfoForwarder( - MBeanServer mbs) { - return new IdentityMBeanServerForwarder(mbs) { - @Override - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - MBeanInfo mbi = super.getMBeanInfo(name); - Locale locale = getLocale(); - ClassLoader loader = getClassLoaderFor(name); - return mbi.localizeDescriptions(locale, loader); - } - }; - } - - private static MBeanServerForwarder newForwarderProxy(InvocationHandler ih) { - return (MBeanServerForwarder) Proxy.newProxyInstance( - MBeanServerForwarder.class.getClassLoader(), - new Class[] {MBeanServerForwarder.class}, - ih); - } - - // A proxy connection that will strip the 'contextDir' at input (routing), - // and put it back at output (createMBean / registerMBean / query* / - // getObjectInstance). Usually RoutingProxy / RoutingServerProxy are used - // the other way round (they are used for 'cd' - where they need to add - // something at input and remove it at output). - // For 'cd' operations we create RoutingProxys with a non empty sourceDir, - // and a possibly non-empty targetDir. This is the only case where we use - // RoutingProxies with an empty sourceDir (sourceDir is what we add at input - // and remove at output, targetDir is what we remove at input and add at - // output. - // - // Note that using a transient ContextRoutingConnection - // is possible only because RoutingProxys don't rewrite - // notifications sources - otherwise we would have to - // keep the ContextRoutingConnection - just to preserve - // the 'wrapping listeners' - // - private static final class ContextRoutingConnection - extends RoutingServerProxy { - public ContextRoutingConnection(MBeanServer source, - String contextDir) { - super(source, "", contextDir, false); - } - - // Not really needed - but this is safer and more optimized. - // See RoutingProxy for more details. - // - @Override - public Integer getMBeanCount() { - return source().getMBeanCount(); - } - - // Not really needed - but this is safer and more optimized. - // See RoutingProxy for more details. - // - @Override - public String[] getDomains() { - return source().getDomains(); - } - - // Not really needed - but this is safer and more optimized. - // See RoutingProxy for more details. - // - @Override - public String getDefaultDomain() { - return source().getDefaultDomain(); - } - - } - - private static class ContextInvocationHandler implements InvocationHandler { - /* - * MBeanServer requests that don't include jmx.context//foo=bar// - * are forwarded to forwardMBS, which is the unadorned MBeanServer - * that knows nothing about the context namespace. - * MBeanServer requests that do include this prefix will - * usually (depending on the value of the loopMBS parameter to - * newContextForwarder) loop back to the combined MBeanServerForwarder - * that first implements - * jmx.context//:type=JMXNamespace and then implements - * jmx.context//foo=bar//. The reason is that it is valid - * to have jmx.context//foo=bar//jmx.context//baz=buh//, although - * usually that will be combined into jmx.context//foo=bar;baz=buh//. - * - * Before forwarding to loopMBS, we must check for :type=JMXNamespace - * so that jmx.context//foo=bar//:type=JMXNamespace will exist. Its - * existence is partial because it must remain "invisible": it should - * not show up in queryNames or getMBeanCount even though it does - * accept getAttribute and isRegistered and all other methods that - * reference a single MBean. - */ - private MBeanServer forwardMBS; - private final MBeanServer loopMBS; - private static final MBeanServer emptyMBS = new MBeanServerSupport() { - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - throw new InstanceNotFoundException(name.toString()); - } - - @Override - protected Set getNames() { - return Collections.emptySet(); - } - }; - - ContextInvocationHandler(MBeanServer forwardMBS, MBeanServer loopMBS) { - this.forwardMBS = forwardMBS; - DynamicMBean handlerMBean = new StandardMBean( - new JMXNamespace(loopMBS), JMXNamespaceMBean.class, false); - MBeanServerForwarder handlerMBS = new SingleMBeanForwarder( - NAMESPACE_HANDLER_WITHOUT_NAMESPACE, handlerMBean, false); - handlerMBS.setMBeanServer(loopMBS); - this.loopMBS = handlerMBS; - } - - public Object invoke(Object proxy, final Method method, final Object[] args) - throws Throwable { - String methodName = method.getName(); - Class[] paramTypes = method.getParameterTypes(); - - // If this is a method from MBeanServerForwarder, handle it here. - // There are only two such methods: getMBeanServer() and - // setMBeanServer(mbs). - if (methodName.equals("getMBeanServer")) - return forwardMBS; - else if (methodName.equals("setMBeanServer")) { - this.forwardMBS = (MBeanServer) args[0]; - return null; - } - - // It is a method from MBeanServer. - // Find the first parameter whose declared type is ObjectName, - // and see if it is in the context namespace. If so we need to - // trigger the logic for that namespace. If not, we simply - // forward to the next MBeanServer in the chain. This logic - // depends on the fact that if a method in the MBeanServer interface - // has a "routing" ObjectName parameter, it is always the first - // parameter of that type. Conversely, if a method has an - // ObjectName parameter, then it makes sense to "route" that - // method. Except for deserialize and instantiate, but if we - // recognize a context namespace in those methods' ObjectName - // parameters it is pretty harmless. - int objectNameI = -1; - for (int i = 0; i < paramTypes.length; i++) { - if (paramTypes[i] == ObjectName.class) { - objectNameI = i; - break; - } - } - - if (objectNameI < 0) - return invoke(method, forwardMBS, args); - - ObjectName target = (ObjectName) args[objectNameI]; - if (target == null || - !target.getDomain().startsWith(NAMESPACE_PLUS_SEP)) - return invoke(method, forwardMBS, args); - - String domain = target.getDomain().substring(NAMESPACE_PLUS_SEP.length()); - - // The method routes through the (simulated) context namespace. - // Decode the context after it, e.g. jmx.context//jmx.locale=fr//... - // If there is no context part, we can throw an exception, - // because a forwarder has already handled the unique MBean - // jmx.context//:type=JMXNamespace. - int sep = domain.indexOf(NAMESPACE_SEPARATOR); - if (sep < 0) - return invoke(method, emptyMBS, args); // throw exception - final String encodedContext = domain.substring(0, sep); - - if (method.getName().startsWith("query") && - (encodedContext.contains("*") || encodedContext.contains("?"))) { - // Queries like jmx.context//*//d:k=v return - // an empty set, consistent with "real" namespaces. - return Collections.EMPTY_SET; - } - - Map ctx = new TreeMap(getContext()); - ctx.putAll(stringToMap(encodedContext)); - - return doWithContext(ctx, new Callable() { - public Object call() throws Exception { - // Create a proxy connection that will strip - // "jmx.context//" + encodedContext + "//" on input, - // and put it back on output. - // - // Note that using a transient ContextRoutingConnection - // is possible only because it doesn't rewrite - // notification sources - otherwise we would have to - // keep the ContextRoutingConnection - just to preserve - // the 'wrapping listeners' - // - String namespace = NAMESPACE_PLUS_SEP + encodedContext; - final ContextRoutingConnection route = - new ContextRoutingConnection(loopMBS, namespace); - - if (LOG.isLoggable(Level.FINE)) - LOG.fine("context="+encodedContext); - if (LOG.isLoggable(Level.FINER)) - LOG.finer(method.getName()+""+ - ((args==null)?"()":(""+Arrays.asList(args)))); - - return invoke(method, route, args); - } - }); - } - - private static Object invoke(Method method, Object target, Object[] args) - throws Exception { - try { - return method.invoke(target, args); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof Error) - throw (Error) cause; - throw (Exception) cause; - } - } - } - - private static String mapToString(Map map) { - StringBuilder sb = new StringBuilder(); - for (Map.Entry entry : map.entrySet()) { - String key = encode(entry.getKey()); - String value = encode(entry.getValue()); - if (sb.length() > 0) - sb.append(";"); - sb.append(key).append("=").append(value); - } - return sb.toString(); - } - - private static Map stringToMap(String encodedContext) { - Map map = stringToMapOrNull(encodedContext); - if (map == null) { - throw new IllegalArgumentException( - "Invalid encoded context: " + encodedContext); - } - return map; - } - - private static Map stringToMapOrNull(String encodedContext) { - Map map = new LinkedHashMap(); - StringTokenizer stok = new StringTokenizer(encodedContext, ";"); - while (stok.hasMoreTokens()) { - String tok = stok.nextToken(); - int eq = tok.indexOf('='); - if (eq < 0) - return null; - String key = decode(tok.substring(0, eq)); - if (key.equals("")) - return null; - String value = decode(tok.substring(eq + 1)); - map.put(key, value); - } - return map; - } - - private static String encode(String s) { - try { - s = URLEncoder.encode(s, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); // Should not happen - } - return s.replace("*", "%2A"); - // The * character is left intact in URL encodings, but for us it - // is special (an ObjectName wildcard) so we must map it. - // We are assuming that URLDecoder will decode it the same way as any - // other hex escape. - } - - private static String decode(String s) { - try { - return URLDecoder.decode(s, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } -} diff --git a/src/share/classes/javax/management/Description.java b/src/share/classes/javax/management/Description.java deleted file mode 100644 index 3232054a8..000000000 --- a/src/share/classes/javax/management/Description.java +++ /dev/null @@ -1,180 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.ResourceBundle; - -/** - *

The textual description of an MBean or part of an MBean. This - * description is intended to be displayed to users to help them - * understand what the MBean does. Ultimately it will be the value of - * the {@code getDescription()} method of an {@link MBeanInfo}, {@link - * MBeanAttributeInfo}, or similar.

- * - *

This annotation applies to Standard MBean interfaces and to - * MXBean interfaces, as well as to MBean classes defined using the - * {@link MBean @MBean} or {@link MXBean @MXBean} annotations. For - * example, a Standard MBean might be defined like this:

- * - *
- * {@code @Description}("Application configuration")
- * public interface ConfigurationMBean {
- *     {@code @Description}("Cache size in bytes")
- *     public int getCacheSize();
- *     public void setCacheSize(int size);
- *
- *     {@code @Description}("Last time the configuration was changed, " +
- *                  "in milliseconds since 1 Jan 1970")
- *     public long getLastChangedTime();
- *
- *     {@code @Description}("Save the configuration to a file")
- *     public void save(
- *         {@code @Description}("Optional name of the file, or null for the default name")
- *         String fileName);
- * }
- * 
- * - *

The {@code MBeanInfo} for this MBean will have a {@link - * MBeanInfo#getDescription() getDescription()} that is {@code - * "Application configuration"}. It will contain an {@code - * MBeanAttributeInfo} for the {@code CacheSize} attribute that is - * defined by the methods {@code getCacheSize} and {@code - * setCacheSize}, and another {@code MBeanAttributeInfo} for {@code - * LastChangedTime}. The {@link MBeanAttributeInfo#getDescription() - * getDescription()} for {@code CacheSize} will be {@code "Cache size - * in bytes"}. Notice that there is no need to add a - * {@code @Description} to both {@code getCacheSize} and {@code - * setCacheSize} - either alone will do. But if you do add a - * {@code @Description} to both, it must be the same.

- * - *

The {@code MBeanInfo} will also contain an {@link - * MBeanOperationInfo} where {@link - * MBeanOperationInfo#getDescription() getDescription()} is {@code - * "Save the configuration to a file"}. This {@code - * MBeanOperationInfo} will contain an {@link MBeanParameterInfo} - * where {@link MBeanParameterInfo#getDescription() getDescription()} - * is {@code "Optional name of the file, or null for the default - * name"}.

- * - *

The {@code @Description} annotation can also be applied to the - * public constructors of the implementation class. Continuing the - * above example, the {@code Configuration} class implementing {@code - * ConfigurationMBean} might look like this:

- * - *
- * public class Configuration implements ConfigurationMBean {
- *     {@code @Description}("A Configuration MBean with the default file name")
- *     public Configuration() {
- *         this(DEFAULT_FILE_NAME);
- *     }
- *
- *     {@code @Description}("A Configuration MBean with a specified file name")
- *     public Configuration(
- *         {@code @Description}("Name of the file the configuration is stored in")
- *         String fileName) {...}
- *     ...
- * }
- * 
- * - *

The {@code @Description} annotation also works in MBeans that - * are defined using the {@code @MBean} or {@code @MXBean} annotation - * on classes. Here is an alternative implementation of {@code - * Configuration} that does not use an {@code ConfigurationMBean} - * interface.

- * - *
- * {@code @MBean}
- * {@code @Description}("Application configuration")
- * public class Configuration {
- *     {@code @Description}("A Configuration MBean with the default file name")
- *     public Configuration() {
- *         this(DEFAULT_FILE_NAME);
- *     }
- *
- *     {@code @Description}("A Configuration MBean with a specified file name")
- *     public Configuration(
- *         {@code @Description}("Name of the file the configuration is stored in")
- *         String fileName) {...}
- *
- *     {@code @ManagedAttribute}
- *     {@code @Description}("Cache size in bytes")
- *     public int getCacheSize() {...}
- *     {@code @ManagedAttribute}
- *     public void setCacheSize(int size) {...}
- *
- *     {@code @ManagedOperation}
- *     {@code @Description}("Last time the configuration was changed, " +
- *                  "in milliseconds since 1 Jan 1970")
- *     public long getLastChangedTime() {...}
- *
- *     {@code @ManagedOperation}
- *     {@code @Description}("Save the configuration to a file")
- *     public void save(
- *         {@code @Description}("Optional name of the file, or null for the default name")
- *         String fileName) {...}
- *     ...
- * }
- * 
- */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, - ElementType.TYPE}) -public @interface Description { - /** - *

The description.

- */ - String value(); - - /** - *

The base name for the {@link ResourceBundle} in which the key given in - * the {@code descriptionResourceKey} field can be found, for example - * {@code "com.example.myapp.MBeanResources"}. If a non-default value - * is supplied for this element, it will appear in the - * {@code Descriptor} for the annotated item.

- */ - @DescriptorKey( - value = "descriptionResourceBundleBaseName", omitIfDefault = true) - String bundleBaseName() default ""; - - /** - *

A resource key for the description of this element. In - * conjunction with the {@link #bundleBaseName bundleBaseName}, - * this can be used to find a localized version of the description. - * If a non-default value - * is supplied for this element, it will appear in the - * {@code Descriptor} for the annotated item.

- */ - @DescriptorKey(value = "descriptionResourceKey", omitIfDefault = true) - String key() default ""; -} diff --git a/src/share/classes/javax/management/Descriptor.java b/src/share/classes/javax/management/Descriptor.java index 573f8fdbe..afae81b37 100644 --- a/src/share/classes/javax/management/Descriptor.java +++ b/src/share/classes/javax/management/Descriptor.java @@ -38,7 +38,6 @@ import java.util.Arrays; import java.util.Locale; import java.util.ResourceBundle; import javax.management.openmbean.CompositeData; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanOperationInfoSupport; import javax.management.openmbean.OpenMBeanParameterInfoSupport; @@ -118,22 +117,23 @@ import javax.management.openmbean.OpenType; * deprecation, for example {@code "1.3 Replaced by the Capacity * attribute"}. * - * descriptionResource
- * BundleBaseName
StringAny + * descriptionResource
+ * BundleBaseNameStringAny * * The base name for the {@link ResourceBundle} in which the key given in * the {@code descriptionResourceKey} field can be found, for example - * {@code "com.example.myapp.MBeanResources"}. See - * {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}. + * {@code "com.example.myapp.MBeanResources"}. The meaning of this + * field is defined by this specification but the field is not set or + * used by the JMX API itself. * - * descriptionResourceKey + * descriptionResourceKey * StringAny * * A resource key for the description of this element. In * conjunction with the {@code descriptionResourceBundleBaseName}, * this can be used to find a localized version of the description. - * See {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}. - * + * The meaning of this field is defined by this specification but the + * field is not set or used by the JMX API itself. * * enabledString * MBeanAttributeInfo
MBeanNotificationInfo
MBeanOperationInfo @@ -147,31 +147,16 @@ import javax.management.openmbean.OpenType; * might be disabled if it cannot currently be emitted but could be in * other circumstances. * - * exceptionsString[] + * exceptionsString[] * MBeanAttributeInfo, MBeanConstructorInfo, MBeanOperationInfo * * The class names of the exceptions that can be thrown when invoking a - * constructor or operation, or getting an attribute. Exceptions thrown when + * constructor or operation, or getting an attribute. The meaning of this field + * is defined by this specification but the field is not set or used by the + * JMX API itself. Exceptions thrown when * setting an attribute are specified by the field * {@code setExceptions}. * - * exceptionErrorCodesString[] - * MBeanAttributeInfo
MBeanConstructorInfo
MBeanOperationInfo - * - * The {@linkplain GenericMBeanException#getErrorCode() error codes} - * that can appear in a {@link GenericMBeanException} thrown when getting - * this attribute or invoking this operation or constructor. See also - * {@code setExceptionErrorCodes}. - * - * exceptionUserDataTypes - * {@link javax.management.openmbean.CompositeType}[] - * MBeanAttributeInfo
MBeanConstructorInfo
MBeanOperationInfo - * - * The types of {@linkplain GenericMBeanException#getUserData() userData} - * that can appear in a {@link GenericMBeanException} thrown when getting - * this attribute or invoking this operation or constructor. See also - * {@code setExceptionUserDataTypes}. - * * immutableInfoString * MBeanInfo * @@ -213,7 +198,7 @@ import javax.management.openmbean.OpenType; * Legal values for an attribute or parameter. See * {@link javax.management.openmbean}. * - * locale + * locale * StringAny * * The {@linkplain Locale locale} of the description in this @@ -254,21 +239,6 @@ import javax.management.openmbean.OpenType; * StandardMBean} class will have this field in its MBeanInfo * Descriptor. * - * mxbeanMappingFactoryClass - * String - * MBeanInfo - * - * The name of the {@link MXBeanMappingFactory} class that was used for this - * MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default} - * one. - * - * objectNameTemplate - * String - * MBeanInfo - * - * The template to use to name this MBean. Its value must be compliant with - * the specification of the {@link ObjectNameTemplate} annotation. - * * openType{@link OpenType} * MBeanAttributeInfo
MBeanOperationInfo
MBeanParameterInfo * @@ -306,26 +276,11 @@ import javax.management.openmbean.OpenType; * MBeanAttributeInfo * * The class names of the exceptions that can be thrown when setting - * an attribute. Exceptions thrown when getting an attribute are specified + * an attribute. The meaning of this field + * is defined by this specification but the field is not set or used by the + * JMX API itself. Exceptions thrown when getting an attribute are specified * by the field {@code exceptions}. * - * setExceptionErrorCodes - * String[]MBeanAttributeInfo - * - * The {@linkplain GenericMBeanException#getErrorCode() error codes} - * that can appear in a {@link GenericMBeanException} thrown when setting - * this attribute. See also - * {@code exceptionErrorCodes}. - * - * setExceptionUserDataTypes - * {@link javax.management.openmbean.CompositeType}[] - * MBeanAttributeInfo - * - * The types of {@linkplain GenericMBeanException#getUserData() userData} - * that can appear in a {@link GenericMBeanException} thrown when setting - * this attribute. See also - * {@code exceptionUserDataTypes}. - * * severityString
Integer * MBeanNotificationInfo * diff --git a/src/share/classes/javax/management/DescriptorFields.java b/src/share/classes/javax/management/DescriptorFields.java deleted file mode 100644 index 126425326..000000000 --- a/src/share/classes/javax/management/DescriptorFields.java +++ /dev/null @@ -1,137 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

Annotation that adds fields to a {@link Descriptor}. This can be the - * Descriptor for an MBean, or for an attribute, operation, or constructor - * in an MBean, or for a parameter of an operation or constructor.

- * - *

Consider this Standard MBean interface, for example:

- * - *
- * public interface CacheControlMBean {
- *     @DescriptorFields("units=bytes")
- *     public long getCacheSize();
- * }
- * 
- * - *

When a Standard MBean is made using this interface, the usual rules - * mean that it will have an attribute called {@code CacheSize} of type - * {@code long}. The {@code DescriptorFields} annotation will ensure - * that the {@link MBeanAttributeInfo} for this attribute will have a - * {@code Descriptor} that has a field called {@code units} with - * corresponding value {@code bytes}.

- * - *

Similarly, if the interface looks like this:

- * - *
- * public interface CacheControlMBean {
- *     @DescriptorFields({"units=bytes", "since=1.5"})
- *     public long getCacheSize();
- * }
- * 
- * - *

then the resulting {@code Descriptor} will contain the following - * fields:

- * - * - * - * - * - *
NameValue
units"bytes"
since"1.5"
- * - *

The {@code @DescriptorFields} annotation can be applied to:

- * - *
    - *
  • a Standard MBean or MXBean interface; - *
  • a method in such an interface; - *
  • a parameter of a method in a Standard MBean or MXBean interface - * when that method is an operation (not a getter or setter for an attribute); - *
  • a public constructor in the class that implements a Standard MBean - * or MXBean; - *
  • a parameter in such a constructor. - *
- * - *

Other uses of the annotation will either fail to compile or be - * ignored.

- * - *

Interface annotations are checked only on the exact interface - * that defines the management interface of a Standard MBean or an - * MXBean, not on its parent interfaces. Method annotations are - * checked only in the most specific interface in which the method - * appears; in other words, if a child interface overrides a method - * from a parent interface, only {@code @DescriptorFields} annotations in - * the method in the child interface are considered. - * - *

The Descriptor fields contributed in this way must be consistent - * with each other and with any fields contributed by {@link - * DescriptorKey @DescriptorKey} annotations. That is, two - * different annotations, or two members of the same annotation, must - * not define a different value for the same Descriptor field. Fields - * from annotations on a getter method must also be consistent with - * fields from annotations on the corresponding setter method.

- * - *

The Descriptor resulting from these annotations will be merged - * with any Descriptor fields provided by the implementation, such as - * the {@code - * immutableInfo} field for an MBean. The fields from the annotations - * must be consistent with these fields provided by the implementation.

- * - *

{@literal @DescriptorFields and @DescriptorKey}

- * - *

The {@link DescriptorKey @DescriptorKey} annotation provides - * another way to use annotations to define Descriptor fields. - * @DescriptorKey requires more work but is also more - * robust, because there is less risk of mistakes such as misspelling - * the name of the field or giving an invalid value. - * @DescriptorFields is more convenient but includes - * those risks. @DescriptorFields is more - * appropriate for occasional use, but for a Descriptor field that you - * add in many places, you should consider a purpose-built annotation - * using @DescriptorKey. - * - * @since 1.7 - */ -@Documented -@Inherited // for @MBean and @MXBean classes -@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, - ElementType.PARAMETER, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface DescriptorFields { - /** - *

The descriptor fields. Each element of the string looks like - * {@code "name=value"}.

- */ - public String[] value(); -} diff --git a/src/share/classes/javax/management/DescriptorKey.java b/src/share/classes/javax/management/DescriptorKey.java index 7646862ce..e1fc046f1 100644 --- a/src/share/classes/javax/management/DescriptorKey.java +++ b/src/share/classes/javax/management/DescriptorKey.java @@ -33,11 +33,6 @@ import java.lang.annotation.*; * an MBean, or for an attribute, operation, or constructor in an * MBean, or for a parameter of an operation or constructor.

* - *

(The {@link DescriptorFields @DescriptorFields} annotation - * provides another way to add fields to a {@code Descriptor}. See - * the documentation for that annotation for a comparison of the - * two possibilities.)

- * *

Consider this annotation for example:

* *
@@ -130,13 +125,12 @@ import java.lang.annotation.*;
  * the method in the child interface are considered.
  *
  * 

The Descriptor fields contributed in this way by different - * annotations on the same program element must be consistent with - * each other and with any fields contributed by a {@link - * DescriptorFields @DescriptorFields} annotation. That is, two - * different annotations, or two members of the same annotation, must - * not define a different value for the same Descriptor field. Fields - * from annotations on a getter method must also be consistent with - * fields from annotations on the corresponding setter method.

+ * annotations on the same program element must be consistent. That + * is, two different annotations, or two members of the same + * annotation, must not define a different value for the same + * Descriptor field. Fields from annotations on a getter method must + * also be consistent with fields from annotations on the + * corresponding setter method.

* *

The Descriptor resulting from these annotations will be merged * with any Descriptor fields provided by the implementation, such as @@ -175,36 +169,4 @@ import java.lang.annotation.*; @Target(ElementType.METHOD) public @interface DescriptorKey { String value(); - - /** - *

Do not include this field in the Descriptor if the annotation - * element has its default value. For example, suppose {@code @Units} is - * defined like this:

- * - *
-     * @Documented
-     * @Target(ElementType.METHOD)
-     * @Retention(RetentionPolicy.RUNTIME)
-     * public @interface Units {
-     *     @DescriptorKey("units")
-     *     String value();
-     *
-     *     @DescriptorKey(value = "descriptionResourceKey",
-     *                    omitIfDefault = true)
-     *     String resourceKey() default "";
-     *
-     *     @DescriptorKey(value = "descriptionResourceBundleBaseName",
-     *                    omitIfDefault = true)
-     *     String resourceBundleBaseName() default "";
-     * }
-     * 
- * - *

Then consider a usage such as {@code @Units("bytes")} or - * {@code @Units(value = "bytes", resourceKey = "")}, where the - * {@code resourceKey} and {@code resourceBundleBaseNames} elements - * have their default values. In this case the Descriptor resulting - * from these annotations will not include a {@code descriptionResourceKey} - * or {@code descriptionResourceBundleBaseName} field.

- */ - boolean omitIfDefault() default false; } diff --git a/src/share/classes/javax/management/DynamicWrapperMBean.java b/src/share/classes/javax/management/DynamicWrapperMBean.java deleted file mode 100644 index 45d2f17cf..000000000 --- a/src/share/classes/javax/management/DynamicWrapperMBean.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2005-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 javax.management; - -/** - *

An MBean can implement this interface to affect how the MBeanServer's - * {@link MBeanServer#getClassLoaderFor getClassLoaderFor} and - * {@link MBeanServer#isInstanceOf isInstanceOf} methods behave. - * If these methods should refer to a wrapped object rather than the - * MBean object itself, then the {@link #getWrappedObject} method should - * return that wrapped object.

- * - * @see MBeanServer#getClassLoaderFor - * @see MBeanServer#isInstanceOf - */ -public interface DynamicWrapperMBean extends DynamicMBean { - /** - *

The resource corresponding to this MBean. This is the object whose - * class name should be reflected by the MBean's - * {@link MBeanServer#getMBeanInfo getMBeanInfo()}.{@link MBeanInfo#getClassName getClassName()} for example. For a "plain" - * DynamicMBean it will be "this". For an MBean that wraps another - * object, in the manner of {@link javax.management.StandardMBean}, it will be the - * wrapped object.

- * - * @return The resource corresponding to this MBean. - */ - public Object getWrappedObject(); - - /** - *

The {@code ClassLoader} for this MBean, which can be used to - * retrieve resources associated with the MBean for example. Usually, - * it will be - * {@link #getWrappedObject()}.{@code getClass().getClassLoader()}. - * - * @return The {@code ClassLoader} for this MBean. - */ - public ClassLoader getWrappedClassLoader(); -} diff --git a/src/share/classes/javax/management/GenericMBeanException.java b/src/share/classes/javax/management/GenericMBeanException.java deleted file mode 100644 index dd0f96e78..000000000 --- a/src/share/classes/javax/management/GenericMBeanException.java +++ /dev/null @@ -1,276 +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 javax.management; - -import javax.management.openmbean.CompositeData; - -/** - *

A customizable exception that has an optional error code string and - * payload. By using this exception in an MBean, you can avoid requiring - * clients of the MBean to have custom exception classes.

- * - *

An instance of this class has an optional {@linkplain #getErrorCode() - * error code}, and an optional {@linkplain #getUserData() payload} known as - * {@code userData}. This allows you to distinguish between different - * sorts of exception while still using this class for all of them.

- * - *

To produce a suitable {@code userData}, it is often simplest to use - * the MXBean framework. For example, suppose you want to convey a severity - * and a subsystem with your exception, which are respectively an int and a - * String. You could define a class like this:

- * - *
- * public class ExceptionDetails {
- *     private final int severity;
- *     private final String subsystem;
- *
- *     {@link java.beans.ConstructorProperties @ConstructorProperties}({"severity", "subsystem"})
- *     public ExceptionDetails(int severity, String subsystem) {
- *         this.severity = severity;
- *         this.subsystem = subsystem;
- *     }
- *
- *     public int getSeverity() {
- *         return severity;
- *     }
- *
- *     public String getSubsystem() {
- *         return subsystem;
- *     }
- * }
- * 
- * - *

Then you can get the MXBean framework to transform {@code ExceptionDetails} - * into {@link CompositeData} like this:

- * - *
- * static final {@link javax.management.openmbean.MXBeanMapping MXBeanMapping} exceptionDetailsMapping = {@link javax.management.openmbean.MXBeanMappingFactory#DEFAULT
- *     MXBeanMappingFactory.DEFAULT}.mappingForType(
- *         ExceptionDetails.class, MXBeanMappingFactory.DEFAULT);
- *
- * public static GenericMBeanException newGenericMBeanException(
- *         String message, String errorCode, int severity, String subsystem) {
- *     ExceptionDetails details = new ExceptionDetails(severity, subsystem);
- *     CompositeData userData = (CompositeData)
- *             exceptionDetailsMapping.toOpenValue(details);
- *     return new GenericMBeanException(
- *             message, errorCode, userData, (Throwable) null);
- * }
- *
- * ...
- *     throw newGenericMBeanException(message, errorCode, 25, "foosystem");
- * 
- * - *

A client that knows the {@code ExceptionDetails} class can convert - * back from the {@code userData} of a {@code GenericMBeanException} - * that was generated as above:

- * - *
- * ...
- *     try {
- *         mbeanProxy.foo();
- *     } catch (GenericMBeanException e) {
- *         CompositeData userData = e.getUserData();
- *         ExceptionDetails details = (ExceptionDetails)
- *                 exceptionDetailsMapping.fromOpenValue(userData);
- *         System.out.println("Exception Severity: " + details.getSeverity());
- *     }
- * ...
- * 
- * - *

The Descriptor field exceptionErrorCodes can be used to specify in the - * {@link MBeanOperationInfo} for an operation what the possible - * {@linkplain #getErrorCode() error codes} are when that operation throws - * {@code GenericMBeanException}. It can also be used in an {@link - * MBeanConstructorInfo} or {@link MBeanAttributeInfo} to specify what the - * possible error codes are for {@code GenericMBeanException} when invoking - * that constructor or getting that attribute, respectively. The field - * setExceptionErrorCodes can be used to specify what the possible - * error codes are when setting an attribute.

- * - *

You may want to use the {@link DescriptorKey @DescriptorKey} facility - * to define annotations that allow you to specify the error codes. If you - * define...

- * - *
- * {@link java.lang.annotation.Documented @Documented}
- * {@link java.lang.annotation.Target @Target}(ElementType.METHOD)
- * {@link java.lang.annotation.Retention @Retention}(RetentionPolicy.RUNTIME)
- * public @interface ErrorCodes {
- *     @DescriptorKey("exceptionErrorCodes")
- *     String[] value();
- * }
- * 
- * - *

...then you can write MBean interfaces like this...

- * - *
- * public interface FooMBean {  // or FooMXBean
- *     @ErrorCodes({"com.example.bad", "com.example.worse"})
- *     public void foo() throws GenericMBeanException;
- * }
- * 
- * - *

The Descriptor field exceptionUserDataTypes can be used to specify in the - * {@link MBeanOperationInfo} for an operation what the possible types of - * {@linkplain #getUserData() userData} are when that operation throws - * {@code GenericMBeanException}. It is an array of - * {@link javax.management.openmbean.CompositeType CompositeType} values - * describing the possible {@link CompositeData} formats. This field can also be used - * in an {@link MBeanConstructorInfo} or {@link MBeanAttributeInfo} to specify - * the possible types of user data for {@code GenericMBeanException} when - * invoking that constructor or getting that attribute, respectively. The - * field - * setExceptionUserDataTypes - * can be used to specify the possible types of user data for exceptions when - * setting an attribute. If a Descriptor has both {@code exceptionErrorCodes} - * and {@code exceptionUserDataTypes} then the two arrays should be the - * same size; each pair of corresponding elements describes one kind - * of exception. Similarly for {@code setExceptionErrorCodes} and {@code - * setExceptionUserDataTypes}. - * - * - *

Serialization

- * - *

For compatibility reasons, instances of this class are serialized as - * instances of {@link MBeanException}. Special logic in that class converts - * them back to instances of this class at deserialization time. If the - * serialized object is deserialized in an earlier version of the JMX API - * that does not include this class, then it will appear as just an {@code - * MBeanException} and the error code or userData will not be available.

- * - * @since 1.7 - */ -public class GenericMBeanException extends MBeanException { - private static final long serialVersionUID = -1560202003985932823L; - - /** - *

Constructs a new {@code GenericMBeanException} with the given - * detail message. This constructor is - * equivalent to {@link #GenericMBeanException(String, String, - * CompositeData, Throwable) GenericMBeanException(message, "", - * null, null)}.

- * - * @param message the exception detail message. - */ - public GenericMBeanException(String message) { - this(message, "", null, null); - } - - /** - *

Constructs a new {@code GenericMBeanException} with the given - * detail message and cause. This constructor is - * equivalent to {@link #GenericMBeanException(String, String, - * CompositeData, Throwable) GenericMBeanException(message, "", - * null, cause)}.

- * - * @param message the exception detail message. - * @param cause the cause of this exception. Can be null. - */ - public GenericMBeanException(String message, Throwable cause) { - this(message, "", null, cause); - } - - /** - *

Constructs a new {@code GenericMBeanException} with the given - * detail message, error code, and user data. This constructor is - * equivalent to {@link #GenericMBeanException(String, String, - * CompositeData, Throwable) GenericMBeanException(message, errorCode, - * userData, null)}.

- * - * @param message the exception detail message. - * @param errorCode the exception error code. Specifying a null value - * is equivalent to specifying an empty string. It is recommended to use - * the same reverse domain name convention as package names, for example - * "com.example.foo.UnexpectedFailure". There is no requirement that the - * error code be a syntactically valid Java identifier. - * @param userData extra information about the exception. Can be null. - */ - public GenericMBeanException( - String message, String errorCode, CompositeData userData) { - this(message, errorCode, userData, null); - } - - /** - *

Constructs a new {@code GenericMBeanException} with the given - * detail message, error code, user data, and cause.

- * - * @param message the exception detail message. - * @param errorCode the exception error code. Specifying a null value - * is equivalent to specifying an empty string. It is recommended to use - * the same reverse domain name convention as package names, for example - * "com.example.foo.UnexpectedFailure". There is no requirement that the - * error code be a syntactically valid Java identifier. - * @param userData extra information about the exception. Can be null. - * @param cause the cause of this exception. Can be null. - */ - public GenericMBeanException( - String message, String errorCode, CompositeData userData, - Throwable cause) { - super(message, (errorCode == null) ? "" : errorCode, userData, cause); - } - - /** - *

Returns the error code of this exception.

- * - * @return the error code. This value is never null. - */ - public String getErrorCode() { - return errorCode; - } - - /** - *

Returns the userData of this exception.

- * - * @return the userData. Can be null. - */ - public CompositeData getUserData() { - return userData; - } - - /** - *

Instances of this class are serialized as instances of - * {@link MBeanException}. {@code MBeanException} has private fields that can - * not be set by its public constructors. They can only be set in objects - * returned by this method. When an {@code MBeanException} instance is - * deserialized, if those fields are present then its {@code readResolve} - * method will substitute a {@code GenericMBeanException} equivalent to - * this one.

- */ - Object writeReplace() { - MBeanException x = new MBeanException( - getMessage(), errorCode, userData, getCause()); - x.setStackTrace(this.getStackTrace()); - return x; - } -} diff --git a/src/share/classes/javax/management/Impact.java b/src/share/classes/javax/management/Impact.java deleted file mode 100644 index a922e20ae..000000000 --- a/src/share/classes/javax/management/Impact.java +++ /dev/null @@ -1,105 +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 javax.management; - -/** - *

Defines the impact of an MBean operation, in particular whether it - * has an effect on the MBean or simply returns information. This enum - * is used in the {@link ManagedOperation @ManagedOperation} annotation. - * Its {@link #getCode()} method can be used to get an {@code int} suitable - * for use as the {@code impact} parameter in an {@link MBeanOperationInfo} - * constructor.

- */ -public enum Impact { - /** - * The operation is read-like: it returns information but does not change - * any state. - * @see MBeanOperationInfo#INFO - */ - INFO(MBeanOperationInfo.INFO), - - /** - * The operation is write-like: it has an effect but does not return - * any information from the MBean. - * @see MBeanOperationInfo#ACTION - */ - ACTION(MBeanOperationInfo.ACTION), - - /** - * The operation is both read-like and write-like: it has an effect, - * and it also returns information from the MBean. - * @see MBeanOperationInfo#ACTION_INFO - */ - ACTION_INFO(MBeanOperationInfo.ACTION_INFO), - - /** - * The impact of the operation is unknown or cannot be expressed - * using one of the other values. - * @see MBeanOperationInfo#UNKNOWN - */ - UNKNOWN(MBeanOperationInfo.UNKNOWN); - - private final int code; - - /** - * An instance of this enumeration, with the corresponding {@code int} - * code used by the {@link MBeanOperationInfo} constructors. - * - * @param code the code used by the {@code MBeanOperationInfo} constructors. - */ - Impact(int code) { - this.code = code; - } - - /** - * The equivalent {@code int} code used by the {@link MBeanOperationInfo} - * constructors. - * @return the {@code int} code. - */ - public int getCode() { - return code; - } - - /** - * Return the {@code Impact} value corresponding to the given {@code int} - * code. The {@code code} is the value that would be used in an - * {@code MBeanOperationInfo} constructor. - * - * @param code the {@code int} code. - * - * @return an {@code Impact} value {@code x} such that - * {@code code == x.}{@link #getCode()}, or {@code Impact.UNKNOWN} - * if there is no such value. - */ - public static Impact forCode(int code) { - switch (code) { - case MBeanOperationInfo.ACTION: return ACTION; - case MBeanOperationInfo.INFO: return INFO; - case MBeanOperationInfo.ACTION_INFO: return ACTION_INFO; - default: return UNKNOWN; - } - } -} diff --git a/src/share/classes/javax/management/InstanceNotFoundException.java b/src/share/classes/javax/management/InstanceNotFoundException.java index 0b992d344..f572d614d 100644 --- a/src/share/classes/javax/management/InstanceNotFoundException.java +++ b/src/share/classes/javax/management/InstanceNotFoundException.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2003 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 @@ -51,16 +51,4 @@ public class InstanceNotFoundException extends OperationsException { public InstanceNotFoundException(String message) { super(message); } - - /** - * Constructor for the frequent case where the message is the ObjectName - * of the missing MBean. - * - * @param name the ObjectName of the missing MBean. - * - * @since 1.7 - */ - public InstanceNotFoundException(ObjectName name) { - this(String.valueOf(name)); - } } diff --git a/src/share/classes/javax/management/JMRuntimeException.java b/src/share/classes/javax/management/JMRuntimeException.java index 69c3cd541..d34529b51 100644 --- a/src/share/classes/javax/management/JMRuntimeException.java +++ b/src/share/classes/javax/management/JMRuntimeException.java @@ -58,22 +58,6 @@ public class JMRuntimeException extends RuntimeException { * specification. A later version may make it public. */ JMRuntimeException(String message, Throwable cause) { - super(message); - - /* Make a best effort to set the cause, but if we don't - succeed, too bad, you don't get that useful debugging - information. We jump through hoops here so that we can - work on platforms prior to J2SE 1.4 where the - Throwable.initCause method was introduced. If we change - the public interface of JMRuntimeException in a future - version we can add getCause() so we don't need to do this. */ - try { - java.lang.reflect.Method initCause = - Throwable.class.getMethod("initCause", - new Class[] {Throwable.class}); - initCause.invoke(this, new Object[] {cause}); - } catch (Exception e) { - // OK: just means we won't have debugging info - } + super(message, cause); } } diff --git a/src/share/classes/javax/management/JMX.java b/src/share/classes/javax/management/JMX.java index 297b5a74c..302a163f6 100644 --- a/src/share/classes/javax/management/JMX.java +++ b/src/share/classes/javax/management/JMX.java @@ -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 @@ -26,20 +26,8 @@ package javax.management; import com.sun.jmx.mbeanserver.Introspector; -import com.sun.jmx.mbeanserver.MBeanInjector; -import com.sun.jmx.remote.util.ClassLogger; -import java.beans.BeanInfo; -import java.beans.PropertyDescriptor; -import java.io.IOException; -import java.io.Serializable; import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.Proxy; -import java.util.Map; -import java.util.TreeMap; -import javax.management.namespace.JMXNamespaces; -import javax.management.openmbean.MXBeanMappingFactory; /** * Static methods from the JMX API. There are no instances of this class. @@ -60,27 +48,6 @@ public class JMX { */ public static final String DEFAULT_VALUE_FIELD = "defaultValue"; - /** - * The name of the {@code - * descriptionResourceBundleBaseName} field. - */ - public static final String DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD = - "descriptionResourceBundleBaseName"; - - /** - * The name of the {@code - * descriptionResourceKey} field. - */ - public static final String DESCRIPTION_RESOURCE_KEY_FIELD = - "descriptionResourceKey"; - - /** - * The name of the {@code - * exceptions} field. - */ - public static final String EXCEPTIONS_FIELD = "exceptions"; - /** * The name of the {@code * immutableInfo} field. @@ -99,12 +66,6 @@ public class JMX { */ public static final String LEGAL_VALUES_FIELD = "legalValues"; - /** - * The name of the {@code locale} - * field. - */ - public static final String LOCALE_FIELD = "locale"; - /** * The name of the {@code * maxValue} field. @@ -123,14 +84,6 @@ public class JMX { */ public static final String MXBEAN_FIELD = "mxbean"; - /** - * The name of the - * {@code - * mxbeanMappingFactoryClass} field. - */ - public static final String MXBEAN_MAPPING_FACTORY_CLASS_FIELD = - "mxbeanMappingFactoryClass"; - /** * The name of the {@code * openType} field. @@ -143,276 +96,6 @@ public class JMX { */ public static final String ORIGINAL_TYPE_FIELD = "originalType"; - /** - * The name of the {@code - * setExceptions} field. - */ - public static final String SET_EXCEPTIONS_FIELD = "setExceptions"; - - /** - * The name of the {@code - * objectNameTemplate} field. - */ - public static final String OBJECT_NAME_TEMPLATE = "objectNameTemplate"; - - /** - *

Options to apply to an MBean proxy or to an instance of {@link - * StandardMBean}.

- * - *

For example, to specify the "wrapped object visible" option for a - * {@code StandardMBean}, you might write this:

- * - *
-     * StandardMBean.Options opts = new StandardMBean.Options();
-     * opts.setWrappedObjectVisible(true);
-     * StandardMBean mbean = new StandardMBean(impl, intf, opts);
-     * 
- * - * @see javax.management.JMX.ProxyOptions - * @see javax.management.StandardMBean.Options - */ - public static class MBeanOptions implements Serializable, Cloneable { - private static final long serialVersionUID = -6380842449318177843L; - - static final MBeanOptions MXBEAN = new MBeanOptions(); - static { - MXBEAN.setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - } - - private MXBeanMappingFactory mappingFactory; - - /** - *

Construct an {@code MBeanOptions} object where all options have - * their default values.

- */ - public MBeanOptions() {} - - @Override - public MBeanOptions clone() { - try { - return (MBeanOptions) super.clone(); - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } - - /** - *

True if this is an MXBean proxy or a StandardMBean instance - * that is an MXBean. The default value is false.

- * - *

This method is equivalent to {@link #getMXBeanMappingFactory() - * this.getMXBeanMappingFactory()}{@code != null}.

- * - * @return true if this is an MXBean proxy or a StandardMBean instance - * that is an MXBean. - */ - public boolean isMXBean() { - return (this.mappingFactory != null); - } - - /** - *

The mappings between Java types and Open Types to be used in - * an MXBean proxy or a StandardMBean instance that is an MXBean, - * or null if this instance is not for an MXBean. - * The default value is null.

- * - * @return the mappings to be used in this proxy or StandardMBean, - * or null if this instance is not for an MXBean. - */ - public MXBeanMappingFactory getMXBeanMappingFactory() { - return mappingFactory; - } - - /** - *

Set the {@link #getMXBeanMappingFactory() MXBeanMappingFactory} to - * the given value. The value should be null if this instance is not - * for an MXBean. If this instance is for an MXBean, the value should - * usually be either a custom mapping factory, or - * {@link MXBeanMappingFactory#forInterface - * MXBeanMappingFactory.forInterface}{@code (mxbeanInterface)} - * which signifies - * that the {@linkplain MXBeanMappingFactory#DEFAULT default} mapping - * factory should be used unless an {@code @}{@link - * javax.management.openmbean.MXBeanMappingFactoryClass - * MXBeanMappingFactoryClass} annotation on {@code mxbeanInterface} - * specifies otherwise.

- * - *

Examples:

- *
-         * MBeanOptions opts = new MBeanOptions();
-         * opts.setMXBeanMappingFactory(myMappingFactory);
-         * MyMXBean proxy = JMX.newMBeanProxy(
-         *         mbeanServerConnection, objectName, MyMXBean.class, opts);
-         *
-         * // ...or...
-         *
-         * MBeanOptions opts = new MBeanOptions();
-         * MXBeanMappingFactory defaultFactoryForMyMXBean =
-         *         MXBeanMappingFactory.forInterface(MyMXBean.class);
-         * opts.setMXBeanMappingFactory(defaultFactoryForMyMXBean);
-         * MyMXBean proxy = JMX.newMBeanProxy(
-         *         mbeanServerConnection, objectName, MyMXBean.class, opts);
-         * 
- * - * @param f the new value. If null, this instance is not for an - * MXBean. - */ - public void setMXBeanMappingFactory(MXBeanMappingFactory f) { - this.mappingFactory = f; - } - - /* To maximise object sharing, classes in this package can replace - * a private MBeanOptions with no MXBeanMappingFactory with one - * of these shared instances. But they must be EXTREMELY careful - * never to give out the shared instances to user code, which could - * modify them. - */ - private static final MBeanOptions[] CANONICALS = { - new MBeanOptions(), MXBEAN, - }; - // Overridden in local subclasses: - MBeanOptions[] canonicals() { - return CANONICALS; - } - - // This is only used by the logic for canonical instances. - // Overridden in local subclasses: - boolean same(MBeanOptions opt) { - return (opt.mappingFactory == mappingFactory); - } - - final MBeanOptions canonical() { - for (MBeanOptions opt : canonicals()) { - if (opt.getClass() == this.getClass() && same(opt)) - return opt; - } - return this; - } - - final MBeanOptions uncanonical() { - for (MBeanOptions opt : canonicals()) { - if (this == opt) - return clone(); - } - return this; - } - - private Map toMap() { - Map map = new TreeMap(); - try { - BeanInfo bi = java.beans.Introspector.getBeanInfo(getClass()); - PropertyDescriptor[] pds = bi.getPropertyDescriptors(); - for (PropertyDescriptor pd : pds) { - String name = pd.getName(); - if (name.equals("class")) - continue; - Method get = pd.getReadMethod(); - if (get != null) - map.put(name, get.invoke(this)); - } - } catch (Exception e) { - Throwable t = e; - if (t instanceof InvocationTargetException) - t = t.getCause(); - map.put("Exception", t); - } - return map; - } - - @Override - public String toString() { - return getClass().getSimpleName() + toMap(); - // For example "MBeanOptions{MXBean=true, }". - } - - /** - *

Indicates whether some other object is "equal to" this one. The - * result is true if and only if the other object is also an instance - * of MBeanOptions or a subclass, and has the same properties with - * the same values.

- * @return {@inheritDoc} - */ - @Override - public boolean equals(Object obj) { - if (obj == this) - return true; - if (obj == null || obj.getClass() != this.getClass()) - return false; - return toMap().equals(((MBeanOptions) obj).toMap()); - } - - @Override - public int hashCode() { - return toMap().hashCode(); - } - } - - /** - *

Options to apply to an MBean proxy.

- * - * @see #newMBeanProxy - */ - public static class ProxyOptions extends MBeanOptions { - private static final long serialVersionUID = 7238804866098386559L; - - private boolean notificationEmitter; - - /** - *

Construct a {@code ProxyOptions} object where all options have - * their default values.

- */ - public ProxyOptions() {} - - @Override - public ProxyOptions clone() { - return (ProxyOptions) super.clone(); - } - - /** - *

Defines whether the returned proxy should - * implement {@link NotificationEmitter}. The default value is false.

- * - * @return true if this proxy will be a NotificationEmitter. - * - * @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class, - * MBeanOptions) - */ - public boolean isNotificationEmitter() { - return this.notificationEmitter; - } - - /** - *

Set the {@link #isNotificationEmitter NotificationEmitter} option to - * the given value.

- * @param emitter the new value. - */ - public void setNotificationEmitter(boolean emitter) { - this.notificationEmitter = emitter; - } - - // Canonical objects for each of (MXBean,!MXBean) x (Emitter,!Emitter) - private static final ProxyOptions[] CANONICALS = { - new ProxyOptions(), new ProxyOptions(), - new ProxyOptions(), new ProxyOptions(), - }; - static { - CANONICALS[1].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - CANONICALS[2].setNotificationEmitter(true); - CANONICALS[3].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - CANONICALS[3].setNotificationEmitter(true); - } - @Override - MBeanOptions[] canonicals() { - return CANONICALS; - } - - @Override - boolean same(MBeanOptions opt) { - return (super.same(opt) && opt instanceof ProxyOptions && - ((ProxyOptions) opt).notificationEmitter == notificationEmitter); - } - } - /** *

Make a proxy for a Standard MBean in a local or remote * MBean Server.

@@ -501,12 +184,6 @@ public class JMX { * likewise for the other methods of {@link * NotificationBroadcaster} and {@link NotificationEmitter}.

* - *

This method is equivalent to {@link - * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions) - * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where - * {@code opts} is a {@link JMX.ProxyOptions} representing the - * {@code notificationEmitter} parameter.

- * * @param connection the MBean server to forward to. * @param objectName the name of the MBean within * {@code connection} to forward to. @@ -515,18 +192,22 @@ public class JMX { * @param notificationEmitter make the returned proxy * implement {@link NotificationEmitter} by forwarding its methods * via {@code connection}. + * * @param allows the compiler to know that if the {@code * interfaceClass} parameter is {@code MyMBean.class}, for * example, then the return type is {@code MyMBean}. + * * @return the new proxy instance. */ public static T newMBeanProxy(MBeanServerConnection connection, ObjectName objectName, Class interfaceClass, boolean notificationEmitter) { - ProxyOptions opts = new ProxyOptions(); - opts.setNotificationEmitter(notificationEmitter); - return newMBeanProxy(connection, objectName, interfaceClass, opts); + return MBeanServerInvocationHandler.newProxyInstance( + connection, + objectName, + interfaceClass, + notificationEmitter); } /** @@ -599,6 +280,10 @@ public class JMX { * * * + *

The object returned by this method is a + * {@link Proxy} whose {@code InvocationHandler} is an + * {@link MBeanServerInvocationHandler}.

+ * *

This method is equivalent to {@link * #newMXBeanProxy(MBeanServerConnection, ObjectName, Class, * boolean) newMXBeanProxy(connection, objectName, interfaceClass, @@ -641,17 +326,6 @@ public class JMX { * likewise for the other methods of {@link * NotificationBroadcaster} and {@link NotificationEmitter}.

* - *

This method is equivalent to {@link - * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions) - * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where - * {@code opts} is a {@link JMX.ProxyOptions} where the {@link - * JMX.ProxyOptions#getMXBeanMappingFactory() MXBeanMappingFactory} - * property is - * {@link MXBeanMappingFactory#forInterface(Class) - * MXBeanMappingFactory.forInterface(interfaceClass)} and the {@link - * JMX.ProxyOptions#isNotificationEmitter() notificationEmitter} property - * is equal to the {@code notificationEmitter} parameter.

- * * @param connection the MBean server to forward to. * @param objectName the name of the MBean within * {@code connection} to forward to. @@ -660,130 +334,26 @@ public class JMX { * @param notificationEmitter make the returned proxy * implement {@link NotificationEmitter} by forwarding its methods * via {@code connection}. + * * @param allows the compiler to know that if the {@code * interfaceClass} parameter is {@code MyMXBean.class}, for * example, then the return type is {@code MyMXBean}. + * * @return the new proxy instance. */ public static T newMXBeanProxy(MBeanServerConnection connection, ObjectName objectName, Class interfaceClass, boolean notificationEmitter) { - ProxyOptions opts = new ProxyOptions(); - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface(interfaceClass); - opts.setMXBeanMappingFactory(f); - opts.setNotificationEmitter(notificationEmitter); - return newMBeanProxy(connection, objectName, interfaceClass, opts); - } - - /** - *

Make a proxy for a Standard MBean or MXBean in a local or remote MBean - * Server that may also support the methods of {@link - * NotificationEmitter} and (for an MXBean) that may define custom MXBean - * type mappings.

- * - *

This method behaves the same as - * {@link #newMBeanProxy(MBeanServerConnection, ObjectName, Class)} or - * {@link #newMXBeanProxy(MBeanServerConnection, ObjectName, Class)}, - * according as {@code opts.isMXBean()} is respectively false or true; but - * with the following changes based on {@code opts}.

- * - *
    - *
  • If {@code opts.isNotificationEmitter()} is {@code - * true}, then the MBean is assumed to be a {@link - * NotificationBroadcaster} or {@link NotificationEmitter} and the - * returned proxy will implement {@link NotificationEmitter} as - * well as {@code interfaceClass}. A call to {@link - * NotificationBroadcaster#addNotificationListener} on the proxy - * will result in a call to {@link - * MBeanServerConnection#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object)}, and - * likewise for the other methods of {@link - * NotificationBroadcaster} and {@link NotificationEmitter}.
  • - * - *
  • If {@code opts.getMXBeanMappingFactory()} is not null, - * then the mappings it defines will be applied to convert between - * arbitrary Java types and Open Types.
  • - *
- * - *

The object returned by this method is a - * {@link Proxy} whose {@code InvocationHandler} is an - * {@link MBeanServerInvocationHandler}. This means that it is possible - * to retrieve the parameters that were used to produce the proxy. If the - * proxy was produced as follows...

- * - *
-     * FooMBean proxy =
-     *     JMX.newMBeanProxy(connection, objectName, FooMBean.class, opts);
-     * 
- * - *

...then you can get the {@code MBeanServerInvocationHandler} like - * this...

- * - *
-     * MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
-     *     {@link Proxy#getInvocationHandler(Object)
-     *            Proxy.getInvocationHandler}(proxy);
-     * 
- * - *

...and you can retrieve {@code connection}, {@code - * objectName}, and {@code opts} using the {@link - * MBeanServerInvocationHandler#getMBeanServerConnection() - * getMBeanServerConnection()}, {@link - * MBeanServerInvocationHandler#getObjectName() getObjectName()}, and - * {@link MBeanServerInvocationHandler#getMBeanOptions() getMBeanOptions()} - * methods on {@code mbsih}. You can retrieve {@code FooMBean.class} - * using {@code proxy.getClass().}{@link - * Class#getInterfaces() getInterfaces()}.

- * - * @param connection the MBean server to forward to. - * @param objectName the name of the MBean within - * {@code connection} to forward to. - * @param interfaceClass the Standard MBean or MXBean interface, - * which will also be implemented by the returned proxy. - * @param opts the options to apply for this proxy. Can be null, - * in which case default options are applied. - * @param allows the compiler to know that if the {@code - * interfaceClass} parameter is {@code MyMXBean.class}, for - * example, then the return type is {@code MyMXBean}. - * @return the new proxy instance. - * - * @throws IllegalArgumentException if {@code interfaceClass} is not a - * valid MXBean interface. - */ - public static T newMBeanProxy(MBeanServerConnection connection, - ObjectName objectName, - Class interfaceClass, - MBeanOptions opts) { + // Check interface for MXBean compliance + // try { - return newMBeanProxy2(connection, objectName, interfaceClass, opts); + Introspector.testComplianceMXBeanInterface(interfaceClass); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } - } - - private static T newMBeanProxy2(MBeanServerConnection connection, - ObjectName objectName, - Class interfaceClass, - MBeanOptions opts) - throws NotCompliantMBeanException { - - if (opts == null) - opts = new MBeanOptions(); - - boolean notificationEmitter = opts instanceof ProxyOptions && - ((ProxyOptions) opts).isNotificationEmitter(); - - MXBeanMappingFactory mappingFactory = opts.getMXBeanMappingFactory(); - - if (mappingFactory != null) { - // Check interface for MXBean compliance - Introspector.testComplianceMXBeanInterface(interfaceClass, - mappingFactory); - } - InvocationHandler handler = new MBeanServerInvocationHandler( - connection, objectName, opts); + connection, objectName, true); final Class[] interfaces; if (notificationEmitter) { interfaces = @@ -822,109 +392,4 @@ public class JMX { // exactly the string "MXBean" since that would mean there // was no package name, which is pretty unlikely in practice. } - - /** - *

Test if an MBean can emit notifications. An MBean can emit - * notifications if either it implements {@link NotificationBroadcaster} - * (perhaps through its child interface {@link NotificationEmitter}), or - * it uses resource - * injection to obtain an instance of {@link SendNotification} - * through which it can send notifications.

- * - * @param mbean an MBean object. - * @return true if the given object is a valid MBean that can emit - * notifications; false if the object is a valid MBean but that - * cannot emit notifications. - * @throws NotCompliantMBeanException if the given object is not - * a valid MBean. - */ - public static boolean isNotificationSource(Object mbean) - throws NotCompliantMBeanException { - for (int i = 0; i < 2; i++) { - if (mbean instanceof NotificationBroadcaster || - MBeanInjector.injectsSendNotification(mbean)) - return true; - if (mbean instanceof DynamicWrapperMBean) - mbean = ((DynamicWrapperMBean) mbean).getWrappedObject(); - else - break; - } - return false; - } - - /** - *

Return the version of the JMX specification that a (possibly remote) - * MBean Server is using. The JMX specification described in this - * documentation is version 2.0. The earlier versions that might be - * reported by this method are 1.0, 1.1, 1.2, and 1.4. (There is no 1.3.) - * All of these versions and all future versions can be compared using - * {@link String#compareTo(String)}. So, for example, to tell if - * {@code mbsc} is running at least version 2.0 you can write:

- * - *
-     * String version = JMX.getSpecificationVersion(mbsc, null);
-     * boolean atLeast2dot0 = (version.compareTo("2.0") >= 0);
-     * 
- * - *

A remote MBean Server might be running an earlier version of the - * JMX API, and in that case certain - * features might not be available in it.

- * - *

The version of the MBean Server {@code mbsc} is not necessarily - * the version of all namespaces within that MBean Server, for example - * if some of them use {@link javax.management.namespace.JMXRemoteNamespace - * JMXRemoteNamespace}. To determine the version of the namespace - * that a particular MBean is in, give its name as the {@code mbeanName} - * parameter.

- * - * @param mbsc a connection to an MBean Server. - * - * @param mbeanName the name of an MBean within that MBean Server, or null. - * If non-null, the namespace of this name, as determined by - * {@link JMXNamespaces#getContainingNamespace - * JMXNamespaces.getContainingNamespace}, is the one whose specification - * version will be returned. - * - * @return the JMX specification version reported by that MBean Server. - * - * @throws IllegalArgumentException if {@code mbsc} is null, or if - * {@code mbeanName} includes a wildcard character ({@code *} or {@code ?}) - * in its namespace. - * - * @throws IOException if the version cannot be obtained, either because - * there is a communication problem or because the remote MBean Server - * does not have the appropriate {@linkplain - * MBeanServerDelegateMBean#getSpecificationVersion() attribute}. - * - * @see Interoperability between - * versions of the JMX specification - * @see MBeanServerDelegateMBean#getSpecificationVersion - */ - public static String getSpecificationVersion( - MBeanServerConnection mbsc, ObjectName mbeanName) - throws IOException { - if (mbsc == null) - throw new IllegalArgumentException("Null MBeanServerConnection"); - - String namespace; - if (mbeanName == null) - namespace = ""; - else - namespace = JMXNamespaces.getContainingNamespace(mbeanName); - if (namespace.contains("*") || namespace.contains("?")) { - throw new IllegalArgumentException( - "ObjectName contains namespace wildcard: " + mbeanName); - } - - try { - if (namespace.length() > 0) - mbsc = JMXNamespaces.narrowToNamespace(mbsc, namespace); - return (String) mbsc.getAttribute( - MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion"); - } catch (IOException e) { - throw e; - } catch (Exception e) { - throw new IOException(e); - } - } } diff --git a/src/share/classes/javax/management/MBean.java b/src/share/classes/javax/management/MBean.java deleted file mode 100644 index 4b609c3da..000000000 --- a/src/share/classes/javax/management/MBean.java +++ /dev/null @@ -1,68 +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 javax.management; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

Indicates that the annotated class is a Standard MBean. A Standard - * MBean class can be defined as in this example:

- * - *
- * {@code @MBean}
- * public class Configuration {
- *     {@link ManagedAttribute @ManagedAttribute}
- *     public int getCacheSize() {...}
- *     {@code @ManagedAttribute}
- *     public void setCacheSize(int size);
- *
- *     {@code @ManagedAttribute}
- *     public long getLastChangedTime();
- *
- *     {@link ManagedOperation @ManagedOperation}
- *     public void save();
- * }
- * 
- * - *

The class must be public. Public methods within the class can be - * annotated with {@code @ManagedOperation} to indicate that they are - * MBean operations. Public getter and setter methods within the class - * can be annotated with {@code @ManagedAttribute} to indicate that they define - * MBean attributes.

- * - *

If the MBean is to be an MXBean rather than a Standard MBean, then - * the {@link MXBean @MXBean} annotation must be used instead of - * {@code @MBean}.

- */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Inherited -public @interface MBean { -} diff --git a/src/share/classes/javax/management/MBeanAttributeInfo.java b/src/share/classes/javax/management/MBeanAttributeInfo.java index 4c05c376a..32cadfe09 100644 --- a/src/share/classes/javax/management/MBeanAttributeInfo.java +++ b/src/share/classes/javax/management/MBeanAttributeInfo.java @@ -186,10 +186,8 @@ public class MBeanAttributeInfo extends MBeanFeatureInfo implements Cloneable { (getter != null), (setter != null), isIs(getter), - ImmutableDescriptor.union(Introspector. - descriptorForElement(getter, false), - Introspector.descriptorForElement(setter, - true))); + ImmutableDescriptor.union(Introspector.descriptorForElement(getter), + Introspector.descriptorForElement(setter))); } /** diff --git a/src/share/classes/javax/management/MBeanConstructorInfo.java b/src/share/classes/javax/management/MBeanConstructorInfo.java index 689655329..c817f276c 100644 --- a/src/share/classes/javax/management/MBeanConstructorInfo.java +++ b/src/share/classes/javax/management/MBeanConstructorInfo.java @@ -67,7 +67,7 @@ public class MBeanConstructorInfo extends MBeanFeatureInfo implements Cloneable public MBeanConstructorInfo(String description, Constructor constructor) { this(constructor.getName(), description, constructorSignature(constructor), - Introspector.descriptorForElement(constructor, false)); + Introspector.descriptorForElement(constructor)); } /** diff --git a/src/share/classes/javax/management/MBeanException.java b/src/share/classes/javax/management/MBeanException.java index 7edc6639a..839daa5dd 100644 --- a/src/share/classes/javax/management/MBeanException.java +++ b/src/share/classes/javax/management/MBeanException.java @@ -25,8 +25,6 @@ package javax.management; -import javax.management.openmbean.CompositeData; - /** * Represents "user defined" exceptions thrown by MBean methods @@ -42,26 +40,6 @@ public class MBeanException extends JMException { /* Serial version */ private static final long serialVersionUID = 4066342430588744142L; - /** - * @serial This field is null for instances of this class that were - * produced by its public constructors. It is non-null for instances - * of this class that represent serialized instances of {@link - * GenericMBeanException}. - * - * @see GenericMBeanException#getErrorCode() - */ - final String errorCode; - - /** - * @serial This field is null for instances of this class that were - * produced by its public constructors. It may be non-null for instances - * of this class that represent serialized instances of {@link - * GenericMBeanException}. - * - * @see GenericMBeanException#getUserData() - */ - final CompositeData userData; - /** * @serial Encapsulated {@link Exception} */ @@ -73,8 +51,9 @@ public class MBeanException extends JMException { * * @param e the wrapped exception. */ - public MBeanException(Exception e) { - this(null, null, null, e); + public MBeanException(java.lang.Exception e) { + super() ; + exception = e ; } /** @@ -84,19 +63,11 @@ public class MBeanException extends JMException { * @param e the wrapped exception. * @param message the detail message. */ - public MBeanException(Exception e, String message) { - this(message, null, null, e); + public MBeanException(java.lang.Exception e, String message) { + super(message) ; + exception = e ; } - MBeanException( - String message, String errorCode, CompositeData userData, Throwable cause) { - super(message); - initCause(cause); - if (cause instanceof Exception) - this.exception = (Exception) cause; - this.errorCode = errorCode; - this.userData = userData; - } /** * Return the actual {@link Exception} thrown. @@ -108,24 +79,11 @@ public class MBeanException extends JMException { } /** - * This method is invoked when deserializing instances of this class. - * If the {@code errorCode} field of the deserialized instance is not - * null, this method returns an instance of {@link GenericMBeanException} - * instead. Otherwise it returns {@code this}. - * @return {@code this}, or a {@code GenericMBeanException}. + * Return the actual {@link Exception} thrown. + * + * @return the wrapped exception. */ - Object readResolve() { - if (errorCode == null) { - // serial compatibility: earlier versions did not set - // Throwable.cause because they overrode getCause(). - if (getCause() == null && exception != null) - initCause(exception); - return this; - } else { - Throwable t = new GenericMBeanException( - getMessage(), errorCode, userData, getCause()); - t.setStackTrace(this.getStackTrace()); - return t; - } + public Throwable getCause() { + return exception; } } diff --git a/src/share/classes/javax/management/MBeanInfo.java b/src/share/classes/javax/management/MBeanInfo.java index bf5d59bbe..a1fe87e7a 100644 --- a/src/share/classes/javax/management/MBeanInfo.java +++ b/src/share/classes/javax/management/MBeanInfo.java @@ -25,7 +25,6 @@ package javax.management; -import com.sun.jmx.mbeanserver.Util; import java.io.IOException; import java.io.StreamCorruptedException; import java.io.Serializable; @@ -38,12 +37,6 @@ import java.util.WeakHashMap; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.HashMap; -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.ResourceBundle; -import java.util.logging.Level; -import java.util.logging.Logger; import static javax.management.ImmutableDescriptor.nonNullDescriptor; /** @@ -80,50 +73,27 @@ import static javax.management.ImmutableDescriptor.nonNullDescriptor; * constructors in that object; * *
  • {@link #getAttributes()} returns the list of all attributes - * whose existence is deduced as follows: - *
      - *
    • if the Standard MBean is defined with an MBean interface, - * from getName, isName, or - * setName methods that conform to the conventions + * whose existence is deduced from the presence in the MBean interface + * of a getName, isName, or + * setName method that conforms to the conventions * for Standard MBeans; - *
    • if the Standard MBean is defined with the {@link MBean @MBean} or - * {@link MXBean @MXBean} annotation on a class, from methods with the - * {@link ManagedAttribute @ManagedAttribute} annotation; - *
    * - *
  • {@link #getOperations()} returns the list of all operations whose - * existence is deduced as follows: - *
      - *
    • if the Standard MBean is defined with an MBean interface, from methods in + *
    • {@link #getOperations()} returns the list of all methods in * the MBean interface that do not represent attributes; - *
    • if the Standard MBean is defined with the {@link MBean @MBean} or - * {@link MXBean @MXBean} annotation on a class, from methods with the - * {@link ManagedOperation @ManagedOperation} annotation; - *
    * - *
  • {@link #getNotifications()} returns: - *
      - *
    • if the MBean implements the {@link NotificationBroadcaster} interface, - * the result of calling {@link + *
    • {@link #getNotifications()} returns an empty array if the MBean + * does not implement the {@link NotificationBroadcaster} interface, + * otherwise the result of calling {@link * NotificationBroadcaster#getNotificationInfo()} on it; - *
    • otherwise, if there is a {@link NotificationInfo @NotificationInfo} - * or {@link NotificationInfos @NotificationInfos} annotation on the - * MBean interface or @MBean or @MXBean - * class, the array implied by those annotations; - *
    • otherwise an empty array; - *
    * *
  • {@link #getDescriptor()} returns a descriptor containing the contents * of any descriptor annotations in the MBean interface (see - * {@link DescriptorFields @DescriptorFields} and * {@link DescriptorKey @DescriptorKey}). * * * *

    The description returned by {@link #getDescription()} and the - * descriptions of the contained attributes and operations are determined - * by the corresponding {@link Description} annotations if any; - * otherwise their contents are not specified.

    + * descriptions of the contained attributes and operations are not specified.

    * *

    The remaining details of the MBeanInfo for a * Standard MBean are not specified. This includes the description of @@ -758,377 +728,4 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead { throw new StreamCorruptedException("Got unexpected byte."); } } - - /** - *

    Return an {@code MBeanInfo} object that is the same as this one - * except that its descriptions are localized in the given locale. - * This means the text returned by {@link MBeanInfo#getDescription} - * (the description of the MBean itself), and the text returned by the - * {@link MBeanFeatureInfo#getDescription getDescription()} method - * for every {@linkplain MBeanAttributeInfo attribute}, {@linkplain - * MBeanOperationInfo operation}, {@linkplain MBeanConstructorInfo - * constructor}, and {@linkplain MBeanNotificationInfo notification} - * contained in the {@code MBeanInfo}.

    - * - *

    Here is how the description {@code this.getDescription()} is - * localized.

    - * - *

    First, if the {@linkplain #getDescriptor() descriptor} - * of this {@code MBeanInfo} contains a field "locale", and the value of - * the field is the same as {@code locale.toString()}, then this {@code - * MBeanInfo} is returned. Otherwise, localization proceeds as follows, - * and the {@code "locale"} field in the returned {@code MBeanInfo} will - * be {@code locale.toString()}. - * - *

    A {@code className} is determined. If this - * {@code MBeanInfo} contains a descriptor with the field - * {@code - * "interfaceClassName"}, then the value of that field is the - * {@code className}. Otherwise, it is {@link #getClassName()}. - * Everything before the last period (.) in the {@code className} is - * the {@code package}, and everything after is the {@code - * simpleClassName}. (If there is no period, then the {@code package} - * is empty and the {@code simpleClassName} is the same as the {@code - * className}.)

    - * - *

    A {@code resourceKey} is determined. If this {@code - * MBeanInfo} contains a {@linkplain MBeanInfo#getDescriptor() descriptor} - * with a field {@link JMX#DESCRIPTION_RESOURCE_KEY_FIELD - * "descriptionResourceKey"}, the value of the field is - * the {@code resourceKey}. Otherwise, the {@code resourceKey} is {@code - * simpleClassName + ".mbean"}.

    - * - *

    A {@code resourceBundleBaseName} is determined. If - * this {@code MBeanInfo} contains a descriptor with a field {@link - * JMX#DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD - * "descriptionResourceBundleBaseName"}, the value of the field - * is the {@code resourceBundleBaseName}. Otherwise, the {@code - * resourceBundleBaseName} is {@code package + ".MBeanDescriptions"}. - * - *

    Then, a {@link java.util.ResourceBundle ResourceBundle} is - * determined, using
    {@link java.util.ResourceBundle#getBundle(String, - * Locale, ClassLoader) ResourceBundle.getBundle(resourceBundleBaseName, - * locale, loader)}. If this succeeds, and if {@link - * java.util.ResourceBundle#getString(String) getString(resourceKey)} - * returns a string, then that string is the localized description. - * Otherwise, the original description is unchanged.

    - * - *

    A localized description for an {@code MBeanAttributeInfo} is - * obtained similarly. The default {@code resourceBundleBaseName} - * is the same as above. The default description and the - * descriptor fields {@code "descriptionResourceKey"} and {@code - * "descriptionResourceBundleBaseName"} come from the {@code - * MBeanAttributeInfo} rather than the {@code MBeanInfo}. If the - * attribute's {@linkplain MBeanFeatureInfo#getName() name} is {@code - * Foo} then its default {@code resourceKey} is {@code simpleClassName + - * ".attribute.Foo"}.

    - * - *

    Similar rules apply for operations, constructors, and notifications. - * If the name of the operation, constructor, or notification is {@code - * Foo} then the default {@code resourceKey} is respectively {@code - * simpleClassName + ".operation.Foo"}, {@code simpleClassName + - * ".constructor.Foo"}, or {@code simpleClassName + ".notification.Foo"}. - * If two operations or constructors have the same name (overloading) then - * they have the same default {@code resourceKey}; if different localized - * descriptions are needed then a non-default key must be supplied using - * {@code "descriptionResourceKey"}.

    - * - *

    Similar rules also apply for descriptions of parameters ({@link - * MBeanParameterInfo}). The default {@code resourceKey} for a parameter - * whose {@linkplain MBeanFeatureInfo#getName() name} is {@code - * Bar} in an operation or constructor called {@code Foo} is {@code - * simpleClassName + ".operation.Foo.Bar"} or {@code simpleClassName + - * ".constructor.Foo.Bar"} respectively.

    - * - *

    Example

    - * - *

    Suppose you have an MBean defined by these two Java source files:

    - * - *
    -     * // ConfigurationMBean.java
    -     * package com.example;
    -     * public interface ConfigurationMBean {
    -     *     public String getName();
    -     *     public void save(String fileName);
    -     * }
    -     *
    -     * // Configuration.java
    -     * package com.example;
    -     * public class Configuration implements ConfigurationMBean {
    -     *     public Configuration(String defaultName) {
    -     *         ...
    -     *     }
    -     *     ...
    -     * }
    -     * 
    - * - *

    Then you could define the default descriptions for the MBean, by - * including a resource bundle called {@code com/example/MBeanDescriptions} - * with the compiled classes. Most often this is done by creating a file - * {@code MBeanDescriptions.properties} in the same directory as {@code - * ConfigurationMBean.java}. Make sure that this file is copied into the - * same place as the compiled classes; in typical build environments that - * will be true by default.

    - * - *

    The file {@code com/example/MBeanDescriptions.properties} might - * look like this:

    - * - *
    -     * # Description of the MBean
    -     * ConfigurationMBean.mbean = Configuration manager
    -     *
    -     * # Description of the Name attribute
    -     * ConfigurationMBean.attribute.Name = The name of the configuration
    -     *
    -     * # Description of the save operation
    -     * ConfigurationMBean.operation.save = Save the configuration to a file
    -     *
    -     * # Description of the parameter to the save operation.
    -     * # Parameter names from the original Java source are not available,
    -     * # so the default names are p1, p2, etc.  If the names were available,
    -     * # this would be ConfigurationMBean.operation.save.fileName
    -     * ConfigurationMBean.operation.save.p1 = The name of the file
    -     *
    -     * # Description of the constructor.  The default name of a constructor is
    -     * # its fully-qualified class name.
    -     * ConfigurationMBean.constructor.com.example.Configuration = Constructor with name of default file
    -     * # Description of the constructor parameter.
    -     * ConfigurationMBean.constructor.com.example.Configuration.p1 = Name of the default file
    -     * 
    - * - *

    Starting with this file, you could create descriptions for the French - * locale by creating {@code com/example/MBeanDescriptions_fr.properties}. - * The keys in this file are the same as before but the text has been - * translated: - * - *

    -     * ConfigurationMBean.mbean = Gestionnaire de configuration
    -     *
    -     * ConfigurationMBean.attribute.Name = Le nom de la configuration
    -     *
    -     * ConfigurationMBean.operation.save = Sauvegarder la configuration dans un fichier
    -     *
    -     * ConfigurationMBean.operation.save.p1 = Le nom du fichier
    -     *
    -     * ConfigurationMBean.constructor.com.example.Configuration = Constructeur avec nom du fichier par défaut
    -     * ConfigurationMBean.constructor.com.example.Configuration.p1 = Nom du fichier par défaut
    -     * 
    - * - *

    The descriptions in {@code MBeanDescriptions.properties} and - * {@code MBeanDescriptions_fr.properties} will only be consulted if - * {@code localizeDescriptions} is called, perhaps because the - * MBean Server has been wrapped by {@link - * ClientContext#newLocalizeMBeanInfoForwarder} or because the - * connector server has been created with the {@link - * javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER - * LOCALIZE_MBEAN_INFO_FORWARDER} option. If you want descriptions - * even when there is no localization step, then you should consider - * using {@link Description @Description} annotations. Annotations - * provide descriptions by default but are overridden if {@code - * localizeDescriptions} is called.

    - * - * @param locale the target locale for descriptions. Cannot be null. - * - * @param loader the {@code ClassLoader} to use for looking up resource - * bundles. - * - * @return an {@code MBeanInfo} with descriptions appropriately localized. - * - * @throws NullPointerException if {@code locale} is null. - */ - public MBeanInfo localizeDescriptions(Locale locale, ClassLoader loader) { - if (locale == null) - throw new NullPointerException("locale"); - Descriptor d = getDescriptor(); - String mbiLocaleString = (String) d.getFieldValue(JMX.LOCALE_FIELD); - if (locale.toString().equals(mbiLocaleString)) - return this; - return new Rewriter(this, locale, loader).getMBeanInfo(); - } - - private static class Rewriter { - private final MBeanInfo mbi; - private final ClassLoader loader; - private final Locale locale; - private final String packageName; - private final String simpleClassNamePlusDot; - private ResourceBundle defaultBundle; - private boolean defaultBundleLoaded; - - // ResourceBundle.getBundle throws NullPointerException - // if the loader is null, even though that is perfectly - // valid and means the bootstrap loader. So we work - // around with a ClassLoader that is equivalent to the - // bootstrap loader but is not null. - private static final ClassLoader bootstrapLoader = - new ClassLoader(null) {}; - - Rewriter(MBeanInfo mbi, Locale locale, ClassLoader loader) { - this.mbi = mbi; - this.locale = locale; - if (loader == null) - loader = bootstrapLoader; - this.loader = loader; - - String intfName = (String) - mbi.getDescriptor().getFieldValue("interfaceClassName"); - if (intfName == null) - intfName = mbi.getClassName(); - int lastDot = intfName.lastIndexOf('.'); - this.packageName = intfName.substring(0, lastDot + 1); - this.simpleClassNamePlusDot = intfName.substring(lastDot + 1) + "."; - // Inner classes show up as Outer$Inner so won't match the dot. - // When there is no dot, lastDot is -1, - // packageName is empty, and simpleClassNamePlusDot is intfName. - } - - MBeanInfo getMBeanInfo() { - MBeanAttributeInfo[] mbais = - rewrite(mbi.getAttributes(), "attribute."); - MBeanOperationInfo[] mbois = - rewrite(mbi.getOperations(), "operation."); - MBeanConstructorInfo[] mbcis = - rewrite(mbi.getConstructors(), "constructor."); - MBeanNotificationInfo[] mbnis = - rewrite(mbi.getNotifications(), "notification."); - Descriptor d = mbi.getDescriptor(); - d = changeLocale(d); - String description = getDescription(d, "mbean", ""); - if (description == null) - description = mbi.getDescription(); - return new MBeanInfo( - mbi.getClassName(), description, - mbais, mbcis, mbois, mbnis, d); - } - - private Descriptor changeLocale(Descriptor d) { - if (d.getFieldValue(JMX.LOCALE_FIELD) != null) { - Map map = new HashMap(); - for (String field : d.getFieldNames()) - map.put(field, d.getFieldValue(field)); - map.remove(JMX.LOCALE_FIELD); - d = new ImmutableDescriptor(map); - } - return ImmutableDescriptor.union( - d, new ImmutableDescriptor(JMX.LOCALE_FIELD + "=" + locale)); - } - - private String getDescription( - Descriptor d, String defaultPrefix, String defaultSuffix) { - ResourceBundle bundle = bundleFromDescriptor(d); - if (bundle == null) - return null; - String key = - (String) d.getFieldValue(JMX.DESCRIPTION_RESOURCE_KEY_FIELD); - if (key == null) - key = simpleClassNamePlusDot + defaultPrefix + defaultSuffix; - return descriptionFromResource(bundle, key); - } - - private T[] rewrite( - T[] features, String resourcePrefix) { - for (int i = 0; i < features.length; i++) { - T feature = features[i]; - Descriptor d = feature.getDescriptor(); - String description = - getDescription(d, resourcePrefix, feature.getName()); - if (description != null && - !description.equals(feature.getDescription())) { - features[i] = setDescription(feature, description); - } - } - return features; - } - - private T setDescription( - T feature, String description) { - - Object newf; - String name = feature.getName(); - Descriptor d = feature.getDescriptor(); - - if (feature instanceof MBeanAttributeInfo) { - MBeanAttributeInfo mbai = (MBeanAttributeInfo) feature; - newf = new MBeanAttributeInfo( - name, mbai.getType(), description, - mbai.isReadable(), mbai.isWritable(), mbai.isIs(), - d); - } else if (feature instanceof MBeanOperationInfo) { - MBeanOperationInfo mboi = (MBeanOperationInfo) feature; - MBeanParameterInfo[] sig = rewrite( - mboi.getSignature(), "operation." + name + "."); - newf = new MBeanOperationInfo( - name, description, sig, - mboi.getReturnType(), mboi.getImpact(), d); - } else if (feature instanceof MBeanConstructorInfo) { - MBeanConstructorInfo mbci = (MBeanConstructorInfo) feature; - MBeanParameterInfo[] sig = rewrite( - mbci.getSignature(), "constructor." + name + "."); - newf = new MBeanConstructorInfo( - name, description, sig, d); - } else if (feature instanceof MBeanNotificationInfo) { - MBeanNotificationInfo mbni = (MBeanNotificationInfo) feature; - newf = new MBeanNotificationInfo( - mbni.getNotifTypes(), name, description, d); - } else if (feature instanceof MBeanParameterInfo) { - MBeanParameterInfo mbpi = (MBeanParameterInfo) feature; - newf = new MBeanParameterInfo( - name, mbpi.getType(), description, d); - } else { - logger().log(Level.FINE, "Unknown feature type: " + - feature.getClass()); - newf = feature; - } - - return Util.cast(newf); - } - - private ResourceBundle bundleFromDescriptor(Descriptor d) { - String bundleName = (String) d.getFieldValue( - JMX.DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD); - - if (bundleName != null) - return getBundle(bundleName); - - if (defaultBundleLoaded) - return defaultBundle; - - bundleName = packageName + "MBeanDescriptions"; - defaultBundle = getBundle(bundleName); - defaultBundleLoaded = true; - return defaultBundle; - } - - private String descriptionFromResource( - ResourceBundle bundle, String key) { - try { - return bundle.getString(key); - } catch (MissingResourceException e) { - logger().log(Level.FINEST, "No resource for " + key, e); - } catch (Exception e) { - logger().log(Level.FINE, "Bad resource for " + key, e); - } - return null; - } - - private ResourceBundle getBundle(String name) { - try { - return ResourceBundle.getBundle(name, locale, loader); - } catch (Exception e) { - logger().log(Level.FINE, - "Could not load ResourceBundle " + name, e); - return null; - } - } - - private Logger logger() { - return Logger.getLogger("javax.management.locale"); - } - } } diff --git a/src/share/classes/javax/management/MBeanOperationInfo.java b/src/share/classes/javax/management/MBeanOperationInfo.java index c3ee53826..b7e01ad89 100644 --- a/src/share/classes/javax/management/MBeanOperationInfo.java +++ b/src/share/classes/javax/management/MBeanOperationInfo.java @@ -48,28 +48,24 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { /** * Indicates that the operation is read-like: * it returns information but does not change any state. - * @see Impact#INFO */ public static final int INFO = 0; /** * Indicates that the operation is write-like: it has an effect but does * not return any information from the MBean. - * @see Impact#ACTION */ public static final int ACTION = 1; /** * Indicates that the operation is both read-like and write-like: * it has an effect, and it also returns information from the MBean. - * @see Impact#ACTION_INFO */ public static final int ACTION_INFO = 2; /** * Indicates that the impact of the operation is unknown or cannot be * expressed using one of the other values. - * @see Impact#UNKNOWN */ public static final int UNKNOWN = 3; @@ -113,7 +109,7 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { methodSignature(method), method.getReturnType().getName(), UNKNOWN, - Introspector.descriptorForElement(method, false)); + Introspector.descriptorForElement(method)); } /** @@ -185,6 +181,7 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { *

    Since this class is immutable, cloning is chiefly of interest * to subclasses.

    */ + @Override public Object clone () { try { return super.clone() ; @@ -257,6 +254,7 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { return impact; } + @Override public String toString() { String impactString; switch (getImpact()) { @@ -288,6 +286,7 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { * to those of this MBeanConstructorInfo. Two signature arrays * are equal if their elements are pairwise equal. */ + @Override public boolean equals(Object o) { if (o == this) return true; @@ -327,14 +326,9 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { for (int i = 0; i < classes.length; i++) { Descriptor d = Introspector.descriptorForAnnotations(annots[i]); - String description = Introspector.descriptionForParameter(annots[i]); - if (description == null) - description = ""; - String name = Introspector.nameForParameter(annots[i]); - if (name == null) - name = "p" + (i + 1); - params[i] = new MBeanParameterInfo( - name, classes[i].getName(), description, d); + final String pn = "p" + (i + 1); + params[i] = + new MBeanParameterInfo(pn, classes[i].getName(), "", d); } return params; diff --git a/src/share/classes/javax/management/MBeanPermission.java b/src/share/classes/javax/management/MBeanPermission.java index fe328c2da..d03527503 100644 --- a/src/share/classes/javax/management/MBeanPermission.java +++ b/src/share/classes/javax/management/MBeanPermission.java @@ -25,7 +25,6 @@ package javax.management; -import com.sun.jmx.mbeanserver.Util; import java.io.IOException; import java.io.ObjectInputStream; import java.security.Permission; @@ -46,7 +45,7 @@ import java.security.Permission; * allowed if the permissions you have {@linkplain #implies imply} the * permission you need.

    * - *

    An MBeanPermission contains five items of information:

    + *

    An MBeanPermission contains four items of information:

    * *
      * @@ -58,23 +57,6 @@ import java.security.Permission; * *

      The action is returned by {@link #getActions()}.

      * - *
    • The MBean Server name.

      - * - *

      For a permission you need, this is the {@linkplain - * javax.management.MBeanServerFactory#getMBeanServerName - * name of the MBeanServer} - * containing the MBean for which the MBean - * permission is checked.

      - * - *

      For a permission you have, this is either the {@linkplain - * javax.management.MBeanServerFactory#getMBeanServerName - * name of the MBeanServer} in which the MBean - * you have this permission for must be registered, - * or a pattern against which that MBean Server name will be matched.
      - * An {@code mbeanServerName} pattern can also be empty or the single - * character {@code "*"}, both of which will match any {@code MBeanServer} name. - *

      - * *
    • The class name.

      * *

      For a permission you need, this is the class name of an MBean @@ -121,15 +103,15 @@ import java.security.Permission; *

    * *

    If you have an MBeanPermission, it allows operations only if all - * five of the items match.

    + * four of the items match.

    * - *

    The MBean Server name, class name, member, and object name can be written - * together as a single string, which is the name of this permission. + *

    The class name, member, and object name can be written together + * as a single string, which is the name of this permission. * The name of the permission is the string returned by {@link * Permission#getName() getName()}. The format of the string is:

    * *
    - * mbeanServerName::className#member[objectName] + * className#member[objectName] *
    * *

    The object name is written using the usual syntax for {@link @@ -137,18 +119,15 @@ import java.security.Permission; * ]. It is terminated by a ] character * that is the last character in the string.

    * - *

    One or more of the mbeanServerName, className, - * member, or objectName may be omitted. If the - * mbeanServerName is omitted, the :: may be too (but - * does not have to be). - * If the member is omitted, the # may be too (but + *

    One or more of the className, member, + * or objectName may be omitted. If the + * member is omitted, the # may be too (but * does not have to be). If the objectName is omitted, * the [] may be too (but does not have to be). It is - * not legal to omit all four items, that is to have a name + * not legal to omit all three items, that is to have a name * that is the empty string.

    * - *

    One or more of the mbeanServerName, className, - * member, + *

    One or more of the className, member, * or objectName may be the character "-", * which is equivalent to a null value. A null value is implied by * any value (including another null value) but does not imply any @@ -267,13 +246,6 @@ public class MBeanPermission extends Permission { */ private transient ObjectName objectName; - /** - * The name of the MBeanServer in which this permission is checked, or - * granted. If null, is implied by any MBean Server name - * but does not imply any non-null MBean Server name. - */ - private transient String mbeanServerName; - /** * Parse actions parameter. */ @@ -311,13 +283,6 @@ public class MBeanPermission extends Permission { throw new IllegalArgumentException("MBeanPermission name " + "cannot be empty"); - final int sepIndex = name.indexOf("::"); - if (sepIndex < 0) { - setMBeanServerName("*"); - } else { - setMBeanServerName(name.substring(0,sepIndex)); - } - /* The name looks like "class#member[objectname]". We subtract elements from the right as we parse, so after parsing the objectname we have "class#member" and after parsing the @@ -325,14 +290,11 @@ public class MBeanPermission extends Permission { // Parse ObjectName - - final int start = (sepIndex<0)?0:sepIndex+2; - int openingBracket = name.indexOf("[",start); + int openingBracket = name.indexOf("["); if (openingBracket == -1) { // If "[on]" missing then ObjectName("*:*") // objectName = ObjectName.WILDCARD; - name = name.substring(start); } else { if (!name.endsWith("]")) { throw new IllegalArgumentException("MBeanPermission: " + @@ -343,11 +305,11 @@ public class MBeanPermission extends Permission { } else { // Create ObjectName // - String on = name.substring(openingBracket + 1, - name.length() - 1); try { // If "[]" then ObjectName("*:*") // + String on = name.substring(openingBracket + 1, + name.length() - 1); if (on.equals("")) objectName = ObjectName.WILDCARD; else if (on.equals("-")) @@ -362,7 +324,7 @@ public class MBeanPermission extends Permission { } } - name = name.substring(start, openingBracket); + name = name.substring(0, openingBracket); } // Parse member @@ -386,9 +348,8 @@ public class MBeanPermission extends Permission { * Assign fields based on className, member, and objectName * parameters. */ - private void initName(String mbeanServerName, String className, - String member, ObjectName objectName) { - setMBeanServerName(mbeanServerName); + private void initName(String className, String member, + ObjectName objectName) { setClassName(className); setMember(member); this.objectName = objectName; @@ -420,30 +381,19 @@ public class MBeanPermission extends Permission { this.member = member; } - private void setMBeanServerName(String mbeanServerName) { - if (mbeanServerName == null || mbeanServerName.equals("-")) { - this.mbeanServerName = null; - } else if (mbeanServerName.equals("")) { - this.mbeanServerName = "*"; - } else { - this.mbeanServerName = mbeanServerName; - } - } - - /** *

    Create a new MBeanPermission object with the specified target name * and actions.

    * *

    The target name is of the form - * "mbeanServerName::className#member[objectName]" where - * each part is optional. It must not be empty or null.

    + * "className#member[objectName]" where each part is + * optional. It must not be empty or null.

    * *

    The actions parameter contains a comma-separated list of the * desired actions granted on the target name. It must not be * empty or null.

    * - * @param name the quadruplet "mbeanServerName::className#member[objectName]". + * @param name the triplet "className#member[objectName]". * @param actions the action string. * * @exception IllegalArgumentException if the name or @@ -468,12 +418,6 @@ public class MBeanPermission extends Permission { * optional. This will be the result of {@link #getName()} on the * resultant MBeanPermission.

    * - *

    This corresponds to a permission granted for all - * MBean servers present in the JVM and is equivalent to - * {@link #MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission("*",className,member,objectName,actions)}. - *

    - * *

    The actions parameter contains a comma-separated list of the * desired actions granted on the target name. It must not be * empty or null.

    @@ -495,67 +439,17 @@ public class MBeanPermission extends Permission { String member, ObjectName objectName, String actions) { - this("*",className,member,objectName,actions); - } - - /** - *

    Create a new MBeanPermission object with the specified target name - * (MBean Server name, class name, member, object name) and actions.

    - * - *

    The MBean Server name, class name, member and object name - * parameters define a target name of the form - * "mbeanServerName::className#member[objectName]" where each - * part is optional. This will be the result of {@link #getName()} on the - * resultant MBeanPermission. - * If the mbeanServerName is empty or exactly {@code "*"}, then - * "{@code mbeanServerName::}" is omitted in that result. - *

    - * - *

    The actions parameter contains a comma-separated list of the - * desired actions granted on the target name. It must not be - * empty or null.

    - * - * @param mbeanServerName the name of the {@code MBeanServer} to which this - * permission applies. - * May be null or "-", which represents an MBeanServer name - * that is implied by any MBeanServer name but does not imply any other - * MBeanServer name. - * @param className the class name to which this permission applies. - * May be null or "-", which represents a class name - * that is implied by any class name but does not imply any other - * class name. - * @param member the member to which this permission applies. May - * be null or "-", which represents a member that is - * implied by any member but does not imply any other member. - * @param objectName the object name to which this permission - * applies. May be null, which represents an object name that is - * implied by any object name but does not imply any other object - * name. - * @param actions the action string. - * - * @since 1.7 - */ - public MBeanPermission(String mbeanServerName, - String className, - String member, - ObjectName objectName, - String actions) { - super(makeName(mbeanServerName,className, member, objectName)); - initName(mbeanServerName,className, member, objectName); + super(makeName(className, member, objectName)); + initName(className, member, objectName); this.actions = actions; parseActions(); } - private static String makeName(String mbeanServerName, String className, - String member, + private static String makeName(String className, String member, ObjectName objectName) { final StringBuilder name = new StringBuilder(); - if (mbeanServerName == null) - mbeanServerName = "-"; - if (!mbeanServerName.equals("") && !mbeanServerName.equals("*")) - name.append(mbeanServerName).append("::"); if (className == null) className = "-"; name.append(className); @@ -1097,9 +991,6 @@ public class MBeanPermission extends Permission { * *
  • p is an instance of MBeanPermission; and
  • * - *
  • p has a null mbeanServerName or p's mbeanServerName - * matches this object's mbeanServerName; and
  • - * *
  • p has a null className or p's className * matches this object's className; and
  • * @@ -1113,13 +1004,6 @@ public class MBeanPermission extends Permission { * * * - *

    If this object's mbeanServerName is a pattern, then p's - * mbeanServerName is matched against that pattern. An empty - * mbeanServerName is equivalent to "{@code *}". A null - * mbeanServerName is equivalent to "{@code -}".

    - *

    If this object's mbeanServerName is "*" or is - * empty, p's mbeanServerName always matches it.

    - * *

    If this object's className is "*", p's * className always matches it. If it is "a.*", p's * className matches it if it begins with "a.".

    @@ -1166,12 +1050,6 @@ public class MBeanPermission extends Permission { // Target name // - // The 'mbeanServerName' check is true iff: - // 1) the mbeanServerName in 'this' permission is omitted or "*", or - // 2) the mbeanServerName in 'that' permission is omitted or "*", or - // 3) the mbeanServerName in 'this' permission does pattern - // matching with the mbeanServerName in 'that' permission. - // // The 'className' check is true iff: // 1) the className in 'this' permission is omitted or "*", or // 2) the className in 'that' permission is omitted or "*", or @@ -1198,17 +1076,6 @@ public class MBeanPermission extends Permission { expect that "that" contains a wildcard, since it is a needed permission. So we assume that.classNameExactMatch. */ - if (that.mbeanServerName == null) { - // bottom is implied - } else if (this.mbeanServerName == null) { - // bottom implies nothing but itself - return false; - } else if (that.mbeanServerName.equals(this.mbeanServerName)) { - // exact match - } else if (!Util.wildmatch(that.mbeanServerName,this.mbeanServerName)) { - return false; // no match - } - if (that.classNamePrefix == null) { // bottom is implied } else if (this.classNamePrefix == null) { diff --git a/src/share/classes/javax/management/MBeanRegistration.java b/src/share/classes/javax/management/MBeanRegistration.java index 93d391d7f..41db2fe1a 100644 --- a/src/share/classes/javax/management/MBeanRegistration.java +++ b/src/share/classes/javax/management/MBeanRegistration.java @@ -33,99 +33,6 @@ package javax.management; * to get a reference to the MBean Server and/or its name within that * MBean Server.

    * - *

    Resource injection

    - * - *

    As an alternative to implementing {@code MBeanRegistration}, if all that - * is needed is the MBean Server or ObjectName then an MBean can use - * resource injection.

    - * - *

    If a field in the MBean object has type {@link ObjectName} and has - * the {@link javax.annotation.Resource @Resource} annotation, - * then the {@code ObjectName} under which the MBean is registered is - * assigned to that field during registration. Likewise, if a field has type - * {@link MBeanServer} and the @Resource annotation, then it will - * be set to the {@code MBeanServer} in which the MBean is registered.

    - * - *

    For example:

    - * - *
    - * public Configuration implements ConfigurationMBean {
    - *     @Resource
    - *     private volatile MBeanServer mbeanServer;
    - *     @Resource
    - *     private volatile ObjectName objectName;
    - *     ...
    - *     void unregisterSelf() throws Exception {
    - *         mbeanServer.unregisterMBean(objectName);
    - *     }
    - * }
    - * 
    - * - *

    Resource injection can also be used on fields of type - * {@link SendNotification} to simplify notification sending. Such a field - * will get a reference to an object of type {@code SendNotification} when - * the MBean is registered, and it can use this reference to send notifications. - * For example:

    - * - *
    - * public Configuration implements ConfigurationMBean {
    - *     @Resource
    - *     private volatile SendNotification sender;
    - *     ...
    - *     private void updated() {
    - *         Notification n = new Notification(...);
    - *         sender.sendNotification(n);
    - *     }
    - * }
    - * 
    - * - *

    (Listeners may be invoked in the same thread as the caller of - * {@code sender.sendNotification}.)

    - * - *

    A field to be injected must not be static. It is recommended that - * such fields be declared {@code volatile}.

    - * - *

    It is also possible to use the @Resource annotation on - * methods. Such a method must have a {@code void} return type and a single - * argument of the appropriate type, for example {@code ObjectName}.

    - * - *

    Any number of fields and methods may have the @Resource - * annotation. All fields and methods with type {@code ObjectName} - * (for example) will receive the same {@code ObjectName} value.

    - * - *

    Resource injection is available for all types of MBeans, not just - * Standard MBeans.

    - * - *

    If an MBean implements the {@link DynamicWrapperMBean} interface then - * resource injection happens on the object returned by that interface's - * {@link DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method - * rather than on the MBean object itself. - * - *

    Resource injection happens after the {@link #preRegister preRegister} - * method is called (if any), and before the MBean is actually registered - * in the MBean Server. If a @Resource method throws - * an exception, the effect is the same as if {@code preRegister} had - * thrown the exception. In particular it will prevent the MBean from being - * registered.

    - * - *

    Resource injection can be used on a field or method where the type - * is a parent of the injected type, if the injected type is explicitly - * specified in the @Resource annotation. For example:

    - * - *
    - *     @Resource(type = MBeanServer.class)
    - *     private volatile MBeanServerConnection mbsc;
    - * 
    - * - *

    Formally, suppose R is the type in the @Resource - * annotation and T is the type of the method parameter or field. - * Then one of R and T must be a subtype of the other - * (or they must be the same type). Injection happens if this subtype - * is {@code MBeanServer}, {@code ObjectName}, or {@code SendNotification}. - * Otherwise the @Resource annotation is ignored.

    - * - *

    Resource injection in MBeans is new in version 2.0 of the JMX API.

    - * * @since 1.5 */ public interface MBeanRegistration { @@ -196,7 +103,7 @@ public interface MBeanRegistration { *

    If the implementation of this method throws a {@link RuntimeException} * or an {@link Error}, the MBean Server will rethrow those inside * a {@link RuntimeMBeanException} or {@link RuntimeErrorException}, - * respectively. However, throwing an excepption in {@code postDeregister} + * respectively. However, throwing an exception in {@code postDeregister} * will not change the state of the MBean: * the MBean was already successfully deregistered and will remain so.

    *

    This might be confusing for the code calling diff --git a/src/share/classes/javax/management/MBeanServer.java b/src/share/classes/javax/management/MBeanServer.java index d602eadbc..cd6e7a45b 100644 --- a/src/share/classes/javax/management/MBeanServer.java +++ b/src/share/classes/javax/management/MBeanServer.java @@ -61,13 +61,9 @@ import javax.management.loading.ClassLoaderRepository; * ObjectName is:
    * JMImplementation:type=MBeanServerDelegate.

    * - *

    An object obtained from the {@link - * MBeanServerFactory#createMBeanServer(String) createMBeanServer}, {@link - * MBeanServerFactory#createNamedMBeanServer(String,String) createNamedMBeanServer}, - * {@link - * MBeanServerFactory#newMBeanServer(String) newMBeanServer}, or - * {@link - * MBeanServerFactory#newNamedMBeanServer(String,String) newNamedMBeanServer} + *

    An object obtained from the {@link + * MBeanServerFactory#createMBeanServer(String) createMBeanServer} or + * {@link MBeanServerFactory#newMBeanServer(String) newMBeanServer} * methods of the {@link MBeanServerFactory} class applies security * checks to its methods, as follows.

    * @@ -77,26 +73,10 @@ import javax.management.loading.ClassLoaderRepository; * *

    Assuming that there is a security manager, or that the * implementation chooses to make checks anyway, the checks are made - * as detailed below. - * In what follows, and unless otherwise specified: - *

    - *
    • className is the + * as detailed below. In what follows, and unless otherwise specified, + * {@code className} is the * string returned by {@link MBeanInfo#getClassName()} for the target - * MBean,
    • - *
    • {@code mbeanServerName} is the - * {@linkplain MBeanServerFactory#getMBeanServerName name of the - * MBean Server} in which the target MBean is registered. This is the - * value returned by {@link MBeanServerFactory#getMBeanServerName - * MBeanServerFactory.getMBeanServerName(MBeanServer)}, and - * is usually the {@code mbeanServerName} parameter that was supplied - * to the {@link - * MBeanServerFactory#createNamedMBeanServer(String,String) - * createNamedMBeanServer} or {@link - * MBeanServerFactory#newNamedMBeanServer(String,String) newNamedMBeanServer} - * methods of the {@link MBeanServerFactory} when the MBeanServer was created, - * or {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if - * no name was supplied. - *
    + * MBean.

    * *

    If a security check fails, the method throws {@link * SecurityException}.

    @@ -110,87 +90,79 @@ import javax.management.loading.ClassLoaderRepository; * *
  • For the {@link #invoke invoke} method, the caller's * permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, operationName, name, "invoke")}. - *

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, operationName, name, "invoke")}.

    * *
  • For the {@link #getAttribute getAttribute} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, attribute, name, - * "getAttribute")}.

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, attribute, name, "getAttribute")}.

    * *
  • For the {@link #getAttributes getAttributes} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName,className, null, name, "getAttribute")}. + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "getAttribute")}. * Additionally, for each attribute a in the {@link * AttributeList}, if the caller's permissions do not imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, a, name, - * "getAttribute")}, the + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, a, name, "getAttribute")}, the * MBean server will behave as if that attribute had not been in the * supplied list.

    * *
  • For the {@link #setAttribute setAttribute} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, attrName, name, - * "setAttribute")}, where + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, attrName, name, "setAttribute")}, where * attrName is {@link Attribute#getName() * attribute.getName()}.

    * *
  • For the {@link #setAttributes setAttributes} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, "setAttribute")}. + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "setAttribute")}. * Additionally, for each attribute a in the {@link * AttributeList}, if the caller's permissions do not imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, a, name, - * "setAttribute")}, the + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, a, name, "setAttribute")}, the * MBean server will behave as if that attribute had not been in the * supplied list.

    * *
  • For the addNotificationListener methods, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, * "addNotificationListener")}.

    * *
  • For the removeNotificationListener methods, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, * "removeNotificationListener")}.

    * *
  • For the {@link #getMBeanInfo getMBeanInfo} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, "getMBeanInfo")}. - *

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "getMBeanInfo")}.

    * *
  • For the {@link #getObjectInstance getObjectInstance} method, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, - * "getObjectInstance")}.

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "getObjectInstance")}.

    * *
  • For the {@link #isInstanceOf isInstanceOf} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, "isInstanceOf")}. - *

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "isInstanceOf")}.

    * *
  • For the {@link #queryMBeans queryMBeans} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, null, null, null, "queryMBeans")}. + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(null, null, null, "queryMBeans")}. * Additionally, for each MBean n that matches name, * if the caller's permissions do not imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, n, "queryMBeans")}, - * the MBean server will behave as if that MBean did not exist.

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, n, "queryMBeans")}, the + * MBean server will behave as if that MBean did not exist.

    * *

    Certain query elements perform operations on the MBean server. * If the caller does not have the required permissions for a given @@ -208,10 +180,10 @@ import javax.management.loading.ClassLoaderRepository; * *

  • For the {@link #getDomains getDomains} method, the caller's * permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, null, null, null, "getDomains")}. - * Additionally, for each domain d in the returned array, if the - * caller's permissions do not imply {@link + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(null, null, null, "getDomains")}. Additionally, + * for each domain d in the returned array, if the caller's + * permissions do not imply {@link * MBeanPermission#MBeanPermission(String,String,ObjectName,String) * MBeanPermission(null, null, new ObjectName("d:x=x"), * "getDomains")}, the domain is eliminated from the array. Here, @@ -220,22 +192,21 @@ import javax.management.loading.ClassLoaderRepository; * *

  • For the {@link #getClassLoader getClassLoader} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, loaderName, + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, loaderName, * "getClassLoader")}.

    * *
  • For the {@link #getClassLoaderFor getClassLoaderFor} method, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, mbeanName, + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, mbeanName, * "getClassLoaderFor")}.

    * *
  • For the {@link #getClassLoaderRepository * getClassLoaderRepository} method, the caller's permissions must * imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, null, null, null, - * "getClassLoaderRepository")}.

    + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(null, null, null, "getClassLoaderRepository")}.

    * *
  • For the deprecated deserialize methods, the * required permissions are the same as for the methods that replace @@ -243,15 +214,15 @@ import javax.management.loading.ClassLoaderRepository; * *

  • For the instantiate methods, the caller's * permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, null, "instantiate")}, + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, null, "instantiate")}, * where {@code className} is the name of the class which is to * be instantiated.

    * *
  • For the {@link #registerMBean registerMBean} method, the * caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, "registerMBean")}. + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "registerMBean")}. * *

    If the MBeanPermission check succeeds, the MBean's * class is validated by checking that its {@link @@ -271,8 +242,8 @@ import javax.management.loading.ClassLoaderRepository; * *

  • For the {@link #unregisterMBean unregisterMBean} method, * the caller's permissions must imply {@link - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String) - * MBeanPermission(mbeanServerName, className, null, name, "unregisterMBean")}. + * MBeanPermission#MBeanPermission(String,String,ObjectName,String) + * MBeanPermission(className, null, name, "unregisterMBean")}.

    *

    * * @@ -351,14 +322,11 @@ public interface MBeanServer extends MBeanServerConnection { /** *

    Registers a pre-existing object as an MBean with the MBean - * server. If the object name given is null, the - * MBean must provide its own name in one or both of two ways: by implementing the {@link + * server. If the object name given is null, the MBean must + * provide its own name by implementing the {@link * javax.management.MBeanRegistration MBeanRegistration} interface * and returning the name from the {@link - * MBeanRegistration#preRegister preRegister} method; or by defining - * an {@code objectNameTemplate} field in its {@link Descriptor}, - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} - * annotation.

    + * MBeanRegistration#preRegister preRegister} method. * *

    If this method successfully registers an MBean, a notification * is sent as described above.

    @@ -764,16 +732,13 @@ public interface MBeanServer extends MBeanServerConnection { ReflectionException; /** - *

    Return the {@link java.lang.ClassLoader} that was used for loading - * the class of the named MBean. If the MBean implements the {@link - * DynamicWrapperMBean} interface, then the returned value is the - * result of the {@link DynamicWrapperMBean#getWrappedClassLoader()} - * method.

    + *

    Return the {@link java.lang.ClassLoader} that was used for + * loading the class of the named MBean.

    * * @param mbeanName The ObjectName of the MBean. * * @return The ClassLoader used for that MBean. If l - * is the value specified by the rules above, and r is the + * is the MBean's actual ClassLoader, and r is the * returned value, then either: * *
      diff --git a/src/share/classes/javax/management/MBeanServerConnection.java b/src/share/classes/javax/management/MBeanServerConnection.java index 11509df53..a4d94e005 100644 --- a/src/share/classes/javax/management/MBeanServerConnection.java +++ b/src/share/classes/javax/management/MBeanServerConnection.java @@ -29,7 +29,6 @@ package javax.management; // java import import java.io.IOException; import java.util.Set; -import javax.management.event.NotificationManager; /** @@ -40,20 +39,17 @@ import javax.management.event.NotificationManager; * * @since 1.5 */ -public interface MBeanServerConnection extends NotificationManager { +public interface MBeanServerConnection { /** *

      Instantiates and registers an MBean in the MBean server. The * MBean server will use its {@link * javax.management.loading.ClassLoaderRepository Default Loader * Repository} to load the class of the MBean. An object name is * associated with the MBean. If the object name given is null, the - * MBean must provide its own name in one or both of two ways: by implementing the {@link + * MBean must provide its own name by implementing the {@link * javax.management.MBeanRegistration MBeanRegistration} interface * and returning the name from the {@link - * MBeanRegistration#preRegister preRegister} method; or by defining - * an {@code objectNameTemplate} field in its {@link Descriptor}, - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} - * annotation.

      + * MBeanRegistration#preRegister preRegister} method.

      * *

      This method is equivalent to {@link * #createMBean(String,ObjectName,Object[],String[]) @@ -122,14 +118,11 @@ public interface MBeanServerConnection extends NotificationManager { * class loader to be used is identified by its object name. An * object name is associated with the MBean. If the object name of * the loader is null, the ClassLoader that loaded the MBean - * server will be used. If the object name given is null, the - * MBean must provide its own name in one or both of two ways: by implementing the {@link + * server will be used. If the MBean's object name given is null, + * the MBean must provide its own name by implementing the {@link * javax.management.MBeanRegistration MBeanRegistration} interface * and returning the name from the {@link - * MBeanRegistration#preRegister preRegister} method; or by defining - * an {@code objectNameTemplate} field in its {@link Descriptor}, - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} - * annotation.

      + * MBeanRegistration#preRegister preRegister} method.

      * *

      This method is equivalent to {@link * #createMBean(String,ObjectName,ObjectName,Object[],String[]) @@ -205,13 +198,10 @@ public interface MBeanServerConnection extends NotificationManager { * javax.management.loading.ClassLoaderRepository Default Loader * Repository} to load the class of the MBean. An object name is * associated with the MBean. If the object name given is null, the - * MBean must provide its own name in one or both of two ways: by implementing the {@link + * MBean must provide its own name by implementing the {@link * javax.management.MBeanRegistration MBeanRegistration} interface * and returning the name from the {@link - * MBeanRegistration#preRegister preRegister} method; or by defining - * an {@code objectNameTemplate} field in its {@link Descriptor}, - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} - * annotation.

      + * MBeanRegistration#preRegister preRegister} method. * * @param className The class name of the MBean to be instantiated. * @param name The object name of the MBean. May be null. @@ -280,14 +270,11 @@ public interface MBeanServerConnection extends NotificationManager { * class loader to be used is identified by its object name. An * object name is associated with the MBean. If the object name of * the loader is not specified, the ClassLoader that loaded the - * MBean server will be used. If the object name given is null, the - * MBean must provide its own name in one or both of two ways: by implementing the {@link - * javax.management.MBeanRegistration MBeanRegistration} interface - * and returning the name from the {@link - * MBeanRegistration#preRegister preRegister} method; or by defining - * an {@code objectNameTemplate} field in its {@link Descriptor}, - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate} - * annotation.

      + * MBean server will be used. If the MBean object name given is + * null, the MBean must provide its own name by implementing the + * {@link javax.management.MBeanRegistration MBeanRegistration} + * interface and returning the name from the {@link + * MBeanRegistration#preRegister preRegister} method. * * @param className The class name of the MBean to be instantiated. * @param name The object name of the MBean. May be null. @@ -436,17 +423,7 @@ public interface MBeanServerConnection extends NotificationManager { * specified, all the MBeans registered will be retrieved. * @param query The query expression to be applied for selecting * MBeans. If null no query expression will be applied for - * selecting MBeans. ObjectName patterns that may be contained in the - * query expression will be - * evaluated in the context of the - * {@link javax.management.namespace namespace} - * in which the MBeans selected by {@code name} are registered. - * Thus, in the {@code query} parameter, no ObjectName pattern containing a - * namespace path can match any of the MBean names selected by {@code name}. - * See the - * namespaces documentation for more details. + * selecting MBeans. * * @return A set containing the ObjectInstance * objects for the selected MBeans. If no MBean satisfies the @@ -454,11 +431,6 @@ public interface MBeanServerConnection extends NotificationManager { * * @exception IOException A communication problem occurred when * talking to the MBean server. - * @exception RuntimeOperationsException Wraps a - * java.lang.IllegalArgumentException: The name - * parameter contains an invalid pattern. See the - * namespaces documentation for more details. */ public Set queryMBeans(ObjectName name, QueryExp query) throws IOException; @@ -479,17 +451,7 @@ public interface MBeanServerConnection extends NotificationManager { * specified, the name of all registered MBeans will be retrieved. * @param query The query expression to be applied for selecting * MBeans. If null no query expression will be applied for - * selecting MBeans. ObjectName patterns that may be contained in the - * query expression will be - * evaluated in the context of the - * {@link javax.management.namespace namespace} - * in which the MBeans slected by {@code name} are registered. - * Thus, in the {@code query} parameter, no ObjectName pattern containing a - * namespace path can match any of the MBean names selected by {@code name}. - * See the - * namespaces documentation for more details. + * selecting MBeans. * * @return A set containing the ObjectNames for the MBeans * selected. If no MBean satisfies the query, an empty list is @@ -497,11 +459,6 @@ public interface MBeanServerConnection extends NotificationManager { * * @exception IOException A communication problem occurred when * talking to the MBean server. - * @exception RuntimeOperationsException Wraps a - * java.lang.IllegalArgumentException: The name - * parameter contains an invalid pattern. See the - * namespaces documentation for more details. */ public Set queryNames(ObjectName name, QueryExp query) throws IOException; @@ -594,7 +551,8 @@ public interface MBeanServerConnection extends NotificationManager { * else { * {@code List} missing = new {@code ArrayList}({@link java.util.Arrays#asList Arrays.asList}(attrNames)); - * missing.removeAll(list.toMap().keySet()); + * for (Attribute a : list.asList()) + * missing.remove(a.getName()); * System.out.println("Did not retrieve: " + missing); * } *
  • @@ -681,9 +639,11 @@ public interface MBeanServerConnection extends NotificationManager { * if (inputAttrs.size() == outputAttrs.size()) * System.out.println("All attributes were set successfully"); * else { - * {@code List} missing = new {@code ArrayList}(inputAttrs.toMap().keySet()); - * missing.removeAll(outputAttrs.toMap().keySet()); + * {@code List} missing = new {@code ArrayList}(); + * for (Attribute a : inputAttrs.asList()) + * missing.add(a.getName()); + * for (Attribute a : outputAttrs.asList()) + * missing.remove(a.getName()); * System.out.println("Did not set: " + missing); * } * @@ -809,7 +769,28 @@ public interface MBeanServerConnection extends NotificationManager { public String[] getDomains() throws IOException; - // doc inherited from NotificationManager + /** + *

    Adds a listener to a registered MBean. + * Notifications emitted by the MBean will be forwarded to the listener.

    + * + * @param name The name of the MBean on which the listener should + * be added. + * @param listener The listener object which will handle the + * notifications emitted by the registered MBean. + * @param filter The filter object. If filter is null, no + * filtering will be performed before handling notifications. + * @param handback The context to be sent to the listener when a + * notification is emitted. + * + * @exception InstanceNotFoundException The MBean name provided + * does not match any of the registered MBeans. + * @exception IOException A communication problem occurred when + * talking to the MBean server. + * + * @see #removeNotificationListener(ObjectName, NotificationListener) + * @see #removeNotificationListener(ObjectName, NotificationListener, + * NotificationFilter, Object) + */ public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, @@ -926,13 +907,65 @@ public interface MBeanServerConnection extends NotificationManager { throws InstanceNotFoundException, ListenerNotFoundException, IOException; - // doc inherited from NotificationManager + + /** + *

    Removes a listener from a registered MBean.

    + * + *

    If the listener is registered more than once, perhaps with + * different filters or callbacks, this method will remove all + * those registrations. + * + * @param name The name of the MBean on which the listener should + * be removed. + * @param listener The listener to be removed. + * + * @exception InstanceNotFoundException The MBean name provided + * does not match any of the registered MBeans. + * @exception ListenerNotFoundException The listener is not + * registered in the MBean. + * @exception IOException A communication problem occurred when + * talking to the MBean server. + * + * @see #addNotificationListener(ObjectName, NotificationListener, + * NotificationFilter, Object) + */ public void removeNotificationListener(ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException; - // doc inherited from NotificationManager + /** + *

    Removes a listener from a registered MBean.

    + * + *

    The MBean must have a listener that exactly matches the + * given listener, filter, and + * handback parameters. If there is more than one + * such listener, only one is removed.

    + * + *

    The filter and handback parameters + * may be null if and only if they are null in a listener to be + * removed.

    + * + * @param name The name of the MBean on which the listener should + * be removed. + * @param listener The listener to be removed. + * @param filter The filter that was specified when the listener + * was added. + * @param handback The handback that was specified when the + * listener was added. + * + * @exception InstanceNotFoundException The MBean name provided + * does not match any of the registered MBeans. + * @exception ListenerNotFoundException The listener is not + * registered in the MBean, or it is not registered with the given + * filter and handback. + * @exception IOException A communication problem occurred when + * talking to the MBean server. + * + * @see #addNotificationListener(ObjectName, NotificationListener, + * NotificationFilter, Object) + * + */ public void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, @@ -986,12 +1019,6 @@ public interface MBeanServerConnection extends NotificationManager { * *

    Otherwise, the result is false.

    * - *

    If the MBean implements the {@link DynamicWrapperMBean} - * interface, then in the above rules X is the result of the MBean's {@link - * DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method and L - * is the result of its {@link DynamicWrapperMBean#getWrappedClassLoader() - * getWrappedClassLoader()} method. - * * @param name The ObjectName of the MBean. * @param className The name of the class. * diff --git a/src/share/classes/javax/management/MBeanServerDelegate.java b/src/share/classes/javax/management/MBeanServerDelegate.java index aa706da12..194af9a31 100644 --- a/src/share/classes/javax/management/MBeanServerDelegate.java +++ b/src/share/classes/javax/management/MBeanServerDelegate.java @@ -41,7 +41,6 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean, /** The MBean server agent identification.*/ private String mbeanServerId ; - private String mbeanServerName; /** The NotificationBroadcasterSupport object that sends the notifications */ @@ -71,7 +70,6 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean, public MBeanServerDelegate () { stamp = getStamp(); broadcaster = new NotificationBroadcasterSupport() ; - mbeanServerName=null; } @@ -90,98 +88,11 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean, "using \"localhost\" instead. Cause is: "+e); localHost = "localhost"; } - mbeanServerId = - Util.insertMBeanServerName(localHost + "_" + stamp, - mbeanServerName); + mbeanServerId = localHost + "_" + stamp; } return mbeanServerId; } - /** - * The name of the MBeanServer. - * @return The name of the MBeanServer, or {@value - * javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if no - * name was specified. - * - * @since 1.7 - * @see #setMBeanServerName - */ - public synchronized String getMBeanServerName() { - if (Util.isMBeanServerNameUndefined(mbeanServerName)) - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME; - return mbeanServerName; - } - - /** - * Sets the name of the MBeanServer. The name will be embedded into the - * {@link #getMBeanServerId MBeanServerId} using the following format:
    - * {@code mbeanServerId: ;mbeanServerName=} - *

    The characters {@code ':'} (colon), {@code ';'} (semicolon ), - * {@code '*'} (star) and {@code '?'} (question mark) are not legal in an - * MBean Server name.

    - *

    For instance, if the {@code mbeanServerName} provided is - * {@code "com.mycompany.myapp.server1"}, and the original - * {@code MBeanServerId} was {@code "myhost_1213353064145"}, - * then {@code mbeanServerName} will be - * embedded in the {@code MBeanServerId} - and the new value of the - * {@code MBeanServerId} will be: - *

    - *
    -     *       "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"
    -     * 
    - *

    Note: The {@code mbeanServerName} is usually set by the - * {@code MBeanServerFactory}. It is set only once, before the - * MBean Server is returned by the factory. Once the MBean Server name is - * set, it is not possible to change it. - *

    - * @param mbeanServerName The MBeanServer name. - * @throws IllegalArgumentException if the MBeanServerName is already set - * to a different value, or if the provided name contains - * illegal characters, or if the provided name is {@code ""} - * (the empty string) or "-" (dash). - * @throws UnsupportedOperationException if this object is of a legacy - * subclass of MBeanServerDelegate which overrides {@link - * #getMBeanServerId()} - * in a way that doesn't support setting an MBeanServer name. - * @see MBeanServerFactory#getMBeanServerName - * @since 1.7 - */ - public synchronized void setMBeanServerName(String mbeanServerName) { - // Sets the name on the delegate. For complex backward - // compatibility reasons it is not possible to give the - // name to the MBeanServerDelegate constructor. - // - // The method setMBeanServerName() will call getMBeanServerId() - // to check that the name is accurately set in the MBeanServerId. - // If not (which could happen if a custom MBeanServerDelegate - // implementation overrides getMBeanServerId() and was not updated - // with respect to JMX 2.0 spec), this method will throw an - // IllegalStateException... - - // will fail if mbeanServerName is illegal - final String name = Util.checkServerName(mbeanServerName); - - // can only set mbeanServerDelegate once. - if (this.mbeanServerName != null && !this.mbeanServerName.equals(name)) - throw new IllegalArgumentException( - "MBeanServerName already set to a different value"); - - this.mbeanServerName = name; - - // will fail if mbeanServerId already has a different mbeanServerName - mbeanServerId = - Util.insertMBeanServerName(getMBeanServerId(),name); - - // check that we don't have a subclass which overrides - // getMBeanServerId() without setting mbeanServerName - if (!name.equals( - Util.extractMBeanServerName(getMBeanServerId()))) - throw new UnsupportedOperationException( - "Can't set MBeanServerName in MBeanServerId - " + - "unsupported by "+this.getClass().getName()+"?"); - // OK: at this point we know that we have correctly set mbeanServerName. - } - /** * Returns the full name of the JMX specification implemented * by this product. @@ -304,7 +215,7 @@ public class MBeanServerDelegate implements MBeanServerDelegateMBean, * @since 1.6 */ public static final ObjectName DELEGATE_NAME = - ObjectName.valueOf("JMImplementation:type=MBeanServerDelegate"); + Util.newObjectName("JMImplementation:type=MBeanServerDelegate"); /* Return a timestamp that is monotonically increasing even if System.currentTimeMillis() isn't (for example, if you call this diff --git a/src/share/classes/javax/management/MBeanServerFactory.java b/src/share/classes/javax/management/MBeanServerFactory.java index e0225200d..13df4c22e 100644 --- a/src/share/classes/javax/management/MBeanServerFactory.java +++ b/src/share/classes/javax/management/MBeanServerFactory.java @@ -29,11 +29,9 @@ import com.sun.jmx.defaults.JmxProperties; import static com.sun.jmx.defaults.JmxProperties.JMX_INITIAL_BUILDER; import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; import com.sun.jmx.mbeanserver.GetPropertyAction; -import com.sun.jmx.mbeanserver.Util; import java.security.AccessController; import java.security.Permission; import java.util.ArrayList; -import java.util.List; import java.util.logging.Level; import javax.management.loading.ClassLoaderRepository; @@ -83,53 +81,10 @@ import javax.management.loading.ClassLoaderRepository; * returned by the default MBeanServerBuilder implementation, for the purpose * of e.g. adding an additional security layer.

    * - *

    Since version 2.0 of the JMX API, when creating - * an MBeanServer, - * it is possible to specify an {@linkplain #getMBeanServerName - * MBean Server name}. - * To create an MBean Server with a name, the MBeanServerFactory provides two - * new methods:

    - *
    • {@link #createNamedMBeanServer - * createNamedMBeanServer(mbeanServerName, defaultDomain)}: creates a named - * MBeanServer and keeps an internal reference to the created object. The - * MBeanServer can be later retrieved using {@link #findMBeanServer - * findMBeanServer(mbeanServerId)} or - * {@link #findMBeanServerByName findMBeanServerByName(mbeanServerName)}, and - * can be released through {@link - * #releaseMBeanServer releaseMBeanServer(mbeanServer)}.
    • - *
    • {@link #newNamedMBeanServer - * newNamedMBeanServer(mbeanServerName, defaultDomain)}: - * creates a named MBeanServer without keeping any internal reference to the - * named server.
    • - *
    - *

    The name of the MBeanServer is stored in the - * {@linkplain MBeanServerDelegate MBean Server delegate MBean} - * and is embedded in its {@link MBeanServerDelegate#getMBeanServerId - * MBeanServerId} attribute.

    - *

    The name of the MBeanServer is particularly useful when - * MBean permissions are checked: - * it makes it - * possible to distinguish between an MBean named "X" in MBeanServer named - * "M1", and another MBean of the same name "X" in another MBeanServer named - * "M2".

    - *

    When naming MBean servers it is recommended to use a name that starts - * with a Java package name. It is also recommended that the default domain and - * the MBeanServer name be the same.

    - * * @since 1.5 */ public class MBeanServerFactory { - /** - * The MBean Server name that will be - * checked by a permission you need - * when checking access to an MBean registered in an MBeanServer for - * which no MBeanServer name was specified. - * - * @since 1.7 - */ - public final static String DEFAULT_MBEANSERVER_NAME = "default"; - /* * There are no instances of this class so don't generate the * default public constructor. @@ -268,78 +223,13 @@ public class MBeanServerFactory { * javax.management.builder.initial exists and can be * instantiated but is not assignment compatible with {@link * MBeanServerBuilder}. - * - * @see #createNamedMBeanServer */ public static MBeanServer createMBeanServer(String domain) { - return createMBeanServer(null,domain); - } + checkPermission("createMBeanServer"); - /** - *

    Return a new object implementing the {@link MBeanServer} - * interface with the specified - * MBean Server name - * and default domain name. The given MBean server name - * is used in security checks, and - * can also be used to {@linkplain #findMBeanServerByName(java.lang.String) - * find an MBeanServer by name}. The given - * domain name is used as the domain part in the ObjectName of - * MBeans when the domain is specified by the user is null.

    - * - *

    The MBeanServer reference is internally kept. This will - * allow findMBeanServer to return a reference to - * this MBeanServer object.

    - * - * @param mbeanServerName the name for the created - * MBeanServer. This is the name that will be included in the - * {@linkplain MBeanPermission permission you need} when checking - * MBean Permissions for accessing - * an MBean registered in the returned MBeanServer. The characters - * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star) - * and {@code '?'} are not legal. - * It is recommended that the {@code mbeanServerName} - * be unique in the context of a JVM, and in the form of a java package - * identifier. If {@code mbeanServerName} is {@code null} then the created - * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used. - * Calling {@code createNamedMBeanServer(null,domain)} is equivalent - * to calling {@link #createMBeanServer(String) createMBeanServer(domain)}. - * - * @param domain the default domain name for the created - * MBeanServer. This is the value that will be returned by {@link - * MBeanServer#getDefaultDomain}. If a non null mbeanServerName is given, - * it is recommended to pass the same value as default domain. - * - * @return the newly created MBeanServer. - * - * @exception SecurityException if there is a SecurityManager and - * the caller's permissions do not include or imply {@link - * MBeanServerPermission}("createMBeanServer"). - * - * @exception JMRuntimeException if the property - * javax.management.builder.initial exists but the - * class it names cannot be instantiated through a public - * no-argument constructor; or if the instantiated builder returns - * null from its {@link MBeanServerBuilder#newMBeanServerDelegate - * newMBeanServerDelegate} or {@link - * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. - * - * @exception ClassCastException if the property - * javax.management.builder.initial exists and can be - * instantiated but is not assignment compatible with {@link - * MBeanServerBuilder}. - * - * @exception IllegalArgumentException if the specified - * {@code mbeanServerName} is empty, or is {@code "-"}, or contains a - * character which is not legal. - * - * @exception UnsupportedOperationException if the specified - * {@code mbeanServerName} cannot be set. - * - * @since 1.7 - */ - public static MBeanServer createNamedMBeanServer(String mbeanServerName, - String domain) { - return createMBeanServer(mbeanServerName, domain); + final MBeanServer mBeanServer = newMBeanServer(domain); + addMBeanServer(mBeanServer); + return mBeanServer; } /** @@ -418,88 +308,6 @@ public class MBeanServerFactory { * MBeanServerBuilder}. */ public static MBeanServer newMBeanServer(String domain) { - return newMBeanServer(null,domain); - } - - /** - *

    Return a new object implementing the MBeanServer interface - * with the specified MBean server name - * and default domain name, without keeping an - * internal reference to this new object. The given MBean server name - * is used in security checks. - * The given domain name - * is used as the domain part in the ObjectName of MBeans when the - * domain is specified by the user is null.

    - * - *

    No reference is kept. findMBeanServer and - * findMBeanServerByName will not - * be able to return a reference to this MBeanServer object, but - * the garbage collector will be able to remove the MBeanServer - * object when it is no longer referenced.

    - * - * @param mbeanServerName the name for the created - * MBeanServer. This is the name that will be included in the - * {@linkplain MBeanPermission permission you need} when checking - * MBean Permissions for accessing - * an MBean registered in the returned MBeanServer. The characters - * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star) - * and {@code '?'} are not legal. - * It is recommended that the mbeanServerName - * be unique in the context of a JVM, and in the form of a java package - * identifier. If {@code mbeanServerName} is {@code null} then the created - * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used. - * Calling {@code newNamedMBeanServer(null,domain)} is equivalent - * to calling {@link #newMBeanServer(String) newMBeanServer(domain)}. - * - * @param domain the default domain name for the created - * MBeanServer. This is the value that will be returned by {@link - * MBeanServer#getDefaultDomain}. - * - * @return the newly created MBeanServer. - * - * @exception SecurityException if there is a SecurityManager and the - * caller's permissions do not include or imply {@link - * MBeanServerPermission}("newMBeanServer"). - * - * @exception JMRuntimeException if the property - * javax.management.builder.initial exists but the - * class it names cannot be instantiated through a public - * no-argument constructor; or if the instantiated builder returns - * null from its {@link MBeanServerBuilder#newMBeanServerDelegate - * newMBeanServerDelegate} or {@link - * MBeanServerBuilder#newMBeanServer newMBeanServer} methods. - * - * @exception ClassCastException if the property - * javax.management.builder.initial exists and can be - * instantiated but is not assignment compatible with {@link - * MBeanServerBuilder}. - * - * @exception IllegalArgumentException if the specified - * {@code mbeanServerName} is empty, or is {@code "-"}, - * or contains a character which is not legal. - * - * @exception UnsupportedOperationException if the specified - * {@code mbeanServerName} cannot be set. - * - * @since 1.7 - */ - public static MBeanServer newNamedMBeanServer(String mbeanServerName, - String domain) { - return newMBeanServer(mbeanServerName, domain); - } - - private static MBeanServer createMBeanServer(String mbeanServerName, - String domain) { - checkPermission("createMBeanServer"); - - final MBeanServer mBeanServer = - newMBeanServer(mbeanServerName,domain); - addMBeanServer(mBeanServer); - return mBeanServer; - } - - private static MBeanServer newMBeanServer(String mbeanServerName, - String domain) { checkPermission("newMBeanServer"); // Get the builder. Creates a new one if necessary. @@ -516,22 +324,6 @@ public class MBeanServerFactory { "returned null"; throw new JMRuntimeException(msg); } - - // Sets the name on the delegate. For complex backward - // compatibility reasons it is not possible to give the - // name to the MBeanServerDelegate constructor. - // - // The method setMBeanServerName() will call getMBeanServerId() - // to check that the name is accurately set in the MBeanServerId. - // If not (which could happen if a custom MBeanServerDelegate - // implementation overrides getMBeanServerId() and was not updated - // with respect to JMX 2.0 spec, this method will throw an - // IllegalStateException... - // - if (!Util.isMBeanServerNameUndefined(mbeanServerName)) { - delegate.setMBeanServerName(mbeanServerName); - } - final MBeanServer mbeanServer = mbsBuilder.newMBeanServer(domain,null,delegate); if (mbeanServer == null) { @@ -539,20 +331,6 @@ public class MBeanServerFactory { "MBeanServerBuilder.newMBeanServer() returned null"; throw new JMRuntimeException(msg); } - - // double check that the MBeanServer name is correctly set. - // "*" might mean that the caller doesn't have the permission - // to see the MBeanServer name. - // - final String mbsName = Util.getMBeanServerSecurityName(mbeanServer); - if (!mbsName.equals(Util.checkServerName(mbeanServerName)) - && !mbsName.equals("*")) { - throw new UnsupportedOperationException( - "can't create MBeanServer with name \""+ - mbeanServerName+"\" using "+ - builder.getClass().getName()); - } - return mbeanServer; } } @@ -593,96 +371,6 @@ public class MBeanServerFactory { return result; } - /** - *

    Returns a list of registered MBeanServer objects with the given name. A - * registered MBeanServer object is one that was created by one of - * the createMBeanServer or createNamedMBeanServer - * methods and not subsequently released with releaseMBeanServer.

    - *

    See the section about MBean Server names - * above.

    - * - * @param mbeanServerName The name of the MBeanServer to - * retrieve. If this parameter is null, all registered MBeanServers - * in this JVM are returned. - * Otherwise, only those MBeanServers that have a name - * matching mbeanServerName are returned: this - * parameter can be a pattern, where {@code '*'} matches any - * sequence of characters and {@code '?'} matches any character.
    - * The name of an MBeanServer, if specified, is embedded in the - * MBeanServerId attribute of its delegate MBean: - * this method will parse the MBeanServerId to get the - * MBeanServer name. If this parameter is equal to {@code "*"} then - * all registered MBeanServers in this JVM are returned, whether they have - * a name or not: {@code findMBeanServerByName(null)}, - * {@code findMBeanServerByName("*")} and {@code findMBeanServer(null)}, - * are equivalent. It is also possible to get all MBeanServers for which - * no name was specified by calling findMBeanServerByName({@value - * #DEFAULT_MBEANSERVER_NAME}). - * - * @return A list of MBeanServer objects. - * - * @exception SecurityException if there is a SecurityManager and the - * caller's permissions do not include or imply {@link - * MBeanServerPermission}("findMBeanServer"). - * - * @see #getMBeanServerName(MBeanServer) - * @since 1.7 - */ - public synchronized static - List findMBeanServerByName(String mbeanServerName) { - - checkPermission("findMBeanServer"); - - if (mbeanServerName==null || "*".equals(mbeanServerName)) - return new ArrayList(mBeanServerList); - - // noname=true iff we are looking for MBeanServers for which no name - // were specified. - ArrayList result = new ArrayList(); - for (MBeanServer mbs : mBeanServerList) { - final String name = Util.getMBeanServerSecurityName(mbs); - if (Util.wildmatch(name, mbeanServerName)) result.add(mbs); - } - return result; - } - - /** - * Returns the name of the MBeanServer embedded in the MBeanServerId of - * the given {@code server}. If the given MBeanServerId doesn't contain - * any name, {@value #DEFAULT_MBEANSERVER_NAME} is returned. - * The MBeanServerId is expected to be of the form: - * {@code *[;mbeanServerName=[;*]]} - *
    where {@code *} denotes any sequence of characters, and {@code [ ]} - * indicate optional parts. - *

    - *

    For instance, if an MBeanServer is created using {@link - * #createNamedMBeanServer(java.lang.String, java.lang.String) - * server = - * MBeanServerFactory.createNamedMBeanServer("com.mycompany.myapp.server1", - * null)} then {@code MBeanServerFactory.getMBeanServerName(server)} - * will return {@code "com.mycompany.myapp.server1"} and - * server.getAttribute({@link - * javax.management.MBeanServerDelegate#DELEGATE_NAME - * MBeanServerDelegate.DELEGATE_NAME}, "MBeanServerId") will return - * something like - * {@code "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"}. - *

    - *

    See the section about MBean Server names - * above.

    - * @param server A named (or unnamed) MBeanServer. - * @return the name of the MBeanServer if found, or - * {@value #DEFAULT_MBEANSERVER_NAME} if no name is - * present in its MBeanServerId, or "*" if its - * MBeanServerId couldn't be obtained. Returning "*" means that - * only {@link MBeanPermission}s that allow all MBean Server names - * will apply to this MBean Server. - * @see MBeanServerDelegate - * @since 1.7 - */ - public static String getMBeanServerName(MBeanServer server) { - return Util.getMBeanServerSecurityName(server); - } - /** * Return the ClassLoaderRepository used by the given MBeanServer. * This method is equivalent to {@link diff --git a/src/share/classes/javax/management/MBeanServerInvocationHandler.java b/src/share/classes/javax/management/MBeanServerInvocationHandler.java index 20c934f15..384ed180c 100644 --- a/src/share/classes/javax/management/MBeanServerInvocationHandler.java +++ b/src/share/classes/javax/management/MBeanServerInvocationHandler.java @@ -33,9 +33,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.WeakHashMap; -import javax.management.openmbean.MXBeanMappingFactory; - -import static javax.management.JMX.MBeanOptions; /** *

    {@link InvocationHandler} that forwards methods in an MBean's @@ -114,7 +111,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler { public MBeanServerInvocationHandler(MBeanServerConnection connection, ObjectName objectName) { - this(connection, objectName, null); + this(connection, objectName, false); } /** @@ -141,14 +138,6 @@ public class MBeanServerInvocationHandler implements InvocationHandler { public MBeanServerInvocationHandler(MBeanServerConnection connection, ObjectName objectName, boolean isMXBean) { - this(connection, objectName, isMXBean ? MBeanOptions.MXBEAN : null); - } - - public MBeanServerInvocationHandler(MBeanServerConnection connection, - ObjectName objectName, - MBeanOptions options) { - if (options == null) - options = new MBeanOptions(); if (connection == null) { throw new IllegalArgumentException("Null connection"); } @@ -157,7 +146,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler { } this.connection = connection; this.objectName = objectName; - this.options = options.canonical(); + this.isMXBean = isMXBean; } /** @@ -193,16 +182,7 @@ public class MBeanServerInvocationHandler implements InvocationHandler { * @since 1.6 */ public boolean isMXBean() { - return options.isMXBean(); - } - - /** - *

    Return the {@link MBeanOptions} used for this proxy.

    - * - * @return the MBeanOptions. - */ - public MBeanOptions getMBeanOptions() { - return options.uncanonical(); + return isMXBean; } /** @@ -346,40 +326,30 @@ public class MBeanServerInvocationHandler implements InvocationHandler { */ } - private MXBeanProxy findMXBeanProxy(Class mxbeanInterface) { - MXBeanMappingFactory mappingFactory = options.getMXBeanMappingFactory(); + private static MXBeanProxy findMXBeanProxy(Class mxbeanInterface) { synchronized (mxbeanProxies) { - ClassToProxy classToProxy = mxbeanProxies.get(mappingFactory); - if (classToProxy == null) { - classToProxy = new ClassToProxy(); - mxbeanProxies.put(mappingFactory, classToProxy); - } - WeakReference wr = classToProxy.get(mxbeanInterface); - MXBeanProxy p; - if (wr != null) { - p = wr.get(); - if (p != null) - return p; - } - try { - p = new MXBeanProxy(mxbeanInterface, mappingFactory); - } catch (IllegalArgumentException e) { - String msg = "Cannot make MXBean proxy for " + - mxbeanInterface.getName() + ": " + e.getMessage(); - throw new IllegalArgumentException(msg, e.getCause()); + WeakReference proxyRef = + mxbeanProxies.get(mxbeanInterface); + MXBeanProxy p = (proxyRef == null) ? null : proxyRef.get(); + if (p == null) { + try { + p = new MXBeanProxy(mxbeanInterface); + } catch (IllegalArgumentException e) { + String msg = "Cannot make MXBean proxy for " + + mxbeanInterface.getName() + ": " + e.getMessage(); + IllegalArgumentException iae = + new IllegalArgumentException(msg, e.getCause()); + iae.setStackTrace(e.getStackTrace()); + throw iae; + } + mxbeanProxies.put(mxbeanInterface, + new WeakReference(p)); } - classToProxy.put(mxbeanInterface, new WeakReference(p)); return p; } } - private static final WeakHashMap - mxbeanProxies = newWeakHashMap(); - private static class ClassToProxy - extends WeakHashMap, WeakReference> {} - - private static WeakHashMap newWeakHashMap() { - return new WeakHashMap(); - } + private static final WeakHashMap, WeakReference> + mxbeanProxies = new WeakHashMap, WeakReference>(); private Object invokeBroadcasterMethod(Object proxy, Method method, Object[] args) throws Exception { @@ -523,5 +493,5 @@ public class MBeanServerInvocationHandler implements InvocationHandler { private final MBeanServerConnection connection; private final ObjectName objectName; - private final MBeanOptions options; + private final boolean isMXBean; } diff --git a/src/share/classes/javax/management/MBeanServerNotification.java b/src/share/classes/javax/management/MBeanServerNotification.java index e9fe12ad9..8995d47c3 100644 --- a/src/share/classes/javax/management/MBeanServerNotification.java +++ b/src/share/classes/javax/management/MBeanServerNotification.java @@ -64,13 +64,13 @@ package javax.management; * mbeanServer.addNotificationListener( * MBeanServerDelegate.DELEGATE_NAME, printListener, null, null); * + * *

    * An MBean which is not an {@link MBeanServerDelegate} may also emit - * MBeanServerNotifications. In particular, a custom subclass of the - * {@link javax.management.namespace.JMXDomain JMXDomain} MBean or a custom - * subclass of the {@link javax.management.namespace.JMXNamespace JMXNamespace} - * MBean may emit an MBeanServerNotification for a group of MBeans.
    - * An MBeanServerNotification emitted to denote the registration or + * MBeanServerNotifications. In particular, there is a convention for + * MBeans to emit an MBeanServerNotification for a group of MBeans.

    + * + *

    An MBeanServerNotification emitted to denote the registration or * unregistration of a group of MBeans has the following characteristics: *

    • Its {@linkplain Notification#getType() notification type} is * {@code "JMX.mbean.registered.group"} or @@ -92,58 +92,6 @@ package javax.management; * declare them in their {@link MBeanInfo#getNotifications() * MBeanNotificationInfo}. *

      - *

      - * To receive a group MBeanServerNotification, you need to register a listener - * with the MBean that emits it. For instance, assuming that the {@link - * javax.management.namespace.JMXNamespace JMXNamespace} MBean handling - * namespace {@code "foo"} has declared that it emits such a notification, - * you will need to register your notification listener with that MBean, which - * will be named {@link - * javax.management.namespace.JMXNamespaces#getNamespaceObjectName(java.lang.String) - * foo//:type=JMXNamespace}. - *

      - *

      The following code prints a message every time a group of MBean is - * registered or unregistered in the namespace {@code "foo"}, assumimg its - * {@link javax.management.namespace.JMXNamespace handler} supports - * group MBeanServerNotifications:

      - * - *
      - * private static final NotificationListener printListener = new NotificationListener() {
      - *     public void handleNotification(Notification n, Object handback) {
      - *         if (!(n instanceof MBeanServerNotification)) {
      - *             System.out.println("Ignored notification of class " + n.getClass().getName());
      - *             return;
      - *         }
      - *         MBeanServerNotification mbsn = (MBeanServerNotification) n;
      - *         String what;
      - *         ObjectName[] names = null;
      - *         if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
      - *             what = "MBean registered";
      - *         } else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
      - *             what = "MBean unregistered";
      - *         } else if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION+".group")) {
      - *             what = "Group of MBeans registered matching";
      - *             if (mbsn.getUserData() instanceof ObjectName[])
      - *                names =  (ObjectName[]) mbsn.getUserData();
      - *         } else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION+".group")) {
      - *             what = "Group of MBeans unregistered matching";
      - *             if (mbsn.getUserData() instanceof ObjectName[])
      - *                names = (ObjectName[]) mbsn.getUserData();
      - *         } else
      - *             what = "Unknown type " + n.getType();
      - *         System.out.println("Received MBean Server notification: " + what + ": " +
      - *                 mbsn.getMBeanName());
      - *         if (names != null) {
      - *              for (ObjectName mb : names)
      - *                  System.out.println("\t"+mb);
      - *         }
      - *     }
      - * };
      - *
      - * ...
      - *     mbeanServer.addNotificationListener(
      - *             JMXNamespaces.getNamespaceObjectName("foo"), printListener, null, null);
      - * 
      * * @since 1.5 */ diff --git a/src/share/classes/javax/management/MXBean.java b/src/share/classes/javax/management/MXBean.java index f6691ccae..d34c34115 100644 --- a/src/share/classes/javax/management/MXBean.java +++ b/src/share/classes/javax/management/MXBean.java @@ -27,7 +27,6 @@ package javax.management; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -44,10 +43,6 @@ import javax.management.openmbean.CompositeDataInvocationHandler; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataView; import javax.management.openmbean.CompositeType; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingClass; -import javax.management.openmbean.MXBeanMappingFactory; -import javax.management.openmbean.MXBeanMappingFactoryClass; import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenMBeanInfo; import javax.management.openmbean.OpenType; @@ -57,13 +52,11 @@ import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; /** -

      Annotation to mark a class or interface explicitly as being an MXBean, - or as not being an MXBean. By default, an +

      Annotation to mark an interface explicitly as being an MXBean + interface, or as not being an MXBean interface. By default, an interface is an MXBean interface if its name ends with {@code - MXBean}, as in {@code SomethingMXBean}. A class is never an MXBean by - default.

      - -

      The following interfaces are MXBean interfaces:

      + MXBean}, as in {@code SomethingMXBean}. The following interfaces + are MXBean interfaces:

           public interface WhatsitMXBean {}
      @@ -84,12 +77,7 @@ import javax.management.openmbean.TabularType;
           public interface MisleadingMXBean {}
           
      -

      A class can be annotated with {@code @MXBean} to indicate that it - is an MXBean. In this case, its methods should have @{@link - ManagedAttribute} or @{@link ManagedOperation} - annotations, as described for @{@link MBean}.

      - -

      MXBean specification

      +

      MXBean specification

      The MXBean concept provides a simple way to code an MBean that only references a predefined set of types, the ones defined @@ -486,11 +474,7 @@ public class MemoryPool from type opendata(J) to type J, a null value is mapped to a null value.

      -

      In addition to the default type mapping rules, you can specify - custom type mappings, as described below.

      - -

      The following table summarizes the default type mapping rules.

      +

      The following table summarizes the type mapping rules.

      @@ -1051,77 +1035,6 @@ public interface Node { } -

      Alternatively, you can define a custom mapping for your recursive - type; see the next section.

      - -

      Custom MXBean type mappings

      - -

      You can augment or replace the default type mappings described - above with custom mappings. An example appears in the - documentation for {@link MXBeanMapping}.

      - -

      If an MXBean uses custom mappings, then an MXBean proxy for - that MXBean must use the same mappings for correct behavior. - This requires more careful synchronization between client and - server than is necessary with the default mappings. For example - it typically requires the client to have the same implementation - of any {@link MXBeanMapping} subclasses as the server. For this - reason, custom mappings should be avoided if possible.

      - -

      Every MXBean has an associated {@link MXBeanMappingFactory}. - Call this f. Then every type that appears - in that MXBean has an associated {@link MXBeanMapping} - determined by f. If the type is - J, say, then the mapping is {@link - MXBeanMappingFactory#mappingForType - f.mappingForType}(J, - f).

      - -

      The {@code MXBeanMappingFactory} f for an - MXBean is determined as follows.

      - -
        -
      • If a {@link JMX.MBeanOptions} argument is supplied to - the {@link StandardMBean} constructor that makes an MXBean, - or to the {@link JMX#newMBeanProxy(MBeanServerConnection, - ObjectName, Class, JMX.MBeanOptions) JMX.newMBeanProxy} - method, and the {@code MBeanOptions} object defines a non-null - {@code MXBeanMappingFactory}, then that is the value of - f.

      • - -
      • Otherwise, if the MXBean interface has an {@link - MXBeanMappingFactoryClass} annotation, then that annotation - must identify a subclass of {@code MXBeanMappingFactory} - with a no-argument constructor. Then - f is the result of calling this - constructor. If the class does not have a no-argument - constructor, or if calling the constructor produces an - exception, then the MXBean is invalid and an attempt to - register it in the MBean Server will produce a {@link - NotCompliantMBeanException}.

        - -

        This annotation is not inherited from any parent - interfaces. If an MXBean interface has this annotation, - then usually any MXBean subinterfaces must repeat the same - annotation for correct behavior.

      • - -
      • Otherwise, if the package in which the MXBean interface - appears has an {@code MXBeanMappingFactoryClass} annotation, - then f is determined as if that - annotation appeared on the MXBean interface.

      • - -
      • Otherwise, f is the default mapping - factory, {@link MXBeanMappingFactory#DEFAULT}.

      • -
      - -

      The default mapping factory recognizes the {@link - MXBeanMappingClass} annotation on a class or interface. If - J is a class or interface that has such an - annotation, then the {@code MXBeanMapping} for - J produced by the default mapping factory - will be determined by the value of the annotation as described - in its {@linkplain MXBeanMappingClass documentation}.

      -

      MBeanInfo contents for an MXBean

      An MXBean is a type of Open MBean. However, for compatibility @@ -1250,29 +1163,12 @@ public interface Node { appropriate), or C is true of e.{@link Throwable#getCause() getCause()}".

      - @see MXBeanMapping - @since 1.6 */ -/* - * This annotation is @Inherited because if an MXBean is defined as a - * class using annotations, then its subclasses are also MXBeans. - * For example: - * @MXBean - * public class Super { - * @ManagedAttribute - * public String getName() {...} - * } - * public class Sub extends Super {} - * Here Sub is an MXBean. - * - * The @Inherited annotation has no effect when applied to an interface. - */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) -@Inherited public @interface MXBean { /** True if the annotated interface is an MXBean interface. diff --git a/src/share/classes/javax/management/ManagedAttribute.java b/src/share/classes/javax/management/ManagedAttribute.java deleted file mode 100644 index 3b10b77c5..000000000 --- a/src/share/classes/javax/management/ManagedAttribute.java +++ /dev/null @@ -1,64 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

      Indicates that a method in an MBean class defines an MBean attribute. - * This annotation must be applied to a public method of a public class - * that is itself annotated with an {@link MBean @MBean} or - * {@link MXBean @MXBean} annotation, or inherits such an annotation from - * a superclass.

      - * - *

      The annotated method must be a getter or setter. In other words, - * it must look like one of the following...

      - * - *
      - * T getFoo()
      - * void setFoo(T param)
      - * 
      - * - *

      ...where {@code T} is any type and {@code Foo} is the - * name of the attribute. For any attribute {@code Foo}, if only - * a {@code get}{@code Foo} method has a {@code ManagedAttribute} - * annotation, then {@code Foo} is a read-only attribute. If only - * a {@code set}{@code Foo} method has a {@code ManagedAttribute} - * annotation, then {@code Foo} is a write-only attribute. If - * both {@code get}{@code Foo} and {@code set}{@code Foo} - * methods have the annotation, then {@code Foo} is a read-write - * attribute. In this last case, the type {@code T} must be the - * same in both methods.

      - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -@Documented -public @interface ManagedAttribute { -} diff --git a/src/share/classes/javax/management/ManagedOperation.java b/src/share/classes/javax/management/ManagedOperation.java deleted file mode 100644 index 7f70e447c..000000000 --- a/src/share/classes/javax/management/ManagedOperation.java +++ /dev/null @@ -1,67 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

      Indicates that a method in an MBean class defines an MBean operation. - * This annotation can be applied to:

      - * - *
        - *
      • A public method of a public class - * that is itself annotated with an {@link MBean @MBean} or - * {@link MXBean @MXBean} annotation, or inherits such an annotation from - * a superclass.
      • - *
      • A method of an MBean or MXBean interface. - *
      - * - *

      Every method in an MBean or MXBean interface defines an MBean - * operation even without this annotation, but the annotation allows - * you to specify the impact of the operation:

      - * - *
      - * public interface ConfigurationMBean {
      - *     {@code @ManagedOperation}(impact = {@link Impact#ACTION Impact.ACTION})
      - *     public void save();
      - *     ...
      - * }
      - * 
      - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -@Documented -public @interface ManagedOperation { - /** - *

      The impact of this operation, as shown by - * {@link MBeanOperationInfo#getImpact()}. - */ - Impact impact() default Impact.UNKNOWN; -} diff --git a/src/share/classes/javax/management/NotQueryExp.java b/src/share/classes/javax/management/NotQueryExp.java index bb39fbc95..104092312 100644 --- a/src/share/classes/javax/management/NotQueryExp.java +++ b/src/share/classes/javax/management/NotQueryExp.java @@ -90,10 +90,4 @@ class NotQueryExp extends QueryEval implements QueryExp { public String toString() { return "not (" + exp + ")"; } - - @Override - String toQueryString() { - return "not (" + Query.toString(exp) + ")"; - } - } diff --git a/src/share/classes/javax/management/Notification.java b/src/share/classes/javax/management/Notification.java index 85428cc8f..754af4204 100644 --- a/src/share/classes/javax/management/Notification.java +++ b/src/share/classes/javax/management/Notification.java @@ -54,7 +54,7 @@ import com.sun.jmx.mbeanserver.GetPropertyAction; * @since 1.5 */ @SuppressWarnings("serial") // serialVersionUID is not constant -public class Notification extends EventObject implements Cloneable { +public class Notification extends EventObject { // Serialization compatibility stuff: // Two serial forms are supported in this class. The selected form depends @@ -243,26 +243,6 @@ public class Notification extends EventObject implements Cloneable { this.message = message ; } - /** - *

      Creates and returns a copy of this object. The copy is created as - * described for {@link Object#clone()}. This means, first, that the - * class of the object will be the same as the class of this object, and, - * second, that the copy is a "shallow copy". Fields of this notification - * are not themselves copied. In particular, the {@linkplain - * #getUserData user data} of the copy is the same object as the - * original.

      - * - * @return a copy of this object. - */ - @Override - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } - /** * Sets the source. * @@ -341,23 +321,11 @@ public class Notification extends EventObject implements Cloneable { * * @return The message string of this notification object. * - * @see #setMessage */ public String getMessage() { return message ; } - /** - * Set the notification message. - * - * @param message the new notification message. - * - * @see #getMessage - */ - public void setMessage(String message) { - this.message = message; - } - /** * Get the user data. * diff --git a/src/share/classes/javax/management/NotificationBroadcasterSupport.java b/src/share/classes/javax/management/NotificationBroadcasterSupport.java index 44f5a5064..65064ab90 100644 --- a/src/share/classes/javax/management/NotificationBroadcasterSupport.java +++ b/src/share/classes/javax/management/NotificationBroadcasterSupport.java @@ -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 @@ -58,8 +58,7 @@ import com.sun.jmx.remote.util.ClassLogger; * * @since 1.5 */ -public class NotificationBroadcasterSupport - implements NotificationEmitter, SendNotification { +public class NotificationBroadcasterSupport implements NotificationEmitter { /** * Constructs a NotificationBroadcasterSupport where each listener is invoked by the * thread sending the notification. This constructor is equivalent to @@ -249,26 +248,6 @@ public class NotificationBroadcasterSupport } } } - /** - * Returns true if there are any listeners. - * - * @return true if there is at least one listener that has been added with - * {@code addNotificationListener} and not subsequently removed with - * {@code removeNotificationListener} or {@code removeAllNotificationListeners}. - * @since 1.7 - */ - public boolean isListenedTo() { - return listenerList.size() > 0; - } - - /** - * Removes all listeners. - * - * @since 1.7 - */ - public void removeAllNotificationListeners() { - listenerList.clear(); - } /** *

      This method is called by {@link #sendNotification diff --git a/src/share/classes/javax/management/NotificationInfo.java b/src/share/classes/javax/management/NotificationInfo.java deleted file mode 100644 index a5c2f46ac..000000000 --- a/src/share/classes/javax/management/NotificationInfo.java +++ /dev/null @@ -1,135 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

      Specifies the kinds of notification an MBean can emit. In both the - * following examples, the MBean emits notifications of type - * {@code "com.example.notifs.create"} and of type - * {@code "com.example.notifs.destroy"}:

      - * - *
      - * // Example one: a Standard MBean
      - * {@code @NotificationInfo}(types={"com.example.notifs.create",
      - *                          "com.example.notifs.destroy"})
      - * public interface CacheMBean {...}
      - *
      - * public class Cache
      - *         extends NotificationBroadcasterSupport implements CacheMBean {
      - *     public Cache() {
      - *         super();   // do not supply any MBeanNotificationInfo[]
      - *     }
      - *     ...
      - * }
      - * 
      - * - *
      - * // Example two: an annotated MBean
      - * {@link MBean @MBean}
      - * {@code @NotificationInfo}(types={"com.example.notifs.create",
      - *                          "com.example.notifs.destroy"})
      - * public class Cache {
      - *     {@code @Resource}
      - *     private volatile SendNotification sendNotification;
      - *     ...
      - * }
      - * 
      - * - *

      Each {@code @NotificationInfo} produces an {@link - * MBeanNotificationInfo} inside the {@link MBeanInfo} of each MBean - * to which the annotation applies.

      - * - *

      If you need to specify different notification classes, or different - * descriptions for different notification types, then you can group - * several {@code @NotificationInfo} annotations into a containing - * {@link NotificationInfos @NotificationInfos} annotation. - * - *

      The {@code @NotificationInfo} and {@code @NotificationInfos} annotations - * are ignored on an MBean that is not a {@linkplain JMX#isNotificationSource - * notification source} or that implements {@link NotificationBroadcaster} and - * returns a non-empty array from its {@link - * NotificationBroadcaster#getNotificationInfo() getNotificationInfo()} - * method.

      - * - *

      The {@code NotificationInfo} and {@code NotificationInfos} - * annotations can be applied to the MBean implementation class, or to - * any parent class or interface. These annotations on a class take - * precedence over annotations on any superclass or superinterface. - * If an MBean does not have these annotations on its class or any - * superclass, then superinterfaces are examined. It is an error for - * more than one superinterface to have these annotations, unless one - * of them is a descendant of all the others; registering such an erroneous - * MBean will cause a {@link NotCompliantMBeanException}.

      - */ -@Documented -@Inherited -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface NotificationInfo { - /** - *

      The {@linkplain Notification#getType() notification types} - * that this MBean can emit.

      - */ - String[] types(); - - /** - *

      The class that emitted notifications will have. It is recommended - * that this be {@link Notification}, or one of its standard subclasses - * in the JMX API.

      - */ - Class notificationClass() default Notification.class; - - /** - *

      The description of this notification. For example: - * - *

      -     * {@code @NotificationInfo}(
      -     *         types={"com.example.notifs.create"},
      -     *         description={@code @Description}("object created"))
      -     * 
      - */ - Description description() default @Description(""); - - /** - *

      Additional descriptor fields for the derived {@code - * MBeanNotificationInfo}. They are specified in the same way as - * for the {@link DescriptorFields @DescriptorFields} annotation, - * for example:

      - *
      -     * {@code @NotificationInfo}(
      -     *         types={"com.example.notifs.create"},
      -     *         descriptorFields={"severity=6"})
      -     * 
      - */ - String[] descriptorFields() default {}; -} diff --git a/src/share/classes/javax/management/NotificationInfos.java b/src/share/classes/javax/management/NotificationInfos.java deleted file mode 100644 index cc21d06d3..000000000 --- a/src/share/classes/javax/management/NotificationInfos.java +++ /dev/null @@ -1,72 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import javax.management.remote.JMXConnectionNotification; - -/** - *

      Specifies the kinds of notification an MBean can emit, when this - * cannot be represented by a single {@link NotificationInfo - * @NotificationInfo} annotation.

      - * - *

      For example, this annotation specifies that an MBean can emit - * {@link AttributeChangeNotification} and {@link - * JMXConnectionNotification}:

      - * - *
      - * {@code @NotificationInfos}(
      - *     {@code @NotificationInfo}(
      - *         types = {{@link AttributeChangeNotification#ATTRIBUTE_CHANGE}},
      - *         notificationClass = AttributeChangeNotification.class),
      - *     {@code @NotificationInfo}(
      - *         types = {{@link JMXConnectionNotification#OPENED},
      - *                  {@link JMXConnectionNotification#CLOSED}},
      - *         notificationClass = JMXConnectionNotification.class)
      - * )
      - * 
      - * - *

      If an MBean has both {@code NotificationInfo} and {@code - * NotificationInfos} on the same class or interface, the effect is - * the same as if the {@code NotificationInfo} were moved inside the - * {@code NotificationInfos}.

      - */ -@Documented -@Inherited -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -public @interface NotificationInfos { - /** - *

      The {@link NotificationInfo} annotations.

      - */ - NotificationInfo[] value(); -} diff --git a/src/share/classes/javax/management/ObjectName.java b/src/share/classes/javax/management/ObjectName.java index 41025a768..cda2ab944 100644 --- a/src/share/classes/javax/management/ObjectName.java +++ b/src/share/classes/javax/management/ObjectName.java @@ -27,8 +27,6 @@ package javax.management; import com.sun.jmx.mbeanserver.GetPropertyAction; import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.namespace.serial.JMXNamespaceContext; - import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; @@ -56,38 +54,14 @@ import java.util.Map; * properties.

      * *

      The domain is a string of characters not including - * the character colon (:).

      - *

      Starting with the version 2.0 of the JMX specification, the - * domain can also start with a {@linkplain - * javax.management.namespace#NamespacePrefix namespace prefix} identifying - * the {@linkplain javax.management.namespace namespace} in which the - * MBean is registered. A namespace prefix is a path string where - * elements are separated by a double slash (//). - * It identifies the {@linkplain javax.management.namespace namespace} in - * which the MBean so named is registered.

      - * - *

      For instance the ObjectName bar//baz:k=v identifiies an MBean - * named baz:k=v in the namespace bar. Similarly the - * ObjectName foo//bar//baz:k=v identifiies an MBean named - * baz:k=v in the namespace foo//bar. See the {@linkplain - * javax.management.namespace namespace} documentation for more details.

      + * the character colon (:). It is recommended that the domain + * should not contain the string "{@code //}", which is reserved for future use. * *

      If the domain includes at least one occurrence of the wildcard * characters asterisk (*) or question mark * (?), then the object name is a pattern. The asterisk * matches any sequence of zero or more characters, while the question - * mark matches any single character.
      - * A namespace separator // does not match wildcard - * characters unless it is at the very end of the domain string. - * So foo*bar*:* does not match foo//bar:k=v but it - * does match fooxbar//:k=v. - *

      - * - *

      When included in a namespace path the special path element - * ** matches any number of sub namespaces - * recursively, but only if used as a complete namespace path element, - * as in **//b//c//D:k=v or a//**//c//D:k=v - * - see below. + * mark matches any single character.

      * *

      If the domain is empty, it will be replaced in certain contexts * by the default domain of the MBean server in which the @@ -195,51 +169,6 @@ import java.util.Map; * with {@code \}. * * - *

      Pattern and namespaces:

      - *

      In an object name pattern, a path element - * of exactly ** corresponds to a meta - * wildcard that will match any number of sub namespaces.
      Hence:

      - *
      - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
      patternmatchesdoesn't match
      • **//D:k=v
      a//D:k=v
      - * a//b//D:k=v
      - * a//b//c//D:k=v
      D:k=v
      • a//**//D:k=v
      a//b//D:k=v
      - * a//b//c//D:k=v
      b//b//c//D:k=v
      - * a//D:k=v
      - * D:k=v
      • a//**//e//D:k=v
      a//b//e//D:k=v
      - * a//b//c//e//D:k=v
      a//b//c//c//D:k=v
      - * b//b//c//e//D:k=v
      - * a//e//D:k=v
      - * e//D:k=v
      • a//b**//e//D:k=v
      a//b//e//D:k=va//b//c//e//D:k=v
      - * because in that case b**
      - * is not a meta-wildcard - and b**
      - * is thus equivalent to b*.
      - *
    - *

    - *

    - * Note: Although ObjectName patterns where the characters - * * and ? appear in the namespace path are legal, - * they are not valid in the {@code name} parameter of the MBean Server's - * {@link MBeanServer#queryNames queryNames} and {@link MBeanServer#queryMBeans - * queryMBeans} methods. See the - * namespaces documentation for more details. - *

    - * *

    An ObjectName can be written as a String with the following * elements in order:

    * @@ -293,17 +222,6 @@ import java.util.Map; @SuppressWarnings("serial") // don't complain serialVersionUID not constant public class ObjectName implements Comparable, QueryExp { - /** - * The sequence of characters used to separate name spaces in a name space - * path. - * - * @see javax.management.namespace - * @since 1.7 - **/ - public static final String NAMESPACE_SEPARATOR = "//"; - private static final int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - /** * A structure recording property structure and * proposing minimal services @@ -333,17 +251,16 @@ public class ObjectName implements Comparable, QueryExp { /** * Returns a key string for receiver key */ - String getKeyString(String name, int offset) { - final int start = _key_index+offset; - return name.substring(start, start + _key_length); + String getKeyString(String name) { + return name.substring(_key_index, _key_index + _key_length); } /** * Returns a value string for receiver key */ - String getValueString(String name, int offset) { - final int in_begin = _key_index + offset + _key_length + 1; - final int out_end = in_begin + _value_length; + String getValueString(String name) { + int in_begin = _key_index + _key_length + 1; + int out_end = in_begin + _value_length; return name.substring(in_begin, out_end); } } @@ -476,40 +393,6 @@ public class ObjectName implements Comparable, QueryExp { */ private transient boolean _property_value_pattern = false; - private ObjectName(String newDomain, ObjectName aname) - throws MalformedObjectNameException{ - copyToOtherDomain(newDomain,aname); - } - - private void copyToOtherDomain(String domain, ObjectName aname) - throws MalformedObjectNameException { - - // The domain cannot be null - if (domain == null) - throw new NullPointerException("domain cannot be null"); - - // The key property list cannot be null - if (aname == null) - throw new MalformedObjectNameException( - "key property list cannot be empty"); - - // checks domain validity. A side effect of this method is also to - // set the _domain_pattern flag. - if (!isDomain(domain)) - throw new MalformedObjectNameException("Invalid domain: " + domain); - - // init canonicalname - _domain_length = domain.length(); - - _canonicalName = (domain + - aname._canonicalName.substring(aname._domain_length)).intern(); - _kp_array = aname._kp_array; - _ca_array = aname._ca_array; - _propertyList = aname._propertyList; - _property_list_pattern = aname._property_list_pattern; - _property_value_pattern = aname._property_value_pattern; - } - // Instance private fields <======================================= // Private fields <======================================== @@ -754,12 +637,10 @@ public class ObjectName implements Comparable, QueryExp { // we got the key and value part, prepare a property for this if (!value_pattern) { - prop = new Property(key_index-_domain_length, - key_length, value_length); + prop = new Property(key_index, key_length, value_length); } else { _property_value_pattern = true; - prop = new PatternProperty(key_index-_domain_length, - key_length, value_length); + prop = new PatternProperty(key_index, key_length, value_length); } key_name = name.substring(key_index, key_index + key_length); @@ -844,12 +725,12 @@ public class ObjectName implements Comparable, QueryExp { boolean value_pattern = checkValue(value); sb.append(value); if (!value_pattern) { - prop = new Property(key_index-_domain_length, + prop = new Property(key_index, key.length(), value.length()); } else { _property_value_pattern = true; - prop = new PatternProperty(key_index-_domain_length, + prop = new PatternProperty(key_index, key.length(), value.length()); } @@ -929,9 +810,9 @@ public class ObjectName implements Comparable, QueryExp { prop = _ca_array[i]; // length of prop including '=' char prop_len = prop._key_length + prop._value_length + 1; - System.arraycopy(specified_chars, prop._key_index+_domain_length, + System.arraycopy(specified_chars, prop._key_index, canonical_chars, prop_index, prop_len); - prop.setKeyIndex(prop_index-_domain_length); + prop.setKeyIndex(prop_index); prop_index += prop_len; if (i != last_index) { canonical_chars[prop_index] = ','; @@ -1268,37 +1149,15 @@ public class ObjectName implements Comparable, QueryExp { cn = (String)in.readObject(); } - final JMXNamespaceContext ctxt = - JMXNamespaceContext.getDeserializationContext(); try { - construct(changeContext(ctxt,cn)); + construct(cn); } catch (NullPointerException e) { throw new InvalidObjectException(e.toString()); - } catch (IllegalArgumentException e) { - throw new InvalidObjectException(e.toString()); } catch (MalformedObjectNameException e) { throw new InvalidObjectException(e.toString()); } } - private String changeContext(JMXNamespaceContext context, String nameString) { - final String old = context.prefixToRemove; - final String nw = context.prefixToAdd; - final int ol = old.length(); - if (nameString.startsWith(NAMESPACE_SEPARATOR)) return nameString; - if (ol>0) { - if (!nameString.startsWith(old) || - !nameString.startsWith(NAMESPACE_SEPARATOR,ol)) - throw new IllegalArgumentException( - "Serialized ObjectName does not start with " + old + - ": " + nameString); - nameString = nameString.substring(ol+NAMESPACE_SEPARATOR_LENGTH); - } - if (!nw.equals("")) { - nameString = nw + NAMESPACE_SEPARATOR + nameString; - } - return nameString; - } /** * Serializes an {@link ObjectName} to an {@link ObjectOutputStream}. @@ -1361,22 +1220,15 @@ public class ObjectName implements Comparable, QueryExp { private void writeObject(ObjectOutputStream out) throws IOException { - final JMXNamespaceContext ctxt = - JMXNamespaceContext.getSerializationContext(); - if (compat) { // Serializes this instance in the old serial form // Read CR 6441274 before making any changes to this code ObjectOutputStream.PutField fields = out.putFields(); - final String domain = - changeContext(ctxt,_canonicalName.substring(0, _domain_length)); - final String cn = - changeContext(ctxt,_canonicalName); - fields.put("domain", domain); + fields.put("domain", _canonicalName.substring(0, _domain_length)); fields.put("propertyList", getKeyPropertyList()); fields.put("propertyListString", getKeyPropertyListString()); - fields.put("canonicalName", cn); + fields.put("canonicalName", _canonicalName); fields.put("pattern", (_domain_pattern || _property_list_pattern)); fields.put("propertyPattern", _property_list_pattern); out.writeFields(); @@ -1386,8 +1238,7 @@ public class ObjectName implements Comparable, QueryExp { // Serializes this instance in the new serial form // out.defaultWriteObject(); - - out.writeObject(changeContext(ctxt,getSerializedNameString())); + out.writeObject(getSerializedNameString()); } } @@ -1416,10 +1267,9 @@ public class ObjectName implements Comparable, QueryExp { * @exception NullPointerException The name parameter * is null. * - * @see #valueOf(String) */ public static ObjectName getInstance(String name) - throws MalformedObjectNameException { + throws MalformedObjectNameException, NullPointerException { return new ObjectName(name); } @@ -1444,7 +1294,6 @@ public class ObjectName implements Comparable, QueryExp { * follow the rules for quoting. * @exception NullPointerException One of the parameters is null. * - * @see #valueOf(String, String, String) */ public static ObjectName getInstance(String domain, String key, String value) @@ -1476,7 +1325,6 @@ public class ObjectName implements Comparable, QueryExp { * quoting. * @exception NullPointerException One of the parameters is null. * - * @see #valueOf(String, Hashtable) */ public static ObjectName getInstance(String domain, Hashtable table) @@ -1516,143 +1364,7 @@ public class ObjectName implements Comparable, QueryExp { public static ObjectName getInstance(ObjectName name) { if (name.getClass().equals(ObjectName.class)) return name; - return valueOf(name.getSerializedNameString()); - } - - /** - *

    Return an instance of ObjectName that can be used anywhere - * an object obtained with {@link #ObjectName(String) new - * ObjectName(name)} can be used. The returned object may be of - * a subclass of ObjectName. Calling this method twice with the - * same parameters may return the same object or two equal but - * not identical objects.

    - * - *

    This method is equivalent to {@link #getInstance(String)} except that - * it does not throw any checked exceptions.

    - * - * @param name A string representation of the object name. - * - * @return an ObjectName corresponding to the given String. - * - * @exception IllegalArgumentException The string passed as a - * parameter does not have the right format. The {@linkplain - * Throwable#getCause() cause} of this exception will be a - * {@link MalformedObjectNameException}. - * @exception NullPointerException The name parameter - * is null. - * - * @since 1.7 - */ - public static ObjectName valueOf(String name) { - try { - return getInstance(name); - } catch (MalformedObjectNameException e) { - throw new IllegalArgumentException(e.getMessage(), e); - // Just plain IllegalArgumentException(e) produces an exception - // message "javax.management.MalformedObjectNameException: ..." - // which is distracting. - } - } - - /** - *

    Return an instance of ObjectName that can be used anywhere - * an object obtained with {@link #ObjectName(String, String, - * String) new ObjectName(domain, key, value)} can be used. The - * returned object may be of a subclass of ObjectName. Calling - * this method twice with the same parameters may return the same - * object or two equal but not identical objects.

    - * - *

    This method is equivalent to {@link #getInstance(String, String, - * String)} except that it does not throw any checked exceptions.

    - * - * @param domain The domain part of the object name. - * @param key The attribute in the key property of the object name. - * @param value The value in the key property of the object name. - * - * @return an ObjectName corresponding to the given domain, - * key, and value. - * - * @exception IllegalArgumentException The - * domain, key, or value - * contains an illegal character, or value does not - * follow the rules for quoting. The {@linkplain - * Throwable#getCause() cause} of this exception will be a - * {@link MalformedObjectNameException}. - * @exception NullPointerException One of the parameters is null. - * - * @since 1.7 - */ - public static ObjectName valueOf(String domain, String key, String value) { - try { - return getInstance(domain, key, value); - } catch (MalformedObjectNameException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - /** - *

    Return an instance of ObjectName that can be used anywhere - * an object obtained with {@link #ObjectName(String, Hashtable) - * new ObjectName(domain, table)} can be used. The returned - * object may be of a subclass of ObjectName. Calling this method - * twice with the same parameters may return the same object or - * two equal but not identical objects.

    - * - *

    This method is equivalent to {@link #getInstance(String, Hashtable)} - * except that it does not throw any checked exceptions.

    - * - * @param domain The domain part of the object name. - * @param table A hash table containing one or more key - * properties. The key of each entry in the table is the key of a - * key property in the object name. The associated value in the - * table is the associated value in the object name. - * - * @return an ObjectName corresponding to the given domain and - * key mappings. - * - * @exception IllegalArgumentException The domain - * contains an illegal character, or one of the keys or values in - * table contains an illegal character, or one of the - * values in table does not follow the rules for - * quoting. The {@linkplain Throwable#getCause() cause} of this exception - * will be a {@link MalformedObjectNameException}. - * @exception NullPointerException One of the parameters is null. - * - * @since 1.7 - */ - public static ObjectName valueOf(String domain, - Hashtable table) { - try { - return new ObjectName(domain, table); - } catch (MalformedObjectNameException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - /** - * Returns an {@code ObjectName} that is the same as this one but - * with the specified domain. - * This method preserves the original key order in the new instance. - * If the provided name has a key property pattern, it will also be - * preserved in the returned instance. - * - * @param newDomain The new domain for the returned instance; - * must not be null. - * @return A new {@code ObjectName} that is the same as {@code this} - * except the domain is {@code newDomain}. - * @throws NullPointerException if {@code newDomain} is null. - * @exception IllegalArgumentException The {@code newDomain} passed as a - * parameter does not have the right format. The {@linkplain - * Throwable#getCause() cause} of this exception will be a - * {@link MalformedObjectNameException}. - * @since 1.7 - **/ - public final ObjectName withDomain(String newDomain) { - try { - return new ObjectName(newDomain, this); - } catch (MalformedObjectNameException x) { - throw new IllegalArgumentException(x.getMessage(),x); - } + return Util.newObjectName(name.getSerializedNameString()); } /** @@ -1664,8 +1376,6 @@ public class ObjectName implements Comparable, QueryExp { * parameter does not have the right format. * @exception NullPointerException The name parameter * is null. - * - * @see #valueOf(String) */ public ObjectName(String name) throws MalformedObjectNameException { @@ -1684,8 +1394,6 @@ public class ObjectName implements Comparable, QueryExp { * contains an illegal character, or value does not * follow the rules for quoting. * @exception NullPointerException One of the parameters is null. - * - * @see #valueOf(String, String, String) */ public ObjectName(String domain, String key, String value) throws MalformedObjectNameException { @@ -1711,8 +1419,6 @@ public class ObjectName implements Comparable, QueryExp { * values in table does not follow the rules for * quoting. * @exception NullPointerException One of the parameters is null. - * - * @see #valueOf(String, Hashtable) */ public ObjectName(String domain, Hashtable table) throws MalformedObjectNameException { @@ -1814,7 +1520,7 @@ public class ObjectName implements Comparable, QueryExp { throw new NullPointerException("key property can't be null"); for (int i = 0; i < _ca_array.length; i++) { Property prop = _ca_array[i]; - String key = prop.getKeyString(_canonicalName,_domain_length); + String key = prop.getKeyString(_canonicalName); if (key.equals(property)) return (prop instanceof PatternProperty); } @@ -1894,10 +1600,8 @@ public class ObjectName implements Comparable, QueryExp { Property prop; for (int i = len - 1; i >= 0; i--) { prop = _ca_array[i]; - _propertyList.put(prop.getKeyString(_canonicalName, - _domain_length), - prop.getValueString(_canonicalName, - _domain_length)); + _propertyList.put(prop.getKeyString(_canonicalName), + prop.getValueString(_canonicalName)); } } } @@ -1982,8 +1686,7 @@ public class ObjectName implements Comparable, QueryExp { } } - final String name = new String(dest_chars); - return name; + return new String(dest_chars); } /** @@ -2009,7 +1712,7 @@ public class ObjectName implements Comparable, QueryExp { for (int i = 0; i < len; i++) { final Property prop = _kp_array[i]; final int prop_len = prop._key_length + prop._value_length + 1; - System.arraycopy(value, prop._key_index+_domain_length, dest_chars, index, + System.arraycopy(value, prop._key_index, dest_chars, index, prop_len); index += prop_len; if (i < last ) dest_chars[index++] = ','; @@ -2054,10 +1757,6 @@ public class ObjectName implements Comparable, QueryExp { return getSerializedNameString(); } - String toQueryString() { - return "like " + Query.value(toString()); - } - /** * Compares the current object name with another object name. Two * ObjectName instances are equal if and only if their canonical @@ -2218,7 +1917,7 @@ public class ObjectName implements Comparable, QueryExp { * * @since 1.6 */ - public static final ObjectName WILDCARD = valueOf("*:*"); + public static final ObjectName WILDCARD = Util.newObjectName("*:*"); // Category : Utilities <=================================== @@ -2264,7 +1963,7 @@ public class ObjectName implements Comparable, QueryExp { // wildmatch domains // This ObjectName is the pattern // The other ObjectName is the string. - return Util.wildpathmatch(name.getDomain(),getDomain()); + return Util.wildmatch(name.getDomain(),getDomain()); } return getDomain().equals(name.getDomain()); } @@ -2290,7 +1989,7 @@ public class ObjectName implements Comparable, QueryExp { // index in receiver // final Property p = props[i]; - final String k = p.getKeyString(cn,_domain_length); + final String k = p.getKeyString(cn); final String v = nameProps.get(k); // Did we find a value for this key ? // @@ -2300,12 +1999,12 @@ public class ObjectName implements Comparable, QueryExp { if (_property_value_pattern && (p instanceof PatternProperty)) { // wildmatch key property values // p is the property pattern, v is the string - if (Util.wildmatch(v,p.getValueString(cn,_domain_length))) + if (Util.wildmatch(v,p.getValueString(cn))) continue; else return false; } - if (v.equals(p.getValueString(cn,_domain_length))) continue; + if (v.equals(p.getValueString(cn))) continue; return false; } return true; diff --git a/src/share/classes/javax/management/ObjectNameTemplate.java b/src/share/classes/javax/management/ObjectNameTemplate.java deleted file mode 100644 index 97e0c900f..000000000 --- a/src/share/classes/javax/management/ObjectNameTemplate.java +++ /dev/null @@ -1,131 +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 javax.management; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Annotation to allow an MBean to provide its name. - * This annotation can be used on the following types: - *
      - *
    • MBean or MXBean Java interface.
    • - *
    • Java class annotated with {@link javax.management.MBean @MBean} - * annotation.
    • - *
    • Java class annotated with {@link javax.management.MXBean @MXBean} - * annotation.
    • - *
    - * - *

    The value of this annotation is used to build the ObjectName - * when instances of the annotated type are registered in - * an MBeanServer and no explicit name is given to the - * {@code createMBean} or {@code registerMBean} method (the {@code ObjectName} - * is {@code null}).

    - * - *

    For Dynamic MBeans, which define their own {@code MBeanInfo}, you can - * produce the same effect as this annotation by including a field - * {@code objectNameTemplate} - * in the {@link Descriptor} for the {@code MBeanInfo} returned by - * {@link DynamicMBean#getMBeanInfo()}.

    - * - *

    For Standard MBeans and MXBeans, this annotation automatically produces - * an {@code objectNameTemplate} field in the {@code Descriptor}.

    - * - *

    The template can contain variables so that the name of the MBean - * depends on the value of one or more of its attributes. - * A variable that identifies an MBean attribute is of the form - * {attribute name}. For example, to make an MBean name - * depend on the Name attribute, use the variable - * {Name}. Attribute names are case sensitive. - * Naming attributes can be of any type. The String returned by - * toString() is included in the constructed name.

    - * - *

    If you need the attribute value to be quoted - * by a call to {@link ObjectName#quote(String) ObjectName.quote}, - * surround the variable with quotes. Quoting only applies to key values. - * For example, @ObjectNameTemplate("java.lang:type=MemoryPool,name=\"{Name}\""), - * quotes the Name attribute value. You can notice the "\" - * character needed to escape a quote within a String. A name - * produced by this template might look like - * {@code java.lang:type=MemoryPool,name="Code Cache"}.

    - * - *

    Variables can be used anywhere in the String. - * Be sure to make the template derived name comply with - * {@link ObjectName ObjectName} syntax.

    - * - *

    If an MBean is registered with a null name and it implements - * {@link javax.management.MBeanRegistration MBeanRegistration}, then - * the computed name is provided to the preRegister method. - * Similarly, - * if the MBean uses resource - * injection to discover its name, it is the computed name that will - * be injected.

    - *

    All of the above can be used with the {@link StandardMBean} class and - * the annotation is effective in that case too.

    - *

    If any exception occurs (such as unknown attribute, invalid syntax or - * exception - * thrown by the MBean) when the name is computed it is wrapped in a - * NotCompliantMBeanException.

    - *

    Some ObjectName template examples: - *

    • "com.example:type=Memory". Fixed ObjectName. Used to name a - * singleton MBean.
    • - *
    • "com.example:type=MemoryPool,name={Name}". Variable ObjectName. - * Name attribute is retrieved to compose the name - * key value.
    • - *
    • "com.example:type=SomeType,name={InstanceName},id={InstanceId}". - * Variable ObjectName. - * InstanceName and InstanceId attributes are - * retrieved to compose respectively - * the name and id key values.
    • - *
    • "com.example:type=OtherType,name=\"{ComplexName}\"". Variable ObjectName. - * ComplexName attribute is retrieved to compose the - * name key quoted value.
    • - *
    • "com.example:{TypeKey}=SomeOtherType". Variable ObjectName. - * TypeKey attribute is retrieved to compose the - * first key name.
    • - * *
    • "{Domain}:type=YetAnotherType". Variable ObjectName. - * Domain attribute is retrieved to compose the - * management domain.
    • - *
    • "{Naming}". Variable ObjectName. - * Naming attribute is retrieved to compose the - * complete name.
    • - *
    - *

    - */ -@Documented -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ObjectNameTemplate { - - /** - * The MBean name template. - * @return The MBean name template. - */ - @DescriptorKey("objectNameTemplate") - public String value(); -} diff --git a/src/share/classes/javax/management/OrQueryExp.java b/src/share/classes/javax/management/OrQueryExp.java index 4eca43f8a..187c8060f 100644 --- a/src/share/classes/javax/management/OrQueryExp.java +++ b/src/share/classes/javax/management/OrQueryExp.java @@ -104,24 +104,4 @@ class OrQueryExp extends QueryEval implements QueryExp { public String toString() { return "(" + exp1 + ") or (" + exp2 + ")"; } - - @Override - String toQueryString() { - return parens(exp1) + " or " + parens(exp2); - } - - // Add parentheses to avoid possible confusion. If we have an expression - // such as Query.or(Query.and(a, b), c), then we return - // (a and b) or c - // rather than just - // a and b or c - // In fact the precedence rules are such that the parentheses are not - // strictly necessary, but omitting them would be confusing. - private static String parens(QueryExp exp) { - String s = Query.toString(exp); - if (exp instanceof AndQueryExp) - return "(" + s + ")"; - else - return s; - } } diff --git a/src/share/classes/javax/management/QualifiedAttributeValueExp.java b/src/share/classes/javax/management/QualifiedAttributeValueExp.java index 9ed8e6dcc..3ed7d2cb6 100644 --- a/src/share/classes/javax/management/QualifiedAttributeValueExp.java +++ b/src/share/classes/javax/management/QualifiedAttributeValueExp.java @@ -113,8 +113,7 @@ class QualifiedAttributeValueExp extends AttributeValueExp { @Override public String toString() { if (className != null) { - return QueryParser.quoteId(className) + "#" + - QueryParser.quoteId(super.toString()); + return className + "." + super.toString(); } else { return super.toString(); } diff --git a/src/share/classes/javax/management/Query.java b/src/share/classes/javax/management/Query.java index e3a140e7d..25e3fb554 100644 --- a/src/share/classes/javax/management/Query.java +++ b/src/share/classes/javax/management/Query.java @@ -40,14 +40,6 @@ package javax.management; * but the methods in this class return only standard classes that are * part of the JMX implementation.

    * - *

    There are two ways to create {@code QueryExp} objects using the methods - * in this class. The first is to build them by chaining together calls to - * the various methods. The second is to use the Query Language described - * below and produce the {@code QueryExp} by calling - * {@link #fromString Query.fromString}. The two ways are equivalent: - * every {@code QueryExp} returned by {@code fromString} can also be - * constructed by chaining method calls.

    - * *

    As an example, suppose you wanted to find all MBeans where the {@code * Enabled} attribute is {@code true} and the {@code Owner} attribute is {@code * "Duke"}. Here is how you could construct the appropriate {@code QueryExp} by @@ -59,307 +51,6 @@ package javax.management; * Query.eq(Query.attr("Owner"), Query.value("Duke"))); * * - *

    Here is how you could construct the same {@code QueryExp} using the - * Query Language:

    - * - *
    - * QueryExp query = Query.fromString("Enabled = true and Owner = 'Duke'");
    - * 
    - * - *

    The principal advantage of the method-chaining approach is that the - * compiler will check that the query makes sense. The principal advantage - * of the Query Language approach is that it is easier to write and especially - * read.

    - * - * - *

    Query Language

    - * - *

    The query language is closely modeled on the WHERE clause of - * SQL SELECT statements. The formal specification of the language - * appears below, but it is probably easier to - * understand it with examples such as the following.

    - * - *
    - *
    {@code Message = 'OK'} - *
    Selects MBeans that have a {@code Message} attribute whose value - * is the string {@code OK}. - * - *
    {@code FreeSpacePercent < 10} - *
    Selects MBeans that have a {@code FreeSpacePercent} attribute whose - * value is a number less than 10. - * - *
    {@code FreeSpacePercent < 10 and WarningSent = false} - *
    Selects the same MBeans as the previous example, but they must - * also have a boolean attribute {@code WarningSent} whose value - * is false. - * - *
    {@code SpaceUsed > TotalSpace * (2.0 / 3.0)} - *
    Selects MBeans that have {@code SpaceUsed} and {@code TotalSpace} - * attributes where the first is more than two-thirds the second. - * - *
    {@code not (FreeSpacePercent between 10 and 90)} - *
    Selects MBeans that have a {@code FreeSpacePercent} attribute whose - * value is not between 10 and 90, inclusive. - * - *
    {@code FreeSpacePercent not between 10 and 90} - *
    Another way of writing the previous query. - * - *
    {@code Status in ('STOPPED', 'STARTING', 'STARTED')} - *
    Selects MBeans that have a {@code Status} attribute whose value - * is one of those three strings. - * - *
    {@code Message like 'OK: *'} - *
    Selects MBeans that have a {@code Message} attribute whose value - * is a string beginning with {@code "OK: "}. Notice that the - * wildcard characters are not the ones that SQL uses. In SQL, - * {@code %} means "any sequence of characters" and {@code _} - * means "any single character". Here, as in the rest of the JMX API, - * those are represented by {@code *} and {@code ?} respectively. - * - *
    {@code instanceof 'javax.management.NotificationBroadcaster'} - *
    Selects MBeans that are instances of - * {@link javax.management.NotificationBroadcaster}, as reported by - * {@link javax.management.MBeanServer#isInstanceOf MBeanServer.isInstanceOf}. - * - *
    {@code like 'mydomain:*'} - *
    Selects MBeans whose {@link ObjectName}s have the domain {@code mydomain}. - * - *
    - * - *

    The last two examples do not correspond to valid SQL syntax, but all - * the others do.

    - * - *

    The remainder of this description is a formal specification of the - * query language.

    - * - * - *

    Lexical elements

    - * - *

    Keywords such as and, like, and between are not - * case sensitive. You can write between, BETWEEN, or - * BeTwEeN with the same effect.

    - * - *

    On the other hand, attribute names are case sensitive. The - * attribute {@code Name} is not the same as the attribute {@code name}.

    - * - *

    To access an attribute whose name, ignoring case, is the same as one of - * the keywords {@code not}, {@code instanceof}, {@code like}, {@code true}, - * or {@code false}, you can use double quotes, for example {@code "not"}. - * Double quotes can also be used to include non-identifier characters in - * the name of an attribute, for example {@code "attribute-name-with-hyphens"}. - * To include the double quote character in the attribute name, write it - * twice. {@code "foo""bar""baz"} represents the attribute called - * {@code foo"bar"baz}. - * - *

    String constants are written with single quotes like {@code 'this'}. A - * single quote within a string constant must be doubled, for example - * {@code 'can''t'}.

    - * - *

    Integer constants are written as a sequence of decimal digits, - * optionally preceded by a plus or minus sign. An integer constant must be - * a valid input to {@link Long#valueOf(String)}.

    - * - *

    Floating-point constants are written using the Java syntax. A - * floating-point constant must be a valid input to - * {@link Double#valueOf(String)}.

    - * - *

    A boolean constant is either {@code true} or {@code false}, ignoring - * case.

    - * - *

    Spaces cannot appear inside identifiers (unless written with double - * quotes) or keywords or multi-character tokens such as {@code <=}. Spaces can - * appear anywhere else, but are not required except to separate tokens. For - * example, the query {@code a < b and 5 = c} could also be written {@code a - * - * - *

    Grammar

    - * - *
    - *
    query: - *
    andquery [OR query] - * - *
    andquery: - *
    predicate [AND andquery] - * - *
    predicate: - *
    ( query ) |
    - * NOT predicate |
    - * INSTANCEOF stringvalue |
    - * LIKE objectnamepattern |
    - * value predrhs - * - *
    predrhs: - *
    compare value |
    - * [NOT] BETWEEN value AND - * value |
    - * [NOT] IN ( value - * commavalues ) |
    - * [NOT] LIKE stringvalue - * - *
    commavalues: - *
    [ , value commavalues ] - * - *
    compare: - *
    = | < | > | - * <= | >= | <> | != - * - *
    value: - *
    factor [plusorminus - * value] - * - *
    plusorminus: - *
    + | - - * - *
    factor: - *
    term [timesordivide - * factor] - * - *
    timesordivide: - *
    * | / - * - *
    term: - *
    attr | literal | - * ( value ) - * - *
    attr: - *
    name [# name] - * - *
    name: - *
    identifier [.name] - * - *
    identifier: - *
    Java-identifier | double-quoted-identifier - * - *
    literal: - *
    booleanlit | longlit | - * doublelit | stringlit - * - *
    booleanlit: - *
    FALSE | TRUE - * - *
    stringvalue: - *
    stringlit - * - *
    objectnamepattern: - *
    stringlit - * - *
    - * - * - *

    Semantics

    - * - *

    The meaning of the grammar is described in the table below. - * This defines a function q that maps a string to a Java object - * such as a {@link QueryExp} or a {@link ValueExp}.

    - * - * - * - * - *
    String sq(s)
    query1 OR query2 - * {@link Query#or Query.or}(q(query1), q(query2)) - * - *
    query1 AND query2 - * {@link Query#and Query.and}(q(query1), q(query2)) - * - *
    ( queryOrValue ) - * q(queryOrValue) - * - *
    NOT query - * {@link Query#not Query.not}(q(query)) - * - *
    INSTANCEOF stringLiteral - * {@link Query#isInstanceOf Query.isInstanceOf}({@link Query#value(String) Query.value}(q(stringLiteral))) - * - *
    LIKE stringLiteral - * {@link ObjectName#ObjectName(String) new ObjectName}(q(stringLiteral)) - * - *
    value1 = value2 - * {@link Query#eq Query.eq}(q(value1), q(value2)) - * - *
    value1 < value2 - * {@link Query#lt Query.lt}(q(value1), q(value2)) - * - *
    value1 > value2 - * {@link Query#gt Query.gt}(q(value1), q(value2)) - * - *
    value1 <= value2 - * {@link Query#leq Query.leq}(q(value1), q(value2)) - * - *
    value1 >= value2 - * {@link Query#geq Query.geq}(q(value1), q(value2)) - * - *
    value1 <> value2 - * {@link Query#not Query.not}({@link Query#eq Query.eq}(q(value1), q(value2))) - * - *
    value1 != value2 - * {@link Query#not Query.not}({@link Query#eq Query.eq}(q(value1), q(value2))) - * - *
    value1 BETWEEN value2 AND value3 - * {@link Query#between Query.between}(q(value1), - * q(value2), q(value3)) - * - *
    value1 NOT BETWEEN value2 AND value3 - * {@link Query#not Query.not}({@link Query#between Query.between}(q(value1), q(value2), q(value3))) - * - *
    value1 IN ( value2, value3 ) - * {@link Query#in Query.in}(q(value1), - * new ValueExp[] { - * q(value2), q(value3)}) - * - *
    value1 NOT IN ( value2, value3 ) - * {@link Query#not Query.not}({@link Query#in Query.in}(q(value1), - * new ValueExp[] { - * q(value2), q(value3)})) - * - *
    value LIKE stringLiteral - * {@link Query#match Query.match}(q(value), - * q(stringLiteral)) - * - *
    value NOT LIKE stringLiteral - * {@link Query#not Query.not}({@link Query#match Query.match}(q(value), - * q(stringLiteral))) - * - *
    value1 + value2 - * {@link Query#plus Query.plus}(q(value1), q(value2)) - * - *
    value1 - value2 - * {@link Query#minus Query.minus}(q(value1), q(value2)) - * - *
    value1 * value2 - * {@link Query#times Query.times}(q(value1), q(value2)) - * - *
    value1 / value2 - * {@link Query#div Query.div}(q(value1), q(value2)) - * - *
    name - * {@link Query#attr(String) Query.attr}(q(name)) - * - *
    name1#name2 - * {@link Query#attr(String,String) Query.attr}(q(name1), - * q(name2)) - * - *
    FALSE - * {@link Query#value(boolean) Query.value}(false) - * - *
    TRUE - * {@link Query#value(boolean) Query.value}(true) - * - *
    decimalLiteral - * {@link Query#value(long) Query.value}({@link Long#valueOf(String) Long.valueOf}(decimalLiteral)) - * - *
    floatingPointLiteral - * {@link Query#value(double) Query.value}({@link Double#valueOf(String) Double.valueOf}(floatingPointLiteral)) - *
    - * * @since 1.5 */ public class Query extends Object { @@ -600,6 +291,11 @@ package javax.management; *

    Returns a new attribute expression. See {@link AttributeValueExp} * for a detailed description of the semantics of the expression.

    * + *

    Evaluating this expression for a given + * objectName includes performing {@link + * MBeanServer#getAttribute MBeanServer.getAttribute(objectName, + * name)}.

    + * * @param name The name of the attribute. * * @return An attribute expression for the attribute named {@code name}. @@ -943,73 +639,6 @@ package javax.management; return new InstanceOfQueryExp(classNameValue); } - /** - *

    Return a string representation of the given query. The string - * returned by this method can be converted back into an equivalent - * query using {@link #fromString fromString}.

    - * - *

    (Two queries are equivalent if they produce the same result in - * all cases. Equivalent queries are not necessarily identical: - * for example the queries {@code Query.lt(Query.attr("A"), Query.attr("B"))} - * and {@code Query.not(Query.ge(Query.attr("A"), Query.attr("B")))} are - * equivalent but not identical.)

    - * - *

    The string returned by this method is only guaranteed to be converted - * back into an equivalent query if {@code query} was constructed, or - * could have been constructed, using the methods of this class. - * If you make a custom query {@code myQuery} by implementing - * {@link QueryExp} yourself then the result of - * {@code Query.toString(myQuery)} is unspecified.

    - * - * @param query the query to convert. If it is null, the result will - * also be null. - * @return the string representation of the query, or null if the - * query is null. - * - * @since 1.7 - */ - public static String toString(QueryExp query) { - if (query == null) - return null; - - // This is ugly. At one stage we had a non-public class called - // ToQueryString with the toQueryString() method, and every class - // mentioned here inherited from that class. But that interfered - // with serialization of custom subclasses of e.g. QueryEval. Even - // though we could make it work by adding a public constructor to this - // non-public class, that seemed fragile because according to the - // serialization spec it shouldn't work. If only non-public interfaces - // could have non-public methods. - if (query instanceof ObjectName) - return ((ObjectName) query).toQueryString(); - if (query instanceof QueryEval) - return ((QueryEval) query).toQueryString(); - - return query.toString(); - } - - /** - *

    Produce a query from the given string. The query returned - * by this method can be converted back into a string using - * {@link #toString(QueryExp) toString}. The resultant string will - * not necessarily be equal to {@code s}.

    - * - * @param s the string to convert. - * - * @return a {@code QueryExp} derived by parsing the string, or - * null if the string is null. - * - * @throws IllegalArgumentException if the string is not a valid - * query string. - * - * @since 1.7 - */ - public static QueryExp fromString(String s) { - if (s == null) - return null; - return new QueryParser(s).parseQuery(); - } - /** * Utility method to escape strings used with * Query.{initial|any|final}SubString() methods. diff --git a/src/share/classes/javax/management/QueryEval.java b/src/share/classes/javax/management/QueryEval.java index ee781ab0c..eeb19f6c6 100644 --- a/src/share/classes/javax/management/QueryEval.java +++ b/src/share/classes/javax/management/QueryEval.java @@ -75,10 +75,4 @@ public abstract class QueryEval implements Serializable { public static MBeanServer getMBeanServer() { return server.get(); } - - // Subclasses in this package can override this method to return a different - // string. - String toQueryString() { - return toString(); - } } diff --git a/src/share/classes/javax/management/QueryNotificationFilter.java b/src/share/classes/javax/management/QueryNotificationFilter.java deleted file mode 100644 index 5d7e7815b..000000000 --- a/src/share/classes/javax/management/QueryNotificationFilter.java +++ /dev/null @@ -1,415 +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 javax.management; - -import com.sun.jmx.mbeanserver.NotificationMBeanSupport; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Collections; -import java.util.Set; - -/** - *

    General-purpose notification filter. This filter can be used to - * filter notifications from a possibly-remote MBean. Most filtering - * decisions can be coded using this filter, which avoids having to - * write a custom implementation of the {@link NotificationFilter} - * class. Writing a custom implementation requires you to deploy it - * on both the client and the server in the remote case, so using this class - * instead is recommended where possible.

    - * - *

    Because this class was introduced in version 2.0 of the JMX API, - * it may not be present on a remote JMX agent that is running an earlier - * version. The method {@link JMX#getSpecificationVersion - * JMX.getSpecificationVersion} can be used to determine the remote version.

    - * - *

    This class uses the {@linkplain Query Query API} to specify the - * filtering logic. For example, to select only notifications where the - * {@linkplain Notification#getType() type} is {@code "com.example.mytype"}, - * you could use

    - * - *
    - * NotificationFilter filter =
    - *     new QueryNotificationFilter("Type = 'com.example.mytype'");
    - * 
    - * - *

    or equivalently

    - * - *
    - * NotificationFilter filter =
    - *     new QueryNotificationFilter(
    - *             Query.eq(Query.attr("Type"), Query.value("com.example.mytype")));
    - * 
    - * - *

    (This particular example could also use - * {@link NotificationFilterSupport}.)

    - * - *

    Here are some other examples of filters you can specify with this class.

    - * - *
    - * - *
    {@code QueryNotificationFilter("Type = 'com.example.type1' or - * Type = 'com.example.type2'")} - *
    Notifications where the type is either of the given strings. - * - *
    {@code QueryNotificationFilter("Type in ('com.example.type1', - * 'com.example.type2')")} - *
    Another way to write the previous example. - * - *
    {@code QueryNotificationFilter("SequenceNumber > 1000")} - *
    Notifications where the {@linkplain Notification#getSequenceNumber() - * sequence number} is greater than 1000. - * - *
    {@code QueryNotificationFilter(AttributeChangeNotification.class, null)} - *
    Notifications where the notification class is - * {@link AttributeChangeNotification} or a subclass of it. - * - *
    {@code QueryNotificationFilter(AttributeChangeNotification.class, - * "AttributeName = 'Size'")} - *
    Notifications where the notification class is - * {@link AttributeChangeNotification} or a subclass, and where the - * {@linkplain AttributeChangeNotification#getAttributeName() name of the - * changed attribute} is {@code Size}. - * - *
    {@code QueryNotificationFilter(AttributeChangeNotification.class, - * "AttributeName = 'Size' and NewValue - OldValue > 100")} - *
    As above, but the difference between the - * {@linkplain AttributeChangeNotification#getNewValue() new value} and the - * {@linkplain AttributeChangeNotification#getOldValue() old value} must be - * greater than 100. - * - *
    {@code QueryNotificationFilter("like 'com.example.mydomain:*'")} - *
    Notifications where the {@linkplain Notification#getSource() source} - * is an ObjectName that matches the pattern. - * - *
    {@code QueryNotificationFilter("Source.canonicalName like - * 'com.example.mydomain:%'")} - *
    Another way to write the previous example. - * - *
    {@code QueryNotificationFilter(MBeanServerNotification.class, - * "Type = 'JMX.mbean.registered' and MBeanName.canonicalName like - * 'com.example.mydomain:%'")} - *
    Notifications of class {@link MBeanServerNotification} representing - * an object registered in the domain {@code com.example.mydomain}. - * - *
    - * - *

    How it works

    - * - *

    Although the examples above are clear, looking closely at the - * Query API reveals a subtlety. A {@link QueryExp} is evaluated on - * an {@link ObjectName}, not a {@code Notification}.

    - * - *

    Every time a {@code Notification} is to be filtered by a - * {@code QueryNotificationFilter}, a special {@link MBeanServer} is created. - * This {@code MBeanServer} contains exactly one MBean, which represents the - * {@code Notification}. If the {@linkplain Notification#getSource() - * source} of the notification is an {@code ObjectName}, which is - * recommended practice, then the name of the MBean representing the - * {@code Notification} will be this {@code ObjectName}. Otherwise the - * name is unspecified.

    - * - *

    The query specified in the {@code QueryNotificationFilter} constructor - * is evaluated against this {@code MBeanServer} and {@code ObjectName}, - * and the filter returns true if and only if the query does. If the - * query throws an exception, then the filter will return false.

    - * - *

    The MBean representing the {@code Notification} has one attribute for - * every property of the {@code Notification}. Specifically, for every public - * method {@code T getX()} in the {@code NotificationClass}, the MBean will - * have an attribute called {@code X} of type {@code T}. For example, if the - * {@code Notification} is an {@code AttributeChangeNotification}, then the - * MBean will have an attribute called {@code AttributeName} of type - * {@code "java.lang.String"}, corresponding to the method {@link - * AttributeChangeNotification#getAttributeName}.

    - * - *

    Query evaluation usually involves calls to the methods of {@code - * MBeanServer}. The methods have the following behavior:

    - * - *
      - *
    • The {@link MBeanServer#getAttribute getAttribute} method returns the - * value of the corresponding property. - *
    • The {@link MBeanServer#getObjectInstance getObjectInstance} - * method returns an {@link ObjectInstance} where the {@link - * ObjectInstance#getObjectName ObjectName} is the name of the MBean and the - * {@link ObjectInstance#getClassName ClassName} is the class name of the - * {@code Notification}. - *
    • The {@link MBeanServer#isInstanceOf isInstanceOf} method returns true - * if and only if the {@code Notification}'s {@code ClassLoader} can load the - * named class, and the {@code Notification} is an {@linkplain Class#isInstance - * instance} of that class. - *
    - * - *

    These are the only {@code MBeanServer} methods that are needed to - * evaluate standard queries. The behavior of the other {@code MBeanServer} - * methods is unspecified.

    - * - * @since 1.7 - */ -public class QueryNotificationFilter implements NotificationFilter { - private static final long serialVersionUID = -8408613922660635231L; - - private static final ObjectName DEFAULT_NAME = - ObjectName.valueOf(":type=Notification"); - private static final QueryExp trueQuery; - static { - ValueExp zero = Query.value(0); - trueQuery = Query.eq(zero, zero); - } - - private final QueryExp query; - - /** - * Construct a {@code QueryNotificationFilter} that evaluates the given - * {@code QueryExp} to determine whether to accept a notification. - * - * @param query the {@code QueryExp} to evaluate. Can be null, - * in which case all notifications are accepted. - */ - public QueryNotificationFilter(QueryExp query) { - if (query == null) - this.query = trueQuery; - else - this.query = query; - } - - /** - * Construct a {@code QueryNotificationFilter} that evaluates the query - * in the given string to determine whether to accept a notification. - * The string is converted into a {@code QueryExp} using - * {@link Query#fromString Query.fromString}. - * - * @param query the string specifying the query to evaluate. Can be null, - * in which case all notifications are accepted. - * - * @throws IllegalArgumentException if the string is not a valid - * query string. - */ - public QueryNotificationFilter(String query) { - this(Query.fromString(query)); - } - - /** - *

    Construct a {@code QueryNotificationFilter} that evaluates the query - * in the given string to determine whether to accept a notification, - * and where the notification must also be an instance of the given class. - * The string is converted into a {@code QueryExp} using - * {@link Query#fromString Query.fromString}.

    - * - * @param notifClass the class that the notification must be an instance of. - * Cannot be null. - * - * @param query the string specifying the query to evaluate. Can be null, - * in which case all notifications are accepted. - * - * @throws IllegalArgumentException if the string is not a valid - * query string, or if {@code notifClass} is null. - */ - public QueryNotificationFilter( - Class notifClass, String query) { - this(Query.and(Query.isInstanceOf(Query.value(notNull(notifClass).getName())), - Query.fromString(query))); - } - - private static T notNull(T x) { - if (x == null) - throw new IllegalArgumentException("Null argument"); - return x; - } - - /** - * Retrieve the query that this notification filter will evaluate for - * each notification. - * - * @return the query. - */ - public QueryExp getQuery() { - return query; - } - - public boolean isNotificationEnabled(Notification notification) { - ObjectName name; - - Object source = notification.getSource(); - if (source instanceof ObjectName) - name = (ObjectName) source; - else - name = DEFAULT_NAME; - - MBS mbsImpl = new MBS(notification, name); - MBeanServer mbs = (MBeanServer) Proxy.newProxyInstance( - MBeanServer.class.getClassLoader(), - new Class[] {MBeanServer.class}, - new ForwardIH(mbsImpl)); - return evalQuery(query, mbs, name); - } - - private static boolean evalQuery( - QueryExp query, MBeanServer mbs, ObjectName name) { - MBeanServer oldMBS = QueryEval.getMBeanServer(); - try { - if (mbs != null) - query.setMBeanServer(mbs); - return query.apply(name); - } catch (Exception e) { - return false; - } finally { - query.setMBeanServer(oldMBS); - } - } - - private static class ForwardIH implements InvocationHandler { - private final MBS mbs; - - ForwardIH(MBS mbs) { - this.mbs = mbs; - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - Method forward; - try { - forward = MBS.class.getMethod( - method.getName(), method.getParameterTypes()); - } catch (NoSuchMethodException e) { - throw new UnsupportedOperationException(method.getName()); - } - try { - return forward.invoke(mbs, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static class MBS { - private final Notification notification; - private final ObjectName objectName; - private final ObjectInstance objectInstance; - private volatile DynamicMBean mbean; - - MBS(Notification n, ObjectName name) { - this.notification = n; - this.objectName = name; - this.objectInstance = new ObjectInstance(name, n.getClass().getName()); - } - - private void checkName(ObjectName name) throws InstanceNotFoundException { - if (!objectName.equals(name)) - throw new InstanceNotFoundException(String.valueOf(name)); - } - - private DynamicMBean mbean(ObjectName name) - throws InstanceNotFoundException, ReflectionException { - if (mbean == null) { - try { - mbean = new NotificationMBeanSupport(notification); - } catch (NotCompliantMBeanException e) { - throw new ReflectionException(e); - } - } - return mbean; - } - - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - checkName(name); - return objectInstance; - } - - public Set queryMBeans(ObjectName name, QueryExp query) { - Set names = queryNames(name, query); - switch (names.size()) { - case 0: - return Collections.emptySet(); - case 1: - return Collections.singleton(objectInstance); - default: - throw new UnsupportedOperationException("Internal error"); - } - } - - public Set queryNames(ObjectName name, QueryExp query) { - if ((name != null && !name.apply(objectName)) || - (query != null && !evalQuery(query, null, name))) - return Collections.emptySet(); - return Collections.singleton(objectName); - } - - public boolean isRegistered(ObjectName name) { - return objectName.equals(name); - } - - public Integer getMBeanCount() { - return 1; - } - - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - return mbean(name).getAttribute(attribute); - } - - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - return mbean(name).getAttributes(attributes); - } - - public String getDefaultDomain() { - return objectName.getDomain(); - } - - public String[] getDomains() { - return new String[] {objectName.getDomain()}; - } - - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, ReflectionException { - return mbean(name).getMBeanInfo(); - } - - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - try { - mbean(name); - ClassLoader loader = notification.getClass().getClassLoader(); - Class c = Class.forName(className, false, loader); - return c.isInstance(notification); - } catch (ReflectionException e) { - return false; - } catch (ClassNotFoundException e) { - return false; - } - } - - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - checkName(mbeanName); - return notification.getClass().getClassLoader(); - } - } -} diff --git a/src/share/classes/javax/management/QueryParser.java b/src/share/classes/javax/management/QueryParser.java deleted file mode 100644 index 715f42070..000000000 --- a/src/share/classes/javax/management/QueryParser.java +++ /dev/null @@ -1,626 +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 javax.management; - -import java.util.ArrayList; -import java.util.Formatter; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -/** - *

    Parser for JMX queries represented in an SQL-like language.

    - */ -/* - * Note that if a query starts with ( then we don't know whether it is - * a predicate or just a value that is parenthesized. So, inefficiently, - * we try to parse a predicate and if that doesn't work we try to parse - * a value. - */ -class QueryParser { - // LEXER STARTS HERE - - private static class Token { - final String string; - Token(String s) { - this.string = s; - } - - @Override - public String toString() { - return string; - } - } - - private static final Token - END = new Token(""), - LPAR = new Token("("), RPAR = new Token(")"), - COMMA = new Token(","), DOT = new Token("."), SHARP = new Token("#"), - PLUS = new Token("+"), MINUS = new Token("-"), - TIMES = new Token("*"), DIVIDE = new Token("/"), - LT = new Token("<"), GT = new Token(">"), - LE = new Token("<="), GE = new Token(">="), - NE = new Token("<>"), EQ = new Token("="), - NOT = new Id("NOT"), INSTANCEOF = new Id("INSTANCEOF"), - FALSE = new Id("FALSE"), TRUE = new Id("TRUE"), - BETWEEN = new Id("BETWEEN"), AND = new Id("AND"), - OR = new Id("OR"), IN = new Id("IN"), - LIKE = new Id("LIKE"), CLASS = new Id("CLASS"); - - // Keywords that can appear where an identifier can appear. - // If an attribute is one of these, then it must be quoted when - // converting a query into a string. - // We use a TreeSet so we can look up case-insensitively. - private static final Set idKeywords = - new TreeSet(String.CASE_INSENSITIVE_ORDER); - static { - for (Token t : new Token[] {NOT, INSTANCEOF, FALSE, TRUE, LIKE, CLASS}) - idKeywords.add(t.string); - }; - - public static String quoteId(String id) { - if (id.contains("\"") || idKeywords.contains(id)) - return '"' + id.replace("\"", "\"\"") + '"'; - else - return id; - } - - private static class Id extends Token { - Id(String id) { - super(id); - } - - // All other tokens use object identity, which means e.g. that one - // occurrence of the string constant 'x' is not the same as another. - // For identifiers, we ignore case when testing for equality so that - // for a keyword such as AND you can also spell it as "And" or "and". - // But we keep the original case of the identifier, so if it's not - // a keyword we will distinguish between the attribute Foo and the - // attribute FOO. - @Override - public boolean equals(Object o) { - return (o instanceof Id && (((Id) o).toString().equalsIgnoreCase(toString()))); - } - } - - private static class QuotedId extends Token { - QuotedId(String id) { - super(id); - } - - @Override - public String toString() { - return '"' + string.replace("\"", "\"\"") + '"'; - } - } - - private static class StringLit extends Token { - StringLit(String s) { - super(s); - } - - @Override - public String toString() { - return '\'' + string.replace("'", "''") + '\''; - } - } - - private static class LongLit extends Token { - long number; - - LongLit(long number) { - super(Long.toString(number)); - this.number = number; - } - } - - private static class DoubleLit extends Token { - double number; - - DoubleLit(double number) { - super(Double.toString(number)); - this.number = number; - } - } - - private static class Tokenizer { - private final String s; - private final int len; - private int i = 0; - - Tokenizer(String s) { - this.s = s; - this.len = s.length(); - } - - private int thisChar() { - if (i == len) - return -1; - return s.codePointAt(i); - } - - private void advance() { - i += Character.charCount(thisChar()); - } - - private int thisCharAdvance() { - int c = thisChar(); - advance(); - return c; - } - - Token nextToken() { - // In this method, c is the character we're looking at, and - // thisChar() is the character after that. Everything must - // preserve these invariants. When we return we then have - // thisChar() being the start of the following token, so - // the next call to nextToken() will begin from there. - int c; - - // Skip space - do { - if (i == len) - return null; - c = thisCharAdvance(); - } while (Character.isWhitespace(c)); - - // Now c is the first character of the token, and tokenI points - // to the character after that. - switch (c) { - case '(': return LPAR; - case ')': return RPAR; - case ',': return COMMA; - case '.': return DOT; - case '#': return SHARP; - case '*': return TIMES; - case '/': return DIVIDE; - case '=': return EQ; - case '-': return MINUS; - case '+': return PLUS; - - case '>': - if (thisChar() == '=') { - advance(); - return GE; - } else - return GT; - - case '<': - c = thisChar(); - switch (c) { - case '=': advance(); return LE; - case '>': advance(); return NE; - default: return LT; - } - - case '!': - if (thisCharAdvance() != '=') - throw new IllegalArgumentException("'!' must be followed by '='"); - return NE; - - case '"': - case '\'': { - int quote = c; - StringBuilder sb = new StringBuilder(); - while (true) { - while ((c = thisChar()) != quote) { - if (c < 0) { - throw new IllegalArgumentException( - "Unterminated string constant"); - } - sb.appendCodePoint(thisCharAdvance()); - } - advance(); - if (thisChar() == quote) { - sb.appendCodePoint(quote); - advance(); - } else - break; - } - if (quote == '\'') - return new StringLit(sb.toString()); - else - return new QuotedId(sb.toString()); - } - } - - // Is it a numeric constant? - if (Character.isDigit(c) || c == '.') { - StringBuilder sb = new StringBuilder(); - int lastc = -1; - while (true) { - sb.appendCodePoint(c); - c = Character.toLowerCase(thisChar()); - if (c == '+' || c == '-') { - if (lastc != 'e') - break; - } else if (!Character.isDigit(c) && c != '.' && c != 'e') - break; - lastc = c; - advance(); - } - String s = sb.toString(); - if (s.indexOf('.') >= 0 || s.indexOf('e') >= 0) { - double d = parseDoubleCheckOverflow(s); - return new DoubleLit(d); - } else { - // Like the Java language, we allow the numeric constant - // x where -x = Long.MIN_VALUE, even though x is not - // representable as a long (it is Long.MAX_VALUE + 1). - // Code in the parser will reject this value if it is - // not the operand of unary minus. - long l = -Long.parseLong("-" + s); - return new LongLit(l); - } - } - - // It must be an identifier. - if (!Character.isJavaIdentifierStart(c)) { - StringBuilder sb = new StringBuilder(); - Formatter f = new Formatter(sb); - f.format("Bad character: %c (%04x)", c, c); - throw new IllegalArgumentException(sb.toString()); - } - - StringBuilder id = new StringBuilder(); - while (true) { // identifier - id.appendCodePoint(c); - c = thisChar(); - if (!Character.isJavaIdentifierPart(c)) - break; - advance(); - } - - return new Id(id.toString()); - } - } - - /* Parse a double as a Java compiler would do it, throwing an exception - * if the input does not fit in a double. We assume that the input - * string is not "Infinity" and does not have a leading sign. - */ - private static double parseDoubleCheckOverflow(String s) { - double d = Double.parseDouble(s); - if (Double.isInfinite(d)) - throw new NumberFormatException("Overflow: " + s); - if (d == 0.0) { // Underflow checking is hard! CR 6604864 - String ss = s; - int e = s.indexOf('e'); // we already forced E to lowercase - if (e > 0) - ss = s.substring(0, e); - ss = ss.replace("0", "").replace(".", ""); - if (!ss.equals("")) - throw new NumberFormatException("Underflow: " + s); - } - return d; - } - - // PARSER STARTS HERE - - private final List tokens; - private int tokenI; - // The current token is always tokens[tokenI]. - - QueryParser(String s) { - // Construct the complete list of tokens immediately and append - // a sentinel (END). - tokens = new ArrayList(); - Tokenizer tokenizer = new Tokenizer(s); - Token t; - while ((t = tokenizer.nextToken()) != null) - tokens.add(t); - tokens.add(END); - } - - private Token current() { - return tokens.get(tokenI); - } - - // If the current token is t, then skip it and return true. - // Otherwise, return false. - private boolean skip(Token t) { - if (t.equals(current())) { - tokenI++; - return true; - } - return false; - } - - // If the current token is one of the ones in 'tokens', then skip it - // and return its index in 'tokens'. Otherwise, return -1. - private int skipOne(Token... tokens) { - for (int i = 0; i < tokens.length; i++) { - if (skip(tokens[i])) - return i; - } - return -1; - } - - // If the current token is t, then skip it and return. - // Otherwise throw an exception. - private void expect(Token t) { - if (!skip(t)) - throw new IllegalArgumentException("Expected " + t + ", found " + current()); - } - - private void next() { - tokenI++; - } - - QueryExp parseQuery() { - QueryExp qe = query(); - if (current() != END) - throw new IllegalArgumentException("Junk at end of query: " + current()); - return qe; - } - - // The remainder of this class is a classical recursive-descent parser. - // We only need to violate the recursive-descent scheme in one place, - // where parentheses make the grammar not LL(1). - - private QueryExp query() { - QueryExp lhs = andquery(); - while (skip(OR)) - lhs = Query.or(lhs, andquery()); - return lhs; - } - - private QueryExp andquery() { - QueryExp lhs = predicate(); - while (skip(AND)) - lhs = Query.and(lhs, predicate()); - return lhs; - } - - private QueryExp predicate() { - // Grammar hack. If we see a paren, it might be (query) or - // it might be (value). We try to parse (query), and if that - // fails, we parse (value). For example, if the string is - // "(2+3)*4 < 5" then we will try to parse the query - // "2+3)*4 < 5", which will fail at the ), so we'll back up to - // the paren and let value() handle it. - if (skip(LPAR)) { - int parenIndex = tokenI - 1; - try { - QueryExp qe = query(); - expect(RPAR); - return qe; - } catch (IllegalArgumentException e) { - // OK: try parsing a value - } - tokenI = parenIndex; - } - - if (skip(NOT)) - return Query.not(predicate()); - - if (skip(INSTANCEOF)) - return Query.isInstanceOf(stringvalue()); - - if (skip(LIKE)) { - StringValueExp sve = stringvalue(); - String s = sve.getValue(); - try { - return new ObjectName(s); - } catch (MalformedObjectNameException e) { - throw new IllegalArgumentException( - "Bad ObjectName pattern after LIKE: '" + s + "'", e); - } - } - - ValueExp lhs = value(); - - return predrhs(lhs); - } - - // The order of elements in the following arrays is important. The code - // in predrhs depends on integer indexes. Change with caution. - private static final Token[] relations = { - EQ, LT, GT, LE, GE, NE, - // 0, 1, 2, 3, 4, 5, - }; - private static final Token[] betweenLikeIn = { - BETWEEN, LIKE, IN - // 0, 1, 2, - }; - - private QueryExp predrhs(ValueExp lhs) { - Token start = current(); // for errors - - // Look for < > = etc - int i = skipOne(relations); - if (i >= 0) { - ValueExp rhs = value(); - switch (i) { - case 0: return Query.eq(lhs, rhs); - case 1: return Query.lt(lhs, rhs); - case 2: return Query.gt(lhs, rhs); - case 3: return Query.leq(lhs, rhs); - case 4: return Query.geq(lhs, rhs); - case 5: return Query.not(Query.eq(lhs, rhs)); - // There is no Query.ne so <> is shorthand for the above. - default: - throw new AssertionError(); - } - } - - // Must be BETWEEN LIKE or IN, optionally preceded by NOT - boolean not = skip(NOT); - i = skipOne(betweenLikeIn); - if (i < 0) - throw new IllegalArgumentException("Expected relation at " + start); - - QueryExp q; - switch (i) { - case 0: { // BETWEEN - ValueExp lower = value(); - expect(AND); - ValueExp upper = value(); - q = Query.between(lhs, lower, upper); - break; - } - - case 1: { // LIKE - if (!(lhs instanceof AttributeValueExp)) { - throw new IllegalArgumentException( - "Left-hand side of LIKE must be an attribute"); - } - AttributeValueExp alhs = (AttributeValueExp) lhs; - StringValueExp sve = stringvalue(); - q = Query.match(alhs, sve); - break; - } - - case 2: { // IN - expect(LPAR); - List values = new ArrayList(); - values.add(value()); - while (skip(COMMA)) - values.add(value()); - expect(RPAR); - q = Query.in(lhs, values.toArray(new ValueExp[values.size()])); - break; - } - - default: - throw new AssertionError(); - } - - if (not) - q = Query.not(q); - - return q; - } - - private ValueExp value() { - ValueExp lhs = factor(); - int i; - while ((i = skipOne(PLUS, MINUS)) >= 0) { - ValueExp rhs = factor(); - if (i == 0) - lhs = Query.plus(lhs, rhs); - else - lhs = Query.minus(lhs, rhs); - } - return lhs; - } - - private ValueExp factor() { - ValueExp lhs = term(); - int i; - while ((i = skipOne(TIMES, DIVIDE)) >= 0) { - ValueExp rhs = term(); - if (i == 0) - lhs = Query.times(lhs, rhs); - else - lhs = Query.div(lhs, rhs); - } - return lhs; - } - - private ValueExp term() { - boolean signed = false; - int sign = +1; - if (skip(PLUS)) - signed = true; - else if (skip(MINUS)) { - signed = true; sign = -1; - } - - Token t = current(); - next(); - - if (t instanceof DoubleLit) - return Query.value(sign * ((DoubleLit) t).number); - if (t instanceof LongLit) { - long n = ((LongLit) t).number; - if (n == Long.MIN_VALUE && sign != -1) - throw new IllegalArgumentException("Illegal positive integer: " + n); - return Query.value(sign * n); - } - if (signed) - throw new IllegalArgumentException("Expected number after + or -"); - - if (t == LPAR) { - ValueExp v = value(); - expect(RPAR); - return v; - } - if (t.equals(FALSE) || t.equals(TRUE)) { - return Query.value(t.equals(TRUE)); - } - if (t.equals(CLASS)) - return Query.classattr(); - - if (t instanceof StringLit) - return Query.value(t.string); // Not toString(), which would requote ' - - // At this point, all that remains is something that will call Query.attr - - if (!(t instanceof Id) && !(t instanceof QuotedId)) - throw new IllegalArgumentException("Unexpected token " + t); - - String name1 = name(t); - - if (skip(SHARP)) { - Token t2 = current(); - next(); - String name2 = name(t2); - return Query.attr(name1, name2); - } - return Query.attr(name1); - } - - // Initially, t is the first token of a supposed name and current() - // is the second. - private String name(Token t) { - StringBuilder sb = new StringBuilder(); - while (true) { - if (!(t instanceof Id) && !(t instanceof QuotedId)) - throw new IllegalArgumentException("Unexpected token " + t); - sb.append(t.string); - if (current() != DOT) - break; - sb.append('.'); - next(); - t = current(); - next(); - } - return sb.toString(); - } - - private StringValueExp stringvalue() { - // Currently the only way to get a StringValueExp when constructing - // a QueryExp is via Query.value(String), so we only recognize - // string literals here. But if we expand queries in the future - // that might no longer be true. - Token t = current(); - next(); - if (!(t instanceof StringLit)) - throw new IllegalArgumentException("Expected string: " + t); - return Query.value(t.string); - } -} diff --git a/src/share/classes/javax/management/SendNotification.java b/src/share/classes/javax/management/SendNotification.java deleted file mode 100644 index 497b51e60..000000000 --- a/src/share/classes/javax/management/SendNotification.java +++ /dev/null @@ -1,38 +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 javax.management; - -/** - * Interface implemented by objects that can be asked to send a notification. - */ -public interface SendNotification { - /** - * Sends a notification. - * - * @param notification The notification to send. - */ - public void sendNotification(Notification notification); -} diff --git a/src/share/classes/javax/management/StandardEmitterMBean.java b/src/share/classes/javax/management/StandardEmitterMBean.java index abce5b202..eb14f8d70 100644 --- a/src/share/classes/javax/management/StandardEmitterMBean.java +++ b/src/share/classes/javax/management/StandardEmitterMBean.java @@ -25,10 +25,6 @@ package javax.management; -import com.sun.jmx.mbeanserver.MBeanInjector; -import com.sun.jmx.mbeanserver.MBeanIntrospector; -import static javax.management.JMX.MBeanOptions; - /** *

    An MBean whose management interface is determined by reflection * on a Java interface, and that emits notifications.

    @@ -66,7 +62,7 @@ import static javax.management.JMX.MBeanOptions; * @since 1.6 */ public class StandardEmitterMBean extends StandardMBean - implements NotificationEmitter, SendNotification { + implements NotificationEmitter { private final NotificationEmitter emitter; private final MBeanNotificationInfo[] notificationInfo; @@ -80,10 +76,9 @@ public class StandardEmitterMBean extends StandardMBean * for {@code implementation} and {@code emitter} to be the same object.

    * *

    If {@code emitter} is an instance of {@code - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), - * then the MBean's {@link #sendNotification + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification * sendNotification} method will call {@code emitter.}{@link - * SendNotification#sendNotification sendNotification}.

    + * NotificationBroadcasterSupport#sendNotification sendNotification}.

    * *

    The array returned by {@link #getNotificationInfo()} on the * new MBean is a copy of the array returned by @@ -95,18 +90,20 @@ public class StandardEmitterMBean extends StandardMBean * * @param implementation the implementation of the MBean interface. * @param mbeanInterface a Standard MBean interface. - * @param emitter the object that will handle notifications. If null, - * a new {@code NotificationEmitter} will be constructed that also - * implements {@link SendNotification}. + * @param emitter the object that will handle notifications. * * @throws IllegalArgumentException if the {@code mbeanInterface} * does not follow JMX design patterns for Management Interfaces, or * if the given {@code implementation} does not implement the - * specified interface. + * specified interface, or if {@code emitter} is null. */ public StandardEmitterMBean(T implementation, Class mbeanInterface, NotificationEmitter emitter) { - this(implementation, mbeanInterface, false, emitter); + super(implementation, mbeanInterface, false); + if (emitter == null) + throw new IllegalArgumentException("Null emitter"); + this.emitter = emitter; + this.notificationInfo = emitter.getNotificationInfo(); } /** @@ -121,10 +118,9 @@ public class StandardEmitterMBean extends StandardMBean * same object.

    * *

    If {@code emitter} is an instance of {@code - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), - * then the MBean's {@link #sendNotification + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification * sendNotification} method will call {@code emitter.}{@link - * SendNotification#sendNotification sendNotification}.

    + * NotificationBroadcasterSupport#sendNotification sendNotification}.

    * *

    The array returned by {@link #getNotificationInfo()} on the * new MBean is a copy of the array returned by @@ -138,71 +134,21 @@ public class StandardEmitterMBean extends StandardMBean * @param mbeanInterface a Standard MBean interface. * @param isMXBean If true, the {@code mbeanInterface} parameter * names an MXBean interface and the resultant MBean is an MXBean. - * @param emitter the object that will handle notifications. If null, - * a new {@code NotificationEmitter} will be constructed that also - * implements {@link SendNotification}. + * @param emitter the object that will handle notifications. * * @throws IllegalArgumentException if the {@code mbeanInterface} * does not follow JMX design patterns for Management Interfaces, or * if the given {@code implementation} does not implement the - * specified interface. + * specified interface, or if {@code emitter} is null. */ public StandardEmitterMBean(T implementation, Class mbeanInterface, boolean isMXBean, NotificationEmitter emitter) { - this(implementation, mbeanInterface, - isMXBean ? MBeanOptions.MXBEAN : null, emitter); - } - - /** - *

    Make an MBean whose management interface is specified by {@code - * mbeanInterface}, with the given implementation and options, and where - * notifications are handled by the given {@code NotificationEmitter}. - * Options select whether to make a Standard MBean or an MXBean, and - * whether the result of {@link #getWrappedObject()} is the {@code - * StandardEmitterMBean} object or the given implementation. The resultant - * MBean implements the {@code NotificationEmitter} interface by forwarding - * its methods to {@code emitter}. It is legal and useful for {@code - * implementation} and {@code emitter} to be the same object.

    - * - *

    If {@code emitter} is an instance of {@code - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), - * then the MBean's {@link #sendNotification - * sendNotification} method will call {@code emitter.}{@link - * SendNotification#sendNotification sendNotification}.

    - * - *

    The array returned by {@link #getNotificationInfo()} on the - * new MBean is a copy of the array returned by - * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo - * getNotificationInfo()} at the time of construction. If the array - * returned by {@code emitter.getNotificationInfo()} later changes, - * that will have no effect on this object's - * {@code getNotificationInfo()}.

    - * - * @param implementation the implementation of the MBean interface. - * @param mbeanInterface a Standard MBean interface. - * @param options MBeanOptions that control the operation of the resulting - * MBean. - * @param emitter the object that will handle notifications. If null, - * a new {@code NotificationEmitter} will be constructed that also - * implements {@link SendNotification}. - * - * @throws IllegalArgumentException if the {@code mbeanInterface} - * does not follow JMX design patterns for Management Interfaces, or - * if the given {@code implementation} does not implement the - * specified interface. - */ - public StandardEmitterMBean(T implementation, Class mbeanInterface, - MBeanOptions options, - NotificationEmitter emitter) { - super(implementation, mbeanInterface, options); - MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(implementation); + super(implementation, mbeanInterface, isMXBean); if (emitter == null) - emitter = defaultEmitter(defaultMBNIs); + throw new IllegalArgumentException("Null emitter"); this.emitter = emitter; - this.notificationInfo = - firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs); - injectEmitter(); + this.notificationInfo = emitter.getNotificationInfo(); } /** @@ -213,10 +159,9 @@ public class StandardEmitterMBean extends StandardMBean * by forwarding its methods to {@code emitter}.

    * *

    If {@code emitter} is an instance of {@code - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), - * then the MBean's {@link #sendNotification + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification * sendNotification} method will call {@code emitter.}{@link - * SendNotification#sendNotification sendNotification}.

    + * NotificationBroadcasterSupport#sendNotification sendNotification}.

    * *

    The array returned by {@link #getNotificationInfo()} on the * new MBean is a copy of the array returned by @@ -230,17 +175,20 @@ public class StandardEmitterMBean extends StandardMBean * the given {@code mbeanInterface}.

    * * @param mbeanInterface a StandardMBean interface. - * @param emitter the object that will handle notifications. If null, - * a new {@code NotificationEmitter} will be constructed that also - * implements {@link SendNotification}. + * @param emitter the object that will handle notifications. * * @throws IllegalArgumentException if the {@code mbeanInterface} * does not follow JMX design patterns for Management Interfaces, or - * if {@code this} does not implement the specified interface. + * if {@code this} does not implement the specified interface, or + * if {@code emitter} is null. */ protected StandardEmitterMBean(Class mbeanInterface, NotificationEmitter emitter) { - this(mbeanInterface, false, emitter); + super(mbeanInterface, false); + if (emitter == null) + throw new IllegalArgumentException("Null emitter"); + this.emitter = emitter; + this.notificationInfo = emitter.getNotificationInfo(); } /** @@ -252,10 +200,9 @@ public class StandardEmitterMBean extends StandardMBean * forwarding its methods to {@code emitter}.

    * *

    If {@code emitter} is an instance of {@code - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), - * then the MBean's {@link #sendNotification + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification * sendNotification} method will call {@code emitter.}{@link - * SendNotification#sendNotification sendNotification}.

    + * NotificationBroadcasterSupport#sendNotification sendNotification}.

    * *

    The array returned by {@link #getNotificationInfo()} on the * new MBean is a copy of the array returned by @@ -271,102 +218,20 @@ public class StandardEmitterMBean extends StandardMBean * @param mbeanInterface a StandardMBean interface. * @param isMXBean If true, the {@code mbeanInterface} parameter * names an MXBean interface and the resultant MBean is an MXBean. - * @param emitter the object that will handle notifications. If null, - * a new {@code NotificationEmitter} will be constructed that also - * implements {@link SendNotification}. + * @param emitter the object that will handle notifications. * * @throws IllegalArgumentException if the {@code mbeanInterface} * does not follow JMX design patterns for Management Interfaces, or - * if {@code this} does not implement the specified interface. + * if {@code this} does not implement the specified interface, or + * if {@code emitter} is null. */ protected StandardEmitterMBean(Class mbeanInterface, boolean isMXBean, NotificationEmitter emitter) { - this(mbeanInterface, isMXBean ? MBeanOptions.MXBEAN : null, emitter); - } - - /** - *

    Make an MBean whose management interface is specified by {@code - * mbeanInterface}, with the given options, and where notifications are - * handled by the given {@code NotificationEmitter}. This constructor can - * be used to make either Standard MBeans or MXBeans. The resultant MBean - * implements the {@code NotificationEmitter} interface by forwarding its - * methods to {@code emitter}.

    - * - *

    If {@code emitter} is an instance of {@code - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), - * then the MBean's {@link #sendNotification - * sendNotification} method will call {@code emitter.}{@link - * SendNotification#sendNotification sendNotification}.

    - * - *

    The array returned by {@link #getNotificationInfo()} on the - * new MBean is a copy of the array returned by - * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo - * getNotificationInfo()} at the time of construction. If the array - * returned by {@code emitter.getNotificationInfo()} later changes, - * that will have no effect on this object's - * {@code getNotificationInfo()}.

    - * - *

    This constructor must be called from a subclass that implements - * the given {@code mbeanInterface}.

    - * - * @param mbeanInterface a StandardMBean interface. - * @param options MBeanOptions that control the operation of the resulting - * MBean. - * @param emitter the object that will handle notifications. If null, - * a new {@code NotificationEmitter} will be constructed that also - * implements {@link SendNotification}. - * - * @throws IllegalArgumentException if the {@code mbeanInterface} - * does not follow JMX design patterns for Management Interfaces, or - * if {@code this} does not implement the specified interface. - */ - protected StandardEmitterMBean(Class mbeanInterface, MBeanOptions options, - NotificationEmitter emitter) { - super(mbeanInterface, options); - MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(this); + super(mbeanInterface, isMXBean); if (emitter == null) - emitter = defaultEmitter(defaultMBNIs); + throw new IllegalArgumentException("Null emitter"); this.emitter = emitter; - this.notificationInfo = - firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs); - injectEmitter(); - } - - private static MBeanNotificationInfo[] defaultMBNIs(Object mbean) { - return MBeanIntrospector.findNotificationsFromAnnotations( - mbean.getClass()); - } - - private NotificationEmitter defaultEmitter(MBeanNotificationInfo[] defaultMBNIs) { - MBeanNotificationInfo[] mbnis = - firstNonEmpty(getNotificationInfo(), defaultMBNIs); - // Will be null unless getNotificationInfo() is overridden, - // since the notificationInfo field has not been set at this point. - if (mbnis == null) - mbnis = getMBeanInfo().getNotifications(); - return new NotificationBroadcasterSupport(mbnis); - } - - private static T[] firstNonEmpty(T[]... items) { - for (T[] t : items) { - if (t != null && t.length != 0) - return t; - } - return null; - } - - private void injectEmitter() { - if (emitter instanceof SendNotification) { - try { - Object resource = getImplementation(); - SendNotification send = (SendNotification) emitter; - MBeanInjector.injectSendNotification(resource, send); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } + this.notificationInfo = emitter.getNotificationInfo(); } public void removeNotificationListener(NotificationListener listener) @@ -394,10 +259,10 @@ public class StandardEmitterMBean extends StandardMBean /** *

    Sends a notification.

    * - *

    If the {@code emitter} parameter to the constructor was - * an instance of {@link SendNotification}, such as {@link - * NotificationBroadcasterSupport}, then this method will call {@code - * emitter.}{@link SendNotification#sendNotification + *

    If the {@code emitter} parameter to the constructor was an + * instance of {@code NotificationBroadcasterSupport} then this + * method will call {@code emitter.}{@link + * NotificationBroadcasterSupport#sendNotification * sendNotification}.

    * * @param n the notification to send. @@ -406,12 +271,13 @@ public class StandardEmitterMBean extends StandardMBean * constructor was not a {@code NotificationBroadcasterSupport}. */ public void sendNotification(Notification n) { - if (emitter instanceof SendNotification) - ((SendNotification) emitter).sendNotification(n); + if (emitter instanceof NotificationBroadcasterSupport) + ((NotificationBroadcasterSupport) emitter).sendNotification(n); else { final String msg = "Cannot sendNotification when emitter is not an " + - "instance of SendNotification: " + emitter.getClass().getName(); + "instance of NotificationBroadcasterSupport: " + + emitter.getClass().getName(); throw new ClassCastException(msg); } } diff --git a/src/share/classes/javax/management/StandardMBean.java b/src/share/classes/javax/management/StandardMBean.java index 0d015ec19..6fc9a9aff 100644 --- a/src/share/classes/javax/management/StandardMBean.java +++ b/src/share/classes/javax/management/StandardMBean.java @@ -25,27 +25,20 @@ package javax.management; +import static com.sun.jmx.defaults.JmxProperties.MISC_LOGGER; import com.sun.jmx.mbeanserver.DescriptorCache; import com.sun.jmx.mbeanserver.Introspector; -import com.sun.jmx.mbeanserver.MBeanInjector; -import com.sun.jmx.mbeanserver.MBeanInstantiator; -import com.sun.jmx.mbeanserver.MBeanIntrospector; import com.sun.jmx.mbeanserver.MBeanSupport; import com.sun.jmx.mbeanserver.MXBeanSupport; import com.sun.jmx.mbeanserver.StandardMBeanSupport; import com.sun.jmx.mbeanserver.Util; -import java.lang.reflect.Method; + import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.WeakHashMap; import java.util.logging.Level; -import javax.management.openmbean.MXBeanMappingFactory; import javax.management.openmbean.OpenMBeanAttributeInfo; import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanConstructorInfo; @@ -55,9 +48,6 @@ import javax.management.openmbean.OpenMBeanOperationInfoSupport; import javax.management.openmbean.OpenMBeanParameterInfo; import javax.management.openmbean.OpenMBeanParameterInfoSupport; -import static com.sun.jmx.defaults.JmxProperties.MISC_LOGGER; -import static javax.management.JMX.MBeanOptions; - /** *

    An MBean whose management interface is determined by reflection * on a Java interface.

    @@ -133,121 +123,7 @@ import static javax.management.JMX.MBeanOptions; * * @since 1.5 */ -public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { - - /** - *

    Options controlling the behavior of {@code StandardMBean} instances.

    - */ - public static class Options extends JMX.MBeanOptions { - private static final long serialVersionUID = 5107355471177517164L; - - private boolean wrappedVisible; - private boolean forwardRegistration; - - /** - *

    Construct an {@code Options} object where all options have - * their default values.

    - */ - public Options() {} - - @Override - public Options clone() { - return (Options) super.clone(); - } - - /** - *

    Defines whether the {@link StandardMBean#getWrappedObject() - * getWrappedObject} method returns the wrapped object.

    - * - *

    If this option is true, then {@code getWrappedObject()} will return - * the same object as {@link StandardMBean#getImplementation() - * getImplementation}. Otherwise, it will return the - * StandardMBean instance itself. The setting of this option - * affects the behavior of {@link MBeanServer#getClassLoaderFor - * MBeanServer.getClassLoaderFor} and {@link MBeanServer#isInstanceOf - * MBeanServer.isInstanceOf}. The default value is false for - * compatibility reasons, but true is a better value for most new code.

    - * - * @return true if this StandardMBean's {@link - * StandardMBean#getWrappedObject getWrappedObject} returns the wrapped - * object. - */ - public boolean isWrappedObjectVisible() { - return this.wrappedVisible; - } - - /** - *

    Set the {@link #isWrappedObjectVisible WrappedObjectVisible} option - * to the given value.

    - * @param visible the new value. - */ - public void setWrappedObjectVisible(boolean visible) { - this.wrappedVisible = visible; - } - - /** - *

    Defines whether the {@link MBeanRegistration MBeanRegistration} - * callbacks are forwarded to the wrapped object.

    - * - *

    If this option is true, then - * {@link #preRegister(MBeanServer, ObjectName) preRegister}, - * {@link #postRegister(Boolean) postRegister}, - * {@link #preDeregister preDeregister} and - * {@link #postDeregister postDeregister} methods are forwarded - * to the wrapped object, in addition to the behaviour specified - * for the StandardMBean instance itself. - * The default value is false for compatibility reasons, but true - * is a better value for most new code.

    - * - * @return true if the MBeanRegistration callbacks - * are forwarded to the wrapped object. - */ - public boolean isMBeanRegistrationForwarded() { - return this.forwardRegistration; - } - - /** - *

    Set the - * {@link #isMBeanRegistrationForwarded MBeanRegistrationForwarded} - * option to the given value.

    - * @param forward the new value. - */ - public void setMBeanRegistrationForwarded(boolean forward) { - this.forwardRegistration = forward; - } - - // Canonical objects for each of - // (MXBean,!MXBean) x (WVisible,!WVisible) x (Forward,!Forward) - private static final Options[] CANONICALS = { - new Options(), new Options(), new Options(), new Options(), - new Options(), new Options(), new Options(), new Options(), - }; - static { - CANONICALS[1].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - CANONICALS[2].setWrappedObjectVisible(true); - CANONICALS[3].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - CANONICALS[3].setWrappedObjectVisible(true); - CANONICALS[4].setMBeanRegistrationForwarded(true); - CANONICALS[5].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - CANONICALS[5].setMBeanRegistrationForwarded(true); - CANONICALS[6].setWrappedObjectVisible(true); - CANONICALS[6].setMBeanRegistrationForwarded(true); - CANONICALS[7].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - CANONICALS[7].setWrappedObjectVisible(true); - CANONICALS[7].setMBeanRegistrationForwarded(true); - } - @Override - MBeanOptions[] canonicals() { - return CANONICALS; - } - - @Override - boolean same(MBeanOptions opts) { - return (super.same(opts) && opts instanceof Options && - ((Options) opts).wrappedVisible == wrappedVisible && - ((Options) opts).forwardRegistration ==forwardRegistration); - } - } +public class StandardMBean implements DynamicMBean, MBeanRegistration { private final static DescriptorCache descriptors = DescriptorCache.getInstance(JMX.proof); @@ -262,11 +138,6 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { **/ private volatile MBeanInfo cachedMBeanInfo; - /** - * The MBeanOptions for this StandardMBean. - **/ - private MBeanOptions options; - /** * Make a DynamicMBean out of implementation, using the * specified mbeanInterface class. @@ -282,14 +153,12 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * implementation is allowed. If null implementation is allowed, * and a null implementation is passed, then the implementation * is assumed to be this. - * @param options MBeanOptions to apply to this instance. * @exception IllegalArgumentException if the given * implementation is null, and null is not allowed. **/ - @SuppressWarnings("unchecked") // cast to T private void construct(T implementation, Class mbeanInterface, boolean nullImplementationAllowed, - MBeanOptions options) + boolean isMXBean) throws NotCompliantMBeanException { if (implementation == null) { // Have to use (T)this rather than mbeanInterface.cast(this) @@ -298,23 +167,20 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { implementation = Util.cast(this); else throw new IllegalArgumentException("implementation is null"); } - if (options == null) - options = new MBeanOptions(); - MXBeanMappingFactory mappingFactory = options.getMXBeanMappingFactory(); - boolean mx = (mappingFactory != null); - if (mbeanInterface == null) { - mbeanInterface = Util.cast(Introspector.getStandardOrMXBeanInterface( - implementation.getClass(), mx)); - } - if (mx) { - this.mbean = - new MXBeanSupport(implementation, mbeanInterface, - mappingFactory); + if (isMXBean) { + if (mbeanInterface == null) { + mbeanInterface = Util.cast(Introspector.getMXBeanInterface( + implementation.getClass())); + } + this.mbean = new MXBeanSupport(implementation, mbeanInterface); } else { + if (mbeanInterface == null) { + mbeanInterface = Util.cast(Introspector.getStandardMBeanInterface( + implementation.getClass())); + } this.mbean = new StandardMBeanSupport(implementation, mbeanInterface); } - this.options = options.canonical(); } /** @@ -343,7 +209,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { **/ public StandardMBean(T implementation, Class mbeanInterface) throws NotCompliantMBeanException { - construct(implementation, mbeanInterface, false, null); + construct(implementation, mbeanInterface, false, false); } /** @@ -363,7 +229,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { **/ protected StandardMBean(Class mbeanInterface) throws NotCompliantMBeanException { - construct(null, mbeanInterface, true, null); + construct(null, mbeanInterface, true, false); } /** @@ -400,17 +266,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { public StandardMBean(T implementation, Class mbeanInterface, boolean isMXBean) { try { - MBeanOptions opts = new MBeanOptions(); - if (mbeanInterface == null) { - mbeanInterface = Util.cast(Introspector.getStandardOrMXBeanInterface( - implementation.getClass(), isMXBean)); - } - if (isMXBean) { - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface( - mbeanInterface); - opts.setMXBeanMappingFactory(f); - } - construct(implementation, mbeanInterface, false, opts); + construct(implementation, mbeanInterface, false, isMXBean); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } @@ -441,77 +297,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { **/ protected StandardMBean(Class mbeanInterface, boolean isMXBean) { try { - MBeanOptions opts = new MBeanOptions(); - if (mbeanInterface == null) { - mbeanInterface = Introspector.getStandardOrMXBeanInterface( - getClass(), isMXBean); - } - if (isMXBean) { - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface( - mbeanInterface); - opts.setMXBeanMappingFactory(f); - } - construct(null, mbeanInterface, true, opts); - } catch (NotCompliantMBeanException e) { - throw new IllegalArgumentException(e); - } - } - - /** - *

    Make a DynamicMBean out of the object - * implementation, using the specified - * mbeanInterface class and the specified options.

    - * - * @param implementation The implementation of this MBean. - * @param mbeanInterface The Management Interface exported by this - * MBean's implementation. If null, then this - * object will use standard JMX design pattern to determine - * the management interface associated with the given - * implementation. - * @param options MBeanOptions that control the operation of the resulting - * MBean. - * @param Allows the compiler to check - * that {@code implementation} does indeed implement the class - * described by {@code mbeanInterface}. The compiler can only - * check this if {@code mbeanInterface} is a class literal such - * as {@code MyMBean.class}. - * - * @exception IllegalArgumentException if the given - * implementation is null, or if the mbeanInterface - * does not follow JMX design patterns for Management Interfaces, or - * if the given implementation does not implement the - * specified interface. - **/ - public StandardMBean(T implementation, - Class mbeanInterface, - MBeanOptions options) { - try { - construct(implementation, mbeanInterface, false, options); - } catch (NotCompliantMBeanException e) { - throw new IllegalArgumentException(e); - } - } - - /** - *

    Make a DynamicMBean out of this, using the specified - * mbeanInterface class and the specified options.

    - * - *

    Calls {@link #StandardMBean(Object, Class, JMX.MBeanOptions) - * this(this,mbeanInterface,options)}. - * This constructor is reserved to subclasses.

    - * - * @param mbeanInterface The Management Interface exported by this - * MBean. - * @param options MBeanOptions that control the operation of the resulting - * MBean. - * - * @exception IllegalArgumentException if the mbeanInterface - * does not follow JMX design patterns for Management Interfaces, or - * if this does not implement the specified interface. - **/ - protected StandardMBean(Class mbeanInterface, MBeanOptions options) { - try { - construct(null, mbeanInterface, true, options); + construct(null, mbeanInterface, true, isMXBean); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } @@ -527,9 +313,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * * @exception IllegalArgumentException if the given * implementation is null. - * @exception IllegalStateException if the - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} - * option is true. + * * @exception NotCompliantMBeanException if the given * implementation does not implement the * Standard MBean (or MXBean) interface that was @@ -543,24 +327,12 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { if (implementation == null) throw new IllegalArgumentException("implementation is null"); - if(options instanceof Options && - ((Options) options).isMBeanRegistrationForwarded()) - throw new IllegalStateException("Implementation can't be changed " + - "because MBeanRegistrationForwarded option is true"); - - setImplementation2(implementation); - } - - private void setImplementation2(T implementation) - throws NotCompliantMBeanException { - Class intf = Util.cast(getMBeanInterface()); - - if (this.mbean.isMXBean()) { + if (isMXBean()) { this.mbean = new MXBeanSupport(implementation, - intf, - options.getMXBeanMappingFactory()); + Util.>cast(getMBeanInterface())); } else { - this.mbean = new StandardMBeanSupport(implementation, intf); + this.mbean = new StandardMBeanSupport(implementation, + Util.>cast(getMBeanInterface())); } } @@ -571,67 +343,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * @see #setImplementation **/ public Object getImplementation() { - return mbean.getWrappedObject(); - } - - /** - *

    Get the wrapped implementation object or return this object.

    - * - *

    For compatibility reasons, this method only returns the wrapped - * implementation object if the {@link Options#isWrappedObjectVisible - * WrappedObjectVisible} option was specified when this StandardMBean - * was created. Otherwise it returns {@code this}.

    - * - *

    If you want the MBeanServer's {@link MBeanServer#getClassLoaderFor - * getClassLoaderFor} and {@link MBeanServer#isInstanceOf - * isInstanceOf} methods to refer to the wrapped implementation and - * not this StandardMBean object, then you must set the - * {@code WrappedObjectVisible} option, for example using:

    - * - *
    -     * StandardMBean.Options opts = new StandardMBean.Options();
    -     * opts.setWrappedObjectVisible(true);
    -     * StandardMBean mbean = new StandardMBean(impl, MyMBean.class, opts);
    -     * 
    - * - * @return The wrapped implementation object, or this StandardMBean - * instance. - */ - public Object getWrappedObject() { - if (options instanceof Options && - ((Options) options).isWrappedObjectVisible()) - return getImplementation(); - else - return this; - } - - /** - *

    Get the ClassLoader of the wrapped implementation object or of this - * object.

    - * - *

    For compatibility reasons, this method only returns the ClassLoader - * of the wrapped implementation object if the {@link - * Options#isWrappedObjectVisible WrappedObjectVisible} option was - * specified when this StandardMBean was created. Otherwise it returns - * {@code this.getClass().getClassLoader()}.

    - * - *

    If you want the MBeanServer's {@link MBeanServer#getClassLoaderFor - * getClassLoaderFor} and {@link MBeanServer#isInstanceOf - * isInstanceOf} methods to refer to the wrapped implementation and - * not this StandardMBean object, then you must set the - * {@code WrappedObjectVisible} option, for example using:

    - * - *
    -     * StandardMBean.Options opts = new StandardMBean.Options();
    -     * opts.setWrappedObjectVisible(true);
    -     * StandardMBean mbean = new StandardMBean(impl, MyMBean.class, opts);
    -     * 
    - * - * @return The ClassLoader of the wrapped Cimplementation object, or of - * this StandardMBean instance. - */ - public ClassLoader getWrappedClassLoader() { - return getWrappedObject().getClass().getClassLoader(); + return mbean.getResource(); } /** @@ -647,20 +359,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * @return The class of the implementation of this Standard MBean (or MXBean). **/ public Class getImplementationClass() { - return mbean.getWrappedObject().getClass(); - } - - /** - * Return the MBeanOptions that were specified or implied for this StandardMBean - * instance. If an MBeanOptions object was supplied when this StandardMBean - * instance was constructed, and if that object has not been modified in the - * meantime, then the returned object will be equal to that object, although - * it might not be the same object. - * @return The MBeanOptions that were specified or implied for this StandardMBean - * instance. - */ - public MBeanOptions getOptions() { - return options.uncanonical(); + return mbean.getResource().getClass(); } // ------------------------------------------------------------------ @@ -749,7 +448,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { MBeanSupport msupport = mbean; final MBeanInfo bi = msupport.getMBeanInfo(); - final Object impl = msupport.getWrappedObject(); + final Object impl = msupport.getResource(); final boolean immutableInfo = immutableInfo(this.getClass()); @@ -1027,7 +726,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * @return the MBeanNotificationInfo[] for the new MBeanInfo. **/ MBeanNotificationInfo[] getNotifications(MBeanInfo info) { - return info.getNotifications(); + return null; } /** @@ -1116,6 +815,10 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { cachedMBeanInfo = info; } + private boolean isMXBean() { + return mbean.isMXBean(); + } + private static boolean identicalArrays(T[] a, T[] b) { if (a == b) return true; @@ -1323,145 +1026,6 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { return natts; } - // ------------------------------------------------------------------ - // Resolve from a type name to a Class. - // ------------------------------------------------------------------ - private static Class resolveClass(MBeanFeatureInfo info, String type, - Class mbeanItf) - throws ClassNotFoundException { - String t = (String) info.getDescriptor(). - getFieldValue(JMX.ORIGINAL_TYPE_FIELD); - if (t == null) { - t = type; - } - Class clazz = MBeanInstantiator.primitiveType(t); - if(clazz == null) - clazz = Class.forName(t, false, mbeanItf.getClassLoader()); - return clazz; - } - - // ------------------------------------------------------------------ - // Return the subset of valid Management methods - // ------------------------------------------------------------------ - private static Method getManagementMethod(final Class mbeanType, - String opName, Class... parameters) throws NoSuchMethodException, - SecurityException { - Method m = mbeanType.getMethod(opName, parameters); - if (mbeanType.isInterface()) { - return m; - } - final List methods = new ArrayList(); - try { - MBeanIntrospector.getAnnotatedMethods(mbeanType, methods); - }catch (SecurityException ex) { - throw ex; - }catch (NoSuchMethodException ex) { - throw ex; - }catch (Exception ex) { - NoSuchMethodException nsme = - new NoSuchMethodException(ex.toString()); - nsme.initCause(ex); - throw nsme; - } - - if(methods.contains(m)) return m; - - throw new NoSuchMethodException("Operation " + opName + - " not found in management interface " + mbeanType.getName()); - } - /** - * Retrieve the set of MBean attribute accessor Methods - * located in the mbeanInterface MBean interface that - * correspond to the attr MBeanAttributeInfo - * parameter. - * @param mbeanInterface the management interface. - * Can be a standard MBean or MXBean interface, or a Java class - * annotated with {@link MBean @MBean} or {@link MXBean @MXBean}. - * @param attr The attribute we want the accessors for. - * @return The set of accessors. - * @throws java.lang.NoSuchMethodException if no accessor exists - * for the given {@link MBeanAttributeInfo MBeanAttributeInfo}. - * @throws java.lang.IllegalArgumentException if at least one - * of the two parameters is null. - * @throws java.lang.ClassNotFoundException if the class named in the - * attribute type is not found. - * @throws java.lang.SecurityException if this exception is - * encountered while introspecting the MBean interface. - */ - public static Set findAttributeAccessors(Class mbeanInterface, - MBeanAttributeInfo attr) - throws NoSuchMethodException, - ClassNotFoundException { - if (mbeanInterface == null || attr == null) { - throw new IllegalArgumentException("mbeanInterface or attr " + - "parameter is null"); - } - String attributeName = attr.getName(); - Set methods = new HashSet(); - Class clazz = resolveClass(attr, attr.getType(), mbeanInterface); - if (attr.isReadable()) { - String radical = "get"; - if(attr.isIs()) radical = "is"; - Method getter = getManagementMethod(mbeanInterface, radical + - attributeName); - if (getter.getReturnType().equals(clazz)) { - methods.add(getter); - } else { - throw new NoSuchMethodException("Invalid getter return type, " + - "should be " + clazz + ", found " + - getter.getReturnType()); - } - } - if (attr.isWritable()) { - Method setter = getManagementMethod(mbeanInterface, "set" + - attributeName, - clazz); - if (setter.getReturnType().equals(Void.TYPE)) { - methods.add(setter); - } else { - throw new NoSuchMethodException("Invalid setter return type, " + - "should be void, found " + setter.getReturnType()); - } - } - return methods; - } - - /** - * Retrieve the MBean operation Method - * located in the mbeanInterface MBean interface that - * corresponds to the provided op - * MBeanOperationInfo parameter. - * @param mbeanInterface the management interface. - * Can be a standard MBean or MXBean interface, or a Java class - * annotated with {@link MBean @MBean} or {@link MXBean @MXBean}. - * @param op The operation we want the method for. - * @return the method corresponding to the provided MBeanOperationInfo. - * @throws java.lang.NoSuchMethodException if no method exists - * for the given {@link MBeanOperationInfo MBeanOperationInfo}. - * @throws java.lang.IllegalArgumentException if at least one - * of the two parameters is null. - * @throws java.lang.ClassNotFoundException if one of the - * classes named in the operation signature array is not found. - * @throws java.lang.SecurityException if this exception is - * encountered while introspecting the MBean interface. - */ - public static Method findOperationMethod(Class mbeanInterface, - MBeanOperationInfo op) - throws ClassNotFoundException, NoSuchMethodException { - if (mbeanInterface == null || op == null) { - throw new IllegalArgumentException("mbeanInterface or op " + - "parameter is null"); - } - List> classes = new ArrayList>(); - for (MBeanParameterInfo info : op.getSignature()) { - Class clazz = resolveClass(info, info.getType(), mbeanInterface); - classes.add(clazz); - } - Class[] signature = new Class[classes.size()]; - classes.toArray(signature); - return getManagementMethod(mbeanInterface, op.getName(), signature); - } - /** *

    Allows the MBean to perform any operations it needs before * being registered in the MBean server. If the name of the MBean @@ -1470,14 +1034,10 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * registered in the MBean server.

    * *

    The default implementation of this method returns the {@code name} - * parameter. If the - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} - * option is set to true, then this method is forwarded to the object - * returned by the {@link #getImplementation getImplementation()} method. - * The name returned by this call is then returned by this method. - * It does nothing else for Standard MBeans. For MXBeans, it records - * the {@code MBeanServer} and {@code ObjectName} parameters so they can - * be used to translate inter-MXBean references.

    + * parameter. It does nothing else for + * Standard MBeans. For MXBeans, it records the {@code MBeanServer} + * and {@code ObjectName} parameters so they can be used to translate + * inter-MXBean references.

    * *

    It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.preRegister(...)}. @@ -1512,13 +1072,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { - // Forward preRegister before to call register and - // inject parameters. - if(shouldForwardMBeanRegistration()) - name = ((MBeanRegistration)getImplementation()). - preRegister(server, name); mbean.register(server, name); - MBeanInjector.inject(mbean.getWrappedObject(), server, name); return name; } @@ -1526,11 +1080,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { *

    Allows the MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed.

    * - *

    If the - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} - * option is set to true, then this method is forwarded to the object - * returned by the {@link #getImplementation getImplementation()} method. - * The default implementation of this method does nothing else for + *

    The default implementation of this method does nothing for * Standard MBeans. For MXBeans, it undoes any work done by * {@link #preRegister preRegister} if registration fails.

    * @@ -1548,21 +1098,13 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { public void postRegister(Boolean registrationDone) { if (!registrationDone) mbean.unregister(); - if(shouldForwardMBeanRegistration()) - ((MBeanRegistration)getImplementation()). - postRegister(registrationDone); } /** *

    Allows the MBean to perform any operations it needs before * being unregistered by the MBean server.

    * - *

    If the - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} - * option is set to true, then this method is forwarded to the object - * returned by the {@link #getImplementation getImplementation()} method. - * Other than that, the default implementation of this method does nothing. - *

    + *

    The default implementation of this method does nothing.

    * *

    It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.preDeregister(...)}.

    @@ -1574,19 +1116,13 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * @since 1.6 */ public void preDeregister() throws Exception { - if(shouldForwardMBeanRegistration()) - ((MBeanRegistration)getImplementation()).preDeregister(); } /** *

    Allows the MBean to perform any operations needed after having been * unregistered in the MBean server.

    * - *

    If the - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} - * option is set to true, then this method is forwarded to the object - * returned by the {@link #getImplementation getImplementation()} method. - * The default implementation of this method does nothing else for + *

    The default implementation of this method does nothing for * Standard MBeans. For MXBeans, it removes any information that * was recorded by the {@link #preRegister preRegister} method.

    * @@ -1599,15 +1135,8 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { */ public void postDeregister() { mbean.unregister(); - if(shouldForwardMBeanRegistration()) - ((MBeanRegistration)getImplementation()).postDeregister(); } - private boolean shouldForwardMBeanRegistration() { - return (getImplementation() instanceof MBeanRegistration) && - (options instanceof Options && - ((Options) options).isMBeanRegistrationForwarded()); - } // // MBeanInfo immutability // diff --git a/src/share/classes/javax/management/event/EventClient.java b/src/share/classes/javax/management/event/EventClient.java deleted file mode 100644 index 2688b9493..000000000 --- a/src/share/classes/javax/management/event/EventClient.java +++ /dev/null @@ -1,1104 +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 javax.management.event; - -import com.sun.jmx.event.DaemonThreadFactory; -import com.sun.jmx.event.LeaseRenewer; -import com.sun.jmx.event.ReceiverBuffer; -import com.sun.jmx.event.RepeatedSingletonJob; -import com.sun.jmx.mbeanserver.PerThreadGroupPool; -import com.sun.jmx.remote.util.ClassLogger; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; - -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServerConnection; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - -/** - *

    This class is used to manage its notification listeners on the client - * side in the same way as on the MBean server side. This class needs to work - * with an {@link EventClientDelegateMBean} on the server side.

    - * - *

    A user can specify an {@link EventRelay} object to specify how to receive - * notifications forwarded by the {@link EventClientDelegateMBean}. By default, - * the class {@link FetchingEventRelay} is used.

    - * - *

    A user can specify an {@link java.util.concurrent.Executor Executor} - * to distribute notifications to local listeners. If no executor is - * specified, the thread in the {@link EventRelay} which calls {@link - * EventReceiver#receive EventReceiver.receive} will be reused to distribute - * the notifications (in other words, to call the {@link - * NotificationListener#handleNotification handleNotification} method of the - * appropriate listeners). It is useful to make a separate thread do this - * distribution in some cases. For example, if network communication is slow, - * the forwarding thread can concentrate on communication while, locally, - * the distributing thread distributes the received notifications. Another - * usage is to share a thread pool between many clients, for scalability. - * Note, though, that if the {@code Executor} can create more than one thread - * then it is possible that listeners will see notifications in a different - * order from the order in which they were sent.

    - * - *

    An object of this class sends notifications to listeners added with - * {@link #addEventClientListener}. The {@linkplain Notification#getType() - * type} of each such notification is one of {@link #FAILED}, {@link #NONFATAL}, - * or {@link #NOTIFS_LOST}.

    - * - * @since JMX 2.0 - */ -public class EventClient implements EventConsumer, NotificationManager { - - /** - *

    A notification string type used by an {@code EventClient} object - * to inform a listener added by {@link #addEventClientListener} that - * it failed to get notifications from a remote server, and that it is - * possible that no more notifications will be delivered.

    - * - * @see #addEventClientListener - * @see EventReceiver#failed - */ - public static final String FAILED = "jmx.event.service.failed"; - - /** - *

    Reports that an unexpected exception has been received by the {@link - * EventRelay} object but that it is non-fatal. For example, a notification - * received is not serializable or its class is not found.

    - * - * @see #addEventClientListener - * @see EventReceiver#nonFatal - */ - public static final String NONFATAL = "jmx.event.service.nonfatal"; - - /** - *

    A notification string type used by an {@code EventClient} object - * to inform a listener added by {@link #addEventClientListener - * addEventClientListener} that it has detected that notifications have - * been lost. The {@link Notification#getUserData() userData} of the - * notification is a Long which is an upper bound on the number of lost - * notifications that have just been detected.

    - * - * @see #addEventClientListener - */ - public static final String NOTIFS_LOST = "jmx.event.service.notifs.lost"; - - /** - * The default lease time that EventClient instances will request, in - * milliseconds. This value is {@value}. - * - * @see EventClientDelegateMBean#lease - */ - public static final long DEFAULT_REQUESTED_LEASE_TIME = 300000; - - /** - *

    Constructs a default {@code EventClient} object.

    - * - *

    This object creates a {@link FetchingEventRelay} object to - * receive notifications forwarded by the {@link EventClientDelegateMBean}. - * The {@link EventClientDelegateMBean} that it works with is the - * one registered with the {@linkplain EventClientDelegate#OBJECT_NAME - * default ObjectName}. The thread from the {@link FetchingEventRelay} - * object that fetches the notifications is also used to distribute them. - * - * @param conn An {@link MBeanServerConnection} object used to communicate - * with an {@link EventClientDelegateMBean} MBean. - * - * @throws IllegalArgumentException If {@code conn} is null. - * @throws IOException If an I/O error occurs when communicating with the - * {@code EventClientDelegateMBean}. - */ - public EventClient(MBeanServerConnection conn) throws IOException { - this(EventClientDelegate.getProxy(conn)); - } - - /** - * Constructs an {@code EventClient} object with a specified - * {@link EventClientDelegateMBean}. - * - *

    This object creates a {@link FetchingEventRelay} object to receive - * notifications forwarded by the {@link EventClientDelegateMBean}. The - * thread from the {@link FetchingEventRelay} object that fetches the - * notifications is also used to distribute them. - * - * @param delegate An {@link EventClientDelegateMBean} object to work with. - * - * @throws IllegalArgumentException If {@code delegate} is null. - * @throws IOException If an I/O error occurs when communicating with the - * the {@link EventClientDelegateMBean}. - */ - public EventClient(EventClientDelegateMBean delegate) - throws IOException { - this(delegate, null, null, null, DEFAULT_REQUESTED_LEASE_TIME); - } - - /** - * Constructs an {@code EventClient} object with the specified - * {@link EventClientDelegateMBean}, {@link EventRelay} - * object, and distributing thread. - * - * @param delegate An {@link EventClientDelegateMBean} object to work with. - * Usually, this will be a proxy constructed using - * {@link EventClientDelegate#getProxy}. - * @param eventRelay An object used to receive notifications - * forwarded by the {@link EventClientDelegateMBean}. If {@code null}, a - * {@link FetchingEventRelay} object will be used. - * @param distributingExecutor Used to distribute notifications to local - * listeners. Only one job at a time will be submitted to this Executor. - * If {@code distributingExecutor} is {@code null}, the thread that calls - * {@link EventReceiver#receive EventReceiver.receive} from the {@link - * EventRelay} object is used. - * @param leaseScheduler An object that will be used to schedule the - * periodic {@linkplain EventClientDelegateMBean#lease lease updates}. - * If {@code null}, a default scheduler will be used. - * @param requestedLeaseTime The lease time used to keep this client alive - * in the {@link EventClientDelegateMBean}. A value of zero is equivalent - * to the {@linkplain #DEFAULT_REQUESTED_LEASE_TIME default value}. - * - * @throws IllegalArgumentException If {@code delegate} is null. - * @throws IOException If an I/O error occurs when communicating with the - * {@link EventClientDelegateMBean}. - */ - public EventClient(EventClientDelegateMBean delegate, - EventRelay eventRelay, - Executor distributingExecutor, - ScheduledExecutorService leaseScheduler, - long requestedLeaseTime) - throws IOException { - if (delegate == null) { - throw new IllegalArgumentException("Null EventClientDelegateMBean"); - } - - if (requestedLeaseTime == 0) - requestedLeaseTime = DEFAULT_REQUESTED_LEASE_TIME; - else if (requestedLeaseTime < 0) { - throw new IllegalArgumentException( - "Negative lease time: " + requestedLeaseTime); - } - - eventClientDelegate = delegate; - - if (eventRelay != null) { - this.eventRelay = eventRelay; - } else { - try { - this.eventRelay = new FetchingEventRelay(delegate); - } catch (IOException ioe) { - throw ioe; - } catch (Exception e) { - // impossible? - final IOException ioee = new IOException(e.toString()); - ioee.initCause(e); - throw ioee; - } - } - - if (distributingExecutor == null) - distributingExecutor = callerExecutor; - this.distributingExecutor = distributingExecutor; - this.dispatchingJob = new DispatchingJob(); - - clientId = this.eventRelay.getClientId(); - - this.requestedLeaseTime = requestedLeaseTime; - if (leaseScheduler == null) - leaseScheduler = defaultLeaseScheduler(); - leaseRenewer = new LeaseRenewer(leaseScheduler, renewLease); - - if (logger.traceOn()) { - logger.trace("init", "New EventClient: "+clientId); - } - } - - private static ScheduledExecutorService defaultLeaseScheduler() { - // The default lease scheduler uses a ScheduledThreadPoolExecutor - // with a maximum of 20 threads. This means that if you have many - // EventClient instances and some of them get blocked (because of an - // unresponsive network, for example), then even the instances that - // are connected to responsive servers may have their leases expire. - // XXX check if the above is true and possibly fix. - PerThreadGroupPool.Create create = - new PerThreadGroupPool.Create() { - public ScheduledThreadPoolExecutor createThreadPool(ThreadGroup group) { - ThreadFactory daemonThreadFactory = new DaemonThreadFactory( - "JMX EventClient lease renewer %d"); - ScheduledThreadPoolExecutor executor = - new ScheduledThreadPoolExecutor(20, daemonThreadFactory); - executor.setKeepAliveTime(1, TimeUnit.SECONDS); - executor.allowCoreThreadTimeOut(true); - if (setRemoveOnCancelPolicy != null) { - try { - setRemoveOnCancelPolicy.invoke(executor, true); - } catch (Exception e) { - logger.trace("setRemoveOnCancelPolicy", e); - } - } - // By default, a ScheduledThreadPoolExecutor will keep jobs - // in its queue even after they have been cancelled. They - // will only be removed when their scheduled time arrives. - // Since the job references the LeaseRenewer which references - // this EventClient, this can lead to a moderately large number - // of objects remaining referenced until the renewal time - // arrives. Hence the above call, which removes the job from - // the queue as soon as it is cancelled. Since the call is - // new with JDK 7, we invoke it via reflection to make it - // easier to use this code on JDK 6. - return executor; - } - }; - return leaseRenewerThreadPool.getThreadPoolExecutor(create); - } - - private static final Method setRemoveOnCancelPolicy; - static { - Method m; - try { - m = ScheduledThreadPoolExecutor.class.getMethod( - "setRemoveOnCancelPolicy", boolean.class); - } catch (Exception e) { - m = null; - } - setRemoveOnCancelPolicy = m; - } - - /** - *

    Closes this EventClient, removes all listeners and stops receiving - * notifications.

    - * - *

    This method calls {@link - * EventClientDelegateMBean#removeClient(String)} and {@link - * EventRelay#stop}. Both operations occur even if one of them - * throws an {@code IOException}. - * - * @throws IOException if an I/O error occurs when communicating with - * {@link EventClientDelegateMBean}, or if {@link EventRelay#stop} - * throws an {@code IOException}. - */ - public void close() throws IOException { - if (logger.traceOn()) { - logger.trace("close", clientId); - } - - synchronized(listenerInfoMap) { - if (closed) { - return; - } - - closed = true; - listenerInfoMap.clear(); - } - - if (leaseRenewer != null) - leaseRenewer.close(); - - IOException ioe = null; - try { - eventRelay.stop(); - } catch (IOException e) { - ioe = e; - logger.debug("close", "EventRelay.stop", e); - } - - try { - eventClientDelegate.removeClient(clientId); - } catch (Exception e) { - if (e instanceof IOException) - ioe = (IOException) e; - else - ioe = new IOException(e); - logger.debug("close", - "Got exception when removing "+clientId, e); - } - - if (ioe != null) - throw ioe; - } - - /** - *

    Determine if this {@code EventClient} is closed.

    - * - * @return True if the {@code EventClient} is closed. - */ - public boolean closed() { - return closed; - } - - /** - *

    Return the {@link EventRelay} associated with this - * {@code EventClient}.

    - * - * @return The {@link EventRelay} object used. - */ - public EventRelay getEventRelay() { - return eventRelay; - } - - /** - *

    Return the lease time that this {@code EventClient} requests - * on every lease renewal.

    - * - * @return The requested lease time. - * - * @see EventClientDelegateMBean#lease - */ - public long getRequestedLeaseTime() { - return requestedLeaseTime; - } - - /** - * @see javax.management.MBeanServerConnection#addNotificationListener( - * ObjectName, NotificationListener, NotificationFilter, Object). - */ - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, IOException { - if (logger.traceOn()) { - logger.trace("addNotificationListener", ""); - } - - checkState(); - - Integer listenerId; - try { - listenerId = - eventClientDelegate.addListener(clientId, name, filter); - } catch (EventClientNotFoundException ecnfe) { - final IOException ioe = new IOException(ecnfe.getMessage()); - ioe.initCause(ecnfe); - throw ioe; - } - - synchronized(listenerInfoMap) { - listenerInfoMap.put(listenerId, new ListenerInfo( - name, - listener, - filter, - handback, - false)); - } - - startListening(); - } - - /** - * @see javax.management.MBeanServerConnection#removeNotificationListener( - * ObjectName, NotificationListener). - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, - ListenerNotFoundException, - IOException { - if (logger.traceOn()) { - logger.trace("removeNotificationListener", ""); - } - checkState(); - - for (Integer id : getListenerInfo(name, listener, false)) { - removeListener(id); - } - } - - /** - * @see javax.management.MBeanServerConnection#removeNotificationListener( - * ObjectName, NotificationListener, NotificationFilter, Object). - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - ListenerNotFoundException, - IOException { - if (logger.traceOn()) { - logger.trace("removeNotificationListener", "with all arguments."); - } - checkState(); - final Integer listenerId = - getListenerInfo(name, listener, filter, handback, false); - - removeListener(listenerId); - } - - /** - * @see javax.management.event.EventConsumer#unsubscribe( - * ObjectName, NotificationListener). - */ - public void unsubscribe(ObjectName name, - NotificationListener listener) - throws ListenerNotFoundException, IOException { - if (logger.traceOn()) { - logger.trace("unsubscribe", ""); - } - checkState(); - final Integer listenerId = - getMatchedListenerInfo(name, listener, true); - - synchronized(listenerInfoMap) { - if (listenerInfoMap.remove(listenerId) == null) { - throw new ListenerNotFoundException(); - } - } - - stopListening(); - - try { - eventClientDelegate.removeListenerOrSubscriber(clientId, listenerId); - } catch (InstanceNotFoundException e) { - logger.trace("unsubscribe", "removeSubscriber", e); - } catch (EventClientNotFoundException cnfe) { - logger.trace("unsubscribe", "removeSubscriber", cnfe); - } - } - - /** - * @see javax.management.event.EventConsumer#subscribe( - * ObjectName, NotificationListener, NotificationFilter, Object). - */ - public void subscribe(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) throws IOException { - if (logger.traceOn()) { - logger.trace("subscribe", ""); - } - - checkState(); - - Integer listenerId; - try { - listenerId = - eventClientDelegate.addSubscriber(clientId, name, filter); - } catch (EventClientNotFoundException ecnfe) { - final IOException ioe = new IOException(ecnfe.getMessage()); - ioe.initCause(ecnfe); - throw ioe; - } - - synchronized(listenerInfoMap) { - listenerInfoMap.put(listenerId, new ListenerInfo( - name, - listener, - filter, - handback, - true)); - } - - startListening(); - } - - /** - *

    Adds a set of listeners to the remote MBeanServer. This method can - * be used to copy the listeners from one {@code EventClient} to another.

    - * - *

    A listener is represented by a {@link ListenerInfo} object. The listener - * is added by calling {@link #subscribe(ObjectName, - * NotificationListener, NotificationFilter, Object)} if the method - * {@link ListenerInfo#isSubscription() isSubscription} - * returns {@code true}; otherwise it is added by calling - * {@link #addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object)}.

    - * - *

    The method returns the listeners which were added successfully. The - * elements in the returned collection are a subset of the elements in - * {@code listeners}. If all listeners were added successfully, the two - * collections are the same. If no listener was added successfully, the - * returned collection is empty.

    - * - * @param listeners the listeners to add. - * - * @return The listeners that were added successfully. - * - * @throws IOException If an I/O error occurs. - * - * @see #getListeners() - */ - public Collection addListeners(Collection listeners) - throws IOException { - if (logger.traceOn()) { - logger.trace("addListeners", ""); - } - - checkState(); - - if (listeners == null || listeners.isEmpty()) - return Collections.emptySet(); - - final List list = new ArrayList(); - for (ListenerInfo l : listeners) { - try { - if (l.isSubscription()) { - subscribe(l.getObjectName(), - l.getListener(), - l.getFilter(), - l.getHandback()); - } else { - addNotificationListener(l.getObjectName(), - l.getListener(), - l.getFilter(), - l.getHandback()); - } - - list.add(l); - } catch (Exception e) { - if (logger.traceOn()) { - logger.trace("addListeners", "failed to add: "+l, e); - } - } - } - - return list; - } - - /** - *

    Returns the collection of listeners that have been added through - * this {@code EventClient} and not subsequently removed. The returned - * collection contains one entry for every listener added with - * {@link #addNotificationListener addNotificationListener} or - * {@link #subscribe subscribe} and not subsequently removed with - * {@link #removeNotificationListener removeNotificationListener} or - * {@link #unsubscribe unsubscribe}, respectively.

    - * - * @return A collection of listener information. Empty if there are no - * current listeners or if this {@code EventClient} has been {@linkplain - * #close closed}. - * - * @see #addListeners - */ - public Collection getListeners() { - if (logger.traceOn()) { - logger.trace("getListeners", ""); - } - - synchronized(listenerInfoMap) { - return Collections.unmodifiableCollection(listenerInfoMap.values()); - } - } - - /** - * Adds a listener to receive the {@code EventClient} notifications specified in - * {@link #getEventClientNotificationInfo}. - * - * @param listener A listener to receive {@code EventClient} notifications. - * @param filter A filter to select which notifications are to be delivered - * to the listener, or {@code null} if all notifications are to be delivered. - * @param handback An object to be given to the listener along with each - * notification. Can be null. - * @throws NullPointerException If listener is null. - * @see #removeEventClientListener - */ - public void addEventClientListener(NotificationListener listener, - NotificationFilter filter, - Object handback) { - if (logger.traceOn()) { - logger.trace("addEventClientListener", ""); - } - broadcaster.addNotificationListener(listener, filter, handback); - } - - /** - * Removes a listener added to receive {@code EventClient} notifications specified in - * {@link #getEventClientNotificationInfo}. - * - * @param listener A listener to receive {@code EventClient} notifications. - * @throws NullPointerException If listener is null. - * @throws ListenerNotFoundException If the listener is not added to - * this {@code EventClient}. - */ - public void removeEventClientListener(NotificationListener listener) - throws ListenerNotFoundException { - if (logger.traceOn()) { - logger.trace("removeEventClientListener", ""); - } - broadcaster.removeNotificationListener(listener); - } - - /** - *

    Get the types of notification that an {@code EventClient} can send - * to listeners added with {@link #addEventClientListener - * addEventClientListener}.

    - * - * @return Types of notification emitted by this {@code EventClient}. - * - * @see #FAILED - * @see #NONFATAL - * @see #NOTIFS_LOST - */ - public MBeanNotificationInfo[] getEventClientNotificationInfo() { - return myInfo.clone(); - } - - private static boolean match(ListenerInfo li, - ObjectName name, - NotificationListener listener, - boolean subscribed) { - return li.getObjectName().equals(name) && - li.getListener() == listener && - li.isSubscription() == subscribed; - } - - private static boolean match(ListenerInfo li, - ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback, - boolean subscribed) { - return li.getObjectName().equals(name) && - li.getFilter() == filter && - li.getListener() == listener && - li.getHandback() == handback && - li.isSubscription() == subscribed; - } - -// --------------------------------------------------- -// private classes -// --------------------------------------------------- - private class DispatchingJob extends RepeatedSingletonJob { - public DispatchingJob() { - super(distributingExecutor); - } - - public boolean isSuspended() { - return closed || buffer.size() == 0; - } - - public void task() { - TargetedNotification[] tns ; - int lost = 0; - - synchronized(buffer) { - tns = buffer.removeNotifs(); - lost = buffer.removeLost(); - } - - if ((tns == null || tns.length == 0) - && lost == 0) { - return; - } - - // forwarding - if (tns != null && tns.length > 0) { - if (logger.traceOn()) { - logger.trace("DispatchingJob-task", - "Forwarding: "+tns.length); - } - for (TargetedNotification tn : tns) { - final ListenerInfo li = listenerInfoMap.get(tn.getListenerID()); - try { - li.getListener().handleNotification(tn.getNotification(), - li.getHandback()); - } catch (Exception e) { - logger.fine( - "DispatchingJob.task", "listener got exception", e); - } - } - } - - if (lost > 0) { - if (logger.traceOn()) { - logger.trace("DispatchingJob-task", - "lost: "+lost); - } - final Notification n = new Notification(NOTIFS_LOST, - EventClient.this, - myNotifCounter.getAndIncrement(), - System.currentTimeMillis(), - "Lost notifications."); - n.setUserData(new Long(lost)); - broadcaster.sendNotification(n); - } - } - } - - - private class EventReceiverImpl implements EventReceiver { - public void receive(NotificationResult nr) { - if (logger.traceOn()) { - logger.trace("MyEventReceiver-receive", ""); - } - - synchronized(buffer) { - buffer.addNotifs(nr); - - dispatchingJob.resume(); - } - } - - public void failed(Throwable t) { - if (logger.traceOn()) { - logger.trace("MyEventReceiver-failed", "", t); - } - final Notification n = new Notification(FAILED, - this, - myNotifCounter.getAndIncrement(), - System.currentTimeMillis()); - n.setSource(t); - broadcaster.sendNotification(n); - } - - public void nonFatal(Exception e) { - if (logger.traceOn()) { - logger.trace("MyEventReceiver-nonFatal", "", e); - } - - final Notification n = new Notification(NONFATAL, - this, - myNotifCounter.getAndIncrement(), - System.currentTimeMillis()); - n.setSource(e); - broadcaster.sendNotification(n); - } - } - -// ---------------------------------------------------- -// private class -// ---------------------------------------------------- - - -// ---------------------------------------------------- -// private methods -// ---------------------------------------------------- - private Integer getListenerInfo(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback, - boolean subscribed) throws ListenerNotFoundException { - - synchronized(listenerInfoMap) { - for (Map.Entry entry : - listenerInfoMap.entrySet()) { - ListenerInfo li = entry.getValue(); - if (match(li, name, listener, filter, handback, subscribed)) { - return entry.getKey(); - } - } - } - - throw new ListenerNotFoundException(); - } - - private Integer getMatchedListenerInfo(ObjectName name, - NotificationListener listener, - boolean subscribed) throws ListenerNotFoundException { - - synchronized(listenerInfoMap) { - for (Map.Entry entry : - listenerInfoMap.entrySet()) { - ListenerInfo li = entry.getValue(); - if (li.getObjectName().equals(name) && - li.getListener() == listener && - li.isSubscription() == subscribed) { - return entry.getKey(); - } - } - } - - throw new ListenerNotFoundException(); - } - - private Collection getListenerInfo(ObjectName name, - NotificationListener listener, - boolean subscribed) throws ListenerNotFoundException { - - final ArrayList ids = new ArrayList(); - synchronized(listenerInfoMap) { - for (Map.Entry entry : - listenerInfoMap.entrySet()) { - ListenerInfo li = entry.getValue(); - if (match(li, name, listener, subscribed)) { - ids.add(entry.getKey()); - } - } - } - - if (ids.isEmpty()) { - throw new ListenerNotFoundException(); - } - - return ids; - } - - private void checkState() throws IOException { - synchronized(listenerInfoMap) { - if (closed) { - throw new IOException("Ended!"); - } - } - } - - private void startListening() throws IOException { - synchronized(listenerInfoMap) { - if (!startedListening && listenerInfoMap.size() > 0) { - eventRelay.setEventReceiver(myReceiver); - } - - startedListening = true; - - if (logger.traceOn()) { - logger.trace("startListening", "listening"); - } - } - } - - private void stopListening() throws IOException { - synchronized(listenerInfoMap) { - if (listenerInfoMap.size() == 0 && startedListening) { - eventRelay.setEventReceiver(null); - - startedListening = false; - - if (logger.traceOn()) { - logger.trace("stopListening", "non listening"); - } - } - } - } - - private void removeListener(Integer id) - throws InstanceNotFoundException, - ListenerNotFoundException, - IOException { - synchronized(listenerInfoMap) { - if (listenerInfoMap.remove(id) == null) { - throw new ListenerNotFoundException(); - } - - stopListening(); - } - - try { - eventClientDelegate.removeListenerOrSubscriber(clientId, id); - } catch (EventClientNotFoundException cnfe) { - logger.trace("removeListener", "ecd.removeListener", cnfe); - } - } - - -// ---------------------------------------------------- -// private variables -// ---------------------------------------------------- - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventClient"); - - private final Executor distributingExecutor; - private final EventClientDelegateMBean eventClientDelegate; - private final EventRelay eventRelay; - private volatile String clientId = null; - private final long requestedLeaseTime; - - private final ReceiverBuffer buffer = new ReceiverBuffer(); - - private final EventReceiverImpl myReceiver = - new EventReceiverImpl(); - private final DispatchingJob dispatchingJob; - - private final HashMap listenerInfoMap = - new HashMap(); - - private volatile boolean closed = false; - - private volatile boolean startedListening = false; - - // Could change synchronization here. But at worst a race will mean - // sequence numbers are not contiguous, which may not matter much. - private final AtomicLong myNotifCounter = new AtomicLong(); - - private final static MBeanNotificationInfo[] myInfo = - new MBeanNotificationInfo[] { - new MBeanNotificationInfo( - new String[] {FAILED, NONFATAL, NOTIFS_LOST}, - Notification.class.getName(), - "Notifications that can be sent to a listener added with " + - "EventClient.addEventClientListener")}; - - private final NotificationBroadcasterSupport broadcaster = - new NotificationBroadcasterSupport(); - - private final static Executor callerExecutor = new Executor() { - // DirectExecutor using caller thread - public void execute(Runnable r) { - r.run(); - } - }; - - private static void checkInit(final MBeanServerConnection conn, - final ObjectName delegateName) - throws IOException { - if (conn == null) { - throw new IllegalArgumentException("No connection specified"); - } - if (delegateName != null && - (!conn.isRegistered(delegateName))) { - throw new IllegalArgumentException( - delegateName + - ": not found"); - } - if (delegateName == null && - (!conn.isRegistered( - EventClientDelegate.OBJECT_NAME))) { - throw new IllegalArgumentException( - EventClientDelegate.OBJECT_NAME + - ": not found"); - } - } - -// ---------------------------------------------------- -// private event lease issues -// ---------------------------------------------------- - private Callable renewLease = new Callable() { - public Long call() throws IOException, EventClientNotFoundException { - return eventClientDelegate.lease(clientId, requestedLeaseTime); - } - }; - - private final LeaseRenewer leaseRenewer; - -// ------------------------------------------------------------------------ - /** - * Constructs an {@code MBeanServerConnection} that uses an {@code EventClient} object, - * if the underlying connection has an {@link EventClientDelegateMBean}. - *

    The {@code EventClient} object creates a default - * {@link FetchingEventRelay} object to - * receive notifications forwarded by the {@link EventClientDelegateMBean}. - * The {@link EventClientDelegateMBean} it works with is the - * default one registered with the ObjectName - * {@link EventClientDelegate#OBJECT_NAME - * OBJECT_NAME}. - * The thread from the {@link FetchingEventRelay} object that fetches the - * notifications is also used to distribute them. - * - * @param conn An {@link MBeanServerConnection} object used to communicate - * with an {@link EventClientDelegateMBean}. - * @throws IllegalArgumentException If the value of {@code conn} is null, - * or the default {@link EventClientDelegateMBean} is not registered. - * @throws IOException If an I/O error occurs. - */ - public static MBeanServerConnection getEventClientConnection( - final MBeanServerConnection conn) - throws IOException { - return getEventClientConnection(conn, null); - } - - /** - * Constructs an MBeanServerConnection that uses an {@code EventClient} - * object with a user-specific {@link EventRelay} - * object. - *

    - * The {@link EventClientDelegateMBean} which it works with is the - * default one registered with the ObjectName - * {@link EventClientDelegate#OBJECT_NAME - * OBJECT_NAME} - * The thread that calls {@link EventReceiver#receive - * EventReceiver.receive} from the {@link EventRelay} object is used - * to distribute notifications to their listeners. - * - * @param conn An {@link MBeanServerConnection} object used to communicate - * with an {@link EventClientDelegateMBean}. - * @param eventRelay A user-specific object used to receive notifications - * forwarded by the {@link EventClientDelegateMBean}. If null, the default - * {@link FetchingEventRelay} object is used. - * @throws IllegalArgumentException If the value of {@code conn} is null, - * or the default {@link EventClientDelegateMBean} is not registered. - * @throws IOException If an I/O error occurs. - */ - public static MBeanServerConnection getEventClientConnection( - final MBeanServerConnection conn, - final EventRelay eventRelay) - throws IOException { - - if (newEventConn == null) { - throw new IllegalArgumentException( - "Class not found: EventClientConnection"); - } - - checkInit(conn,null); - final Callable factory = new Callable() { - final public EventClient call() throws Exception { - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(conn); - return new EventClient(ecd, eventRelay, null, null, - DEFAULT_REQUESTED_LEASE_TIME); - } - }; - - try { - return (MBeanServerConnection)newEventConn.invoke(null, - conn, factory); - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - - private static Method newEventConn = null; - static { - try { - Class c = Class.forName( - "com.sun.jmx.remote.util.EventClientConnection", - false, Thread.currentThread().getContextClassLoader()); - newEventConn = c.getMethod("getEventConnectionFor", - MBeanServerConnection.class, Callable.class); - } catch (Exception e) { - // OK: we're running in a subset of our classes - } - } - - /** - *

    Get the client id of this {@code EventClient} in the - * {@link EventClientDelegateMBean}. - * - * @return the client id. - * - * @see EventClientDelegateMBean#addClient(String, Object[], String[]) - * EventClientDelegateMBean.addClient - */ - public String getClientId() { - return clientId; - } - - private static final PerThreadGroupPool - leaseRenewerThreadPool = PerThreadGroupPool.make(); -} diff --git a/src/share/classes/javax/management/event/EventClientDelegate.java b/src/share/classes/javax/management/event/EventClientDelegate.java deleted file mode 100644 index 8eeeeb1f5..000000000 --- a/src/share/classes/javax/management/event/EventClientDelegate.java +++ /dev/null @@ -1,824 +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. - * - * @since JMX 2.0 - */ - -package javax.management.event; - -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; - -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.remote.NotificationResult; -import com.sun.jmx.event.EventBuffer; -import com.sun.jmx.event.LeaseManager; -import com.sun.jmx.interceptor.SingleMBeanForwarder; -import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.remote.util.ClassLogger; -import java.lang.ref.WeakReference; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.security.PrivilegedExceptionAction; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import javax.management.DynamicMBean; -import javax.management.MBeanException; -import javax.management.MBeanPermission; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerInvocationHandler; -import javax.management.MBeanServerNotification; -import javax.management.ObjectInstance; -import javax.management.StandardMBean; -import javax.management.remote.MBeanServerForwarder; - -/** - * This is the default implementation of the MBean - * {@link EventClientDelegateMBean}. - */ -public class EventClientDelegate implements EventClientDelegateMBean { - - private EventClientDelegate(MBeanServer server) { - if (server == null) { - throw new NullPointerException("Null MBeanServer."); - } - - if (logger.traceOn()) { - logger.trace("EventClientDelegate", "new one"); - } - mbeanServer = server; - eventSubscriber = EventSubscriber.getEventSubscriber(mbeanServer); - } - - /** - * Returns an {@code EventClientDelegate} instance for the given - * {@code MBeanServer}. Calling this method more than once with the same - * {@code server} argument may return the same object or a different object - * each time. See {@link EventClientDelegateMBean} for an example use of - * this method. - * - * @param server An MBean server instance to work with. - * @return An {@code EventClientDelegate} instance. - * @throws NullPointerException If {@code server} is null. - */ - public static EventClientDelegate getEventClientDelegate(MBeanServer server) { - EventClientDelegate delegate = null; - synchronized(delegateMap) { - final WeakReference wrf = delegateMap.get(server); - delegate = (wrf == null) ? null : wrf.get(); - - if (delegate == null) { - delegate = new EventClientDelegate(server); - try { - // TODO: this may not work with federated MBean, because - // the delegate will *not* emit notifications for those MBeans. - delegate.mbeanServer.addNotificationListener( - MBeanServerDelegate.DELEGATE_NAME, - delegate.cleanListener, null, null); - } catch (InstanceNotFoundException e) { - logger.fine( - "getEventClientDelegate", - "Could not add MBeanServerDelegate listener", e); - } - delegateMap.put(server, - new WeakReference(delegate)); - } - } - - return delegate; - } - - // Logic for the MBeanServerForwarder that simulates the existence of the - // EventClientDelegate MBean. Things are complicated by the fact that - // there may not be anything in the chain after this forwarder when it is - // created - the connection to a real MBeanServer might only come later. - // Recall that there are two ways of creating a JMXConnectorServer - - // either you specify its MBeanServer when you create it, or you specify - // no MBeanServer and register it in an MBeanServer later. In the latter - // case, the forwarder chain points nowhere until this registration - // happens. Since EventClientDelegate wants to add a listener to the - // MBeanServerDelegate, we can't create an EventClientDelegate until - // there is an MBeanServer. So the forwarder initially has - // a dummy ECD where every method throws an exception, and - // the real ECD is created as soon as doing so does not produce an - // exception. - // TODO: rewrite so that the switch from the dummy to the real ECD happens - // just before we would otherwise have thrown UnsupportedOperationException. - // This is more correct, because it's not guaranteed that we will see the - // moment where the real MBeanServer is attached, if it happens by virtue - // of a setMBeanServer on some other forwarder later in the chain. - - private static class Forwarder extends SingleMBeanForwarder { - private MBeanServer loopMBS; - - private static class UnsupportedInvocationHandler - implements InvocationHandler { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - throw new UnsupportedOperationException( - "EventClientDelegate unavailable: no MBeanServer, or " + - "MBeanServer inaccessible"); - } - } - - private static DynamicMBean makeUnsupportedECD() { - EventClientDelegateMBean unsupported = (EventClientDelegateMBean) - Proxy.newProxyInstance( - EventClientDelegateMBean.class.getClassLoader(), - new Class[] {EventClientDelegateMBean.class}, - new UnsupportedInvocationHandler()); - return new StandardMBean( - unsupported, EventClientDelegateMBean.class, false); - } - - private volatile boolean madeECD; - - Forwarder() { - super(OBJECT_NAME, makeUnsupportedECD(), true); - } - - synchronized void setLoopMBS(MBeanServer loopMBS) { - this.loopMBS = loopMBS; - } - - @Override - public synchronized void setMBeanServer(final MBeanServer mbs) { - super.setMBeanServer(mbs); - - if (!madeECD) { - try { - EventClientDelegate ecd = - AccessController.doPrivileged( - new PrivilegedAction() { - public EventClientDelegate run() { - return getEventClientDelegate(loopMBS); - } - }); - DynamicMBean mbean = new StandardMBean( - ecd, EventClientDelegateMBean.class, false); - setSingleMBean(mbean); - madeECD = true; - } catch (Exception e) { - // OK: assume no MBeanServer - logger.fine("setMBeanServer", "isRegistered", e); - } - } - } - } - - /** - *

    Create a new {@link MBeanServerForwarder} that simulates the existence - * of an {@code EventClientDelegateMBean} with the {@linkplain - * #OBJECT_NAME default name}. This forwarder intercepts MBean requests - * that are targeted for that MBean and handles them itself. All other - * requests are forwarded to the next element in the forwarder chain.

    - * - * @param nextMBS the next {@code MBeanServer} in the chain of forwarders, - * which might be another {@code MBeanServerForwarder} or a plain {@code - * MBeanServer}. This is the object to which {@code MBeanServer} requests - * that do not concern the {@code EventClientDelegateMBean} are sent. - * It will be the value of {@link MBeanServerForwarder#getMBeanServer() - * getMBeanServer()} on the returned object, and can be changed with {@link - * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but - * must be set to a non-null value before any {@code MBeanServer} requests - * arrive. - * - * @param loopMBS the {@code MBeanServer} to which requests from the - * {@code EventClientDelegateMBean} should be sent. For example, - * when you invoke the {@link EventClientDelegateMBean#addListener - * addListener} operation on the {@code EventClientDelegateMBean}, it will - * result in a call to {@link - * MBeanServer#addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) addNotificationListener} on this object. - * If this parameter is null, then these requests will be sent to the - * newly-created {@code MBeanServerForwarder}. Usually the parameter will - * either be null or will be the result of {@link - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder() - * getSystemMBeanServerForwarder()} for the connector server in which - * this forwarder will be installed. - * - * @return a new {@code MBeanServerForwarder} that simulates the existence - * of an {@code EventClientDelegateMBean}. - * - * @see javax.management.remote.JMXConnectorServer#installStandardForwarders - */ - public static MBeanServerForwarder newForwarder( - MBeanServer nextMBS, MBeanServer loopMBS) { - Forwarder mbsf = new Forwarder(); - // We must setLoopMBS before setMBeanServer, because when we - // setMBeanServer that will call getEventClientDelegate(loopMBS). - if (loopMBS == null) - loopMBS = mbsf; - mbsf.setLoopMBS(loopMBS); - if (nextMBS != null) - mbsf.setMBeanServer(nextMBS); - return mbsf; - } - - /** - * Returns a proxy of the default {@code EventClientDelegateMBean}. - * - * @param conn An {@link MBeanServerConnection} to work with. - */ - @SuppressWarnings("cast") // cast for jdk 1.5 - public static EventClientDelegateMBean getProxy(MBeanServerConnection conn) { - return (EventClientDelegateMBean)MBeanServerInvocationHandler. - newProxyInstance(conn, - OBJECT_NAME, - EventClientDelegateMBean.class, - false); - } - - public String addClient(String className, Object[] params, String[] sig) - throws MBeanException { - return addClient(className, null, params, sig, true); - } - - public String addClient(String className, - ObjectName classLoader, - Object[] params, - String[] sig) throws MBeanException { - return addClient(className, classLoader, params, sig, false); - } - - private String addClient(String className, - ObjectName classLoader, - Object[] params, - String[] sig, - boolean classLoaderRepository) throws MBeanException { - try { - return addClientX( - className, classLoader, params, sig, classLoaderRepository); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - throw new MBeanException(e); - } - } - - private String addClientX(String className, - ObjectName classLoader, - Object[] params, - String[] sig, - boolean classLoaderRepository) throws Exception { - if (className == null) { - throw new IllegalArgumentException("Null class name."); - } - - final Object o; - - // The special treatment of standard EventForwarders is so that no - // special permissions are necessary to use them. Otherwise you - // couldn't use EventClient if you didn't have permission to call - // MBeanServer.instantiate. We do require that permission for - // non-standard forwarders, because otherwise you could instantiate - // any class with possibly adverse consequences. We also avoid using - // MBeanInstantiator because it looks up constructors by loading each - // class in the sig array, which means a remote user could cause any - // class to be loaded. That's probably not hugely risky but still. - if (className.startsWith("javax.management.event.")) { - Class c = Class.forName( - className, false, this.getClass().getClassLoader()); - Constructor foundCons = null; - if (sig == null) - sig = new String[0]; - for (Constructor cons : c.getConstructors()) { - Class[] types = cons.getParameterTypes(); - String[] consSig = new String[types.length]; - for (int i = 0; i < types.length; i++) - consSig[i] = types[i].getName(); - if (Arrays.equals(sig, consSig)) { - foundCons = cons; - break; - } - } - if (foundCons == null) { - throw new NoSuchMethodException( - "Constructor for " + className + " with argument types " + - Arrays.toString(sig)); - } - o = foundCons.newInstance(params); - } else if (classLoaderRepository) { - o = mbeanServer.instantiate(className, params, sig); - } else { - o = mbeanServer.instantiate(className, classLoader, params, sig); - } - - if (!(o instanceof EventForwarder)) { - throw new IllegalArgumentException( - className+" is not an EventForwarder class."); - } - - final EventForwarder forwarder = (EventForwarder)o; - final String clientId = UUID.randomUUID().toString(); - ClientInfo clientInfo = new ClientInfo(clientId, forwarder); - - clientInfoMap.put(clientId, clientInfo); - - forwarder.setClientId(clientId); - - if (logger.traceOn()) { - logger.trace("addClient", clientId); - } - - return clientId; - } - - public Integer[] getListenerIds(String clientId) - throws IOException, EventClientNotFoundException { - ClientInfo clientInfo = getClientInfo(clientId); - - if (clientInfo == null) { - throw new EventClientNotFoundException("The client is not found."); - } - - Map listenerInfoMap = clientInfo.listenerInfoMap; - synchronized (listenerInfoMap) { - Set ids = listenerInfoMap.keySet(); - return ids.toArray(new Integer[ids.size()]); - } - } - - /** - * {@inheritDoc} - * - *

    The execution of this method includes a call to - * {@link MBeanServer#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object)}.

    - */ - public Integer addListener(String clientId, - final ObjectName name, - NotificationFilter filter) - throws EventClientNotFoundException, InstanceNotFoundException { - - if (logger.traceOn()) { - logger.trace("addListener", ""); - } - - return getClientInfo(clientId).addListenerInfo(name, filter); - } - - /** - * {@inheritDoc} - * - *

    The execution of this method can include call to - * {@link MBeanServer#removeNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object)}.

    - */ - public void removeListenerOrSubscriber(String clientId, Integer listenerId) - throws InstanceNotFoundException, - ListenerNotFoundException, - EventClientNotFoundException, - IOException { - if (logger.traceOn()) { - logger.trace("removeListener", ""+listenerId); - } - getClientInfo(clientId).removeListenerInfo(listenerId); - } - - /** - * {@inheritDoc} - * - *

    The execution of this method includes a call to - * {@link MBeanServer#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object)} for - * every MBean matching {@code name}. If {@code name} is - * an {@code ObjectName} pattern, then the execution of this - * method will include a call to {@link MBeanServer#queryNames}.

    - */ - public Integer addSubscriber(String clientId, ObjectName name, - NotificationFilter filter) - throws EventClientNotFoundException, IOException { - if (logger.traceOn()) { - logger.trace("addSubscriber", ""); - } - return getClientInfo(clientId).subscribeListenerInfo(name, filter); - } - - public NotificationResult fetchNotifications(String clientId, - long startSequenceNumber, - int maxNotifs, - long timeout) - throws EventClientNotFoundException { - if (logger.traceOn()) { - logger.trace("fetchNotifications", "for "+clientId); - } - return getClientInfo(clientId).fetchNotifications(startSequenceNumber, - maxNotifs, - timeout); - } - - public void removeClient(String clientId) - throws EventClientNotFoundException { - if (clientId == null) - throw new EventClientNotFoundException("Null clientId"); - if (logger.traceOn()) { - logger.trace("removeClient", clientId); - } - ClientInfo ci = null; - ci = clientInfoMap.remove(clientId); - - if (ci == null) { - throw new EventClientNotFoundException("clientId is "+clientId); - } else { - ci.clean(); - } - } - - public long lease(String clientId, long timeout) - throws IOException, EventClientNotFoundException { - if (logger.traceOn()) { - logger.trace("lease", "for "+clientId); - } - return getClientInfo(clientId).lease(timeout); - } - - // ------------------------------------ - // private classes - // ------------------------------------ - private class ClientInfo { - final String clientId; - final NotificationListener clientListener; - final Map listenerInfoMap = - new HashMap(); - - ClientInfo(String clientId, EventForwarder forwarder) { - this.clientId = clientId; - this.forwarder = forwarder; - clientListener = - new ForwardingClientListener(listenerInfoMap, forwarder); - } - - Integer addOrSubscribeListenerInfo( - ObjectName name, NotificationFilter filter, boolean subscribe) - throws InstanceNotFoundException, IOException { - - final Integer listenerId = nextListenerId(); - AddedListener listenerInfo = new AddedListener( - listenerId, filter, name, subscribe); - if (subscribe) { - eventSubscriber.subscribe(name, - clientListener, - filter, - listenerInfo); - } else { - mbeanServer.addNotificationListener(name, - clientListener, - filter, - listenerInfo); - } - - synchronized(listenerInfoMap) { - listenerInfoMap.put(listenerId, listenerInfo); - } - - return listenerId; - } - - Integer addListenerInfo(ObjectName name, - NotificationFilter filter) throws InstanceNotFoundException { - try { - return addOrSubscribeListenerInfo(name, filter, false); - } catch (IOException e) { // can't happen - logger.warning( - "EventClientDelegate.addListenerInfo", - "unexpected exception", e); - throw new RuntimeException(e); - } - } - - Integer subscribeListenerInfo(ObjectName name, - NotificationFilter filter) throws IOException { - try { - return addOrSubscribeListenerInfo(name, filter, true); - } catch (InstanceNotFoundException e) { // can't happen - logger.warning( - "EventClientDelegate.subscribeListenerInfo", - "unexpected exception", e); - throw new RuntimeException(e); - } - } - - private final AtomicInteger nextListenerId = new AtomicInteger(); - - private Integer nextListenerId() { - return nextListenerId.getAndIncrement(); - } - - NotificationResult fetchNotifications(long startSequenceNumber, - int maxNotifs, - long timeout) { - - if (!(forwarder instanceof FetchingEventForwarder)) { - throw new IllegalArgumentException( - "This client is using Event Postal Service!"); - } - - return ((FetchingEventForwarder)forwarder). - fetchNotifications(startSequenceNumber, - maxNotifs, timeout); - } - - void removeListenerInfo(Integer listenerId) - throws InstanceNotFoundException, ListenerNotFoundException, IOException { - AddedListener listenerInfo; - synchronized(listenerInfoMap) { - listenerInfo = listenerInfoMap.remove(listenerId); - } - - if (listenerInfo == null) { - throw new ListenerNotFoundException("The listener is not found."); - } - - if (listenerInfo.subscription) { - eventSubscriber.unsubscribe(listenerInfo.name, - clientListener); - } else { - mbeanServer.removeNotificationListener(listenerInfo.name, - clientListener, - listenerInfo.filter, - listenerInfo); - } - } - - void clean(ObjectName name) { - synchronized(listenerInfoMap) { - for (Map.Entry entry : - listenerInfoMap.entrySet()) { - AddedListener li = entry.getValue(); - if (name.equals(li.name)) { - listenerInfoMap.remove(entry.getKey()); - } - } - } - } - - void clean() { - synchronized(listenerInfoMap) { - for (AddedListener li : listenerInfoMap.values()) { - try { - mbeanServer.removeNotificationListener(li.name, - clientListener); - } catch (Exception e) { - logger.trace("ClientInfo.clean", "removeNL", e); - } - } - listenerInfoMap.clear(); - } - - try { - forwarder.close(); - } catch (Exception e) { - logger.trace( - "ClientInfo.clean", "forwarder.close", e); - } - - if (leaseManager != null) { - leaseManager.stop(); - } - } - - long lease(long timeout) { - return leaseManager.lease(timeout); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (o instanceof ClientInfo && - clientId.equals(((ClientInfo)o).clientId)) { - return true; - } - - return false; - } - - @Override - public int hashCode() { - return clientId.hashCode(); - } - - private EventForwarder forwarder = null; - - private final Runnable leaseExpiryCallback = new Runnable() { - public void run() { - try { - removeClient(clientId); - } catch (Exception e) { - logger.trace( - "ClientInfo.leaseExpiryCallback", "removeClient", e); - } - } - }; - - private LeaseManager leaseManager = new LeaseManager(leaseExpiryCallback); - } - - private class ForwardingClientListener implements NotificationListener { - public ForwardingClientListener(Map listenerInfoMap, - EventForwarder forwarder) { - this.listenerInfoMap = listenerInfoMap; - this.forwarder = forwarder; - } - - public void handleNotification(Notification n, Object o) { - if (n == null || (!(o instanceof AddedListener))) { - if (logger.traceOn()) { - logger.trace("ForwardingClientListener-handleNotification", - "received a unknown notif"); - } - return; - } - - AddedListener li = (AddedListener) o; - - if (checkListenerPermission(li.name,li.acc)) { - try { - forwarder.forward(n, li.listenerId); - } catch (Exception e) { - if (logger.traceOn()) { - logger.trace( - "ForwardingClientListener-handleNotification", - "forwarding failed.", e); - } - } - } - } - - private final Map listenerInfoMap; - private final EventForwarder forwarder; - } - - private class AddedListener { - final int listenerId; - final NotificationFilter filter; - final ObjectName name; - final boolean subscription; - final AccessControlContext acc; - - public AddedListener( - int listenerId, - NotificationFilter filter, - ObjectName name, - boolean subscription) { - this.listenerId = listenerId; - this.filter = filter; - this.name = name; - this.subscription = subscription; - acc = AccessController.getContext(); - } - } - - private class CleanListener implements NotificationListener { - public void handleNotification(Notification notification, - Object handback) { - if (notification instanceof MBeanServerNotification) { - if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals( - notification.getType())) { - final ObjectName name = - ((MBeanServerNotification)notification).getMBeanName(); - - final Collection list = - Collections.unmodifiableCollection(clientInfoMap.values()); - - for (ClientInfo ci : list) { - ci.clean(name); - } - } - - } - } - } - - // ------------------------------------------------- - // private method - // ------------------------------------------------- - private ClientInfo getClientInfo(String clientId) - throws EventClientNotFoundException { - ClientInfo clientInfo = null; - clientInfo = clientInfoMap.get(clientId); - - if (clientInfo == null) { - throw new EventClientNotFoundException( - "Client not found (id " + clientId + ")"); - } - - return clientInfo; - } - - /** - * Explicitly check the MBeanPermission for - * the current access control context. - */ - private boolean checkListenerPermission(final ObjectName name, - final AccessControlContext acc) { - if (logger.traceOn()) { - logger.trace("checkListenerPermission", ""); - } - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - final String serverName = getMBeanServerName(); - - ObjectInstance oi = (ObjectInstance) - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Object run() - throws InstanceNotFoundException { - return mbeanServer.getObjectInstance(name); - } - }); - - String classname = oi.getClassName(); - MBeanPermission perm = new MBeanPermission( - serverName, - classname, - null, - name, - "addNotificationListener"); - sm.checkPermission(perm, acc); - } catch (Exception e) { - if (logger.debugOn()) { - logger.debug("checkListenerPermission", "refused.", e); - } - return false; - } - } - return true; - } - - private String getMBeanServerName() { - if (mbeanServerName != null) return mbeanServerName; - else return (mbeanServerName = getMBeanServerName(mbeanServer)); - } - - private static String getMBeanServerName(final MBeanServer server) { - final PrivilegedAction action = new PrivilegedAction() { - public String run() { - return Util.getMBeanServerSecurityName(server); - } - }; - return AccessController.doPrivileged(action); - } - - // ------------------------------------ - // private variables - // ------------------------------------ - private final MBeanServer mbeanServer; - private volatile String mbeanServerName = null; - private Map clientInfoMap = - new ConcurrentHashMap(); - - private final CleanListener cleanListener = new CleanListener(); - private final EventSubscriber eventSubscriber; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventClientDelegate"); - - private static final - Map> delegateMap = - new WeakHashMap>(); -} diff --git a/src/share/classes/javax/management/event/EventClientDelegateMBean.java b/src/share/classes/javax/management/event/EventClientDelegateMBean.java deleted file mode 100644 index e6030b613..000000000 --- a/src/share/classes/javax/management/event/EventClientDelegateMBean.java +++ /dev/null @@ -1,317 +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 javax.management.event; - -import com.sun.jmx.mbeanserver.Util; -import java.io.IOException; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.NotificationFilter; -import javax.management.ObjectName; -import javax.management.remote.NotificationResult; - -/** - *

    This interface specifies necessary methods on the MBean server - * side for a JMX remote client to manage its notification listeners as - * if they are local. - * Users do not usually work directly with this MBean; instead, the {@link - * EventClient} class is designed to be used directly by the user.

    - * - *

    A default implementation of this interface can be added to an MBean - * Server in one of several ways.

    - * - *
      - *
    • The most usual is to insert an {@link - * javax.management.remote.MBeanServerForwarder MBeanServerForwarder} between - * the {@linkplain javax.management.remote.JMXConnectorServer Connector Server} - * and the MBean Server, that will intercept accesses to the Event Client - * Delegate MBean and treat them as the real MBean would. This forwarder is - * inserted by default with the standard RMI Connector Server, and can also - * be created explicitly using {@link EventClientDelegate#newForwarder - * EventClientDelegate.newForwarder}. - * - *

    • A variant on the above is to replace the MBean Server that is - * used locally with a forwarder as described above. Since - * {@code MBeanServerForwarder} extends {@code MBeanServer}, you can use - * a forwarder anywhere you would have used the original MBean Server. The - * code to do this replacement typically looks something like this:

      - * - *
      - * MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();  // or whatever
      - * mbs = EventClientDelegate.newForwarder(mbs, null);
      - * // now use mbs just as you did before, but it will have an EventClientDelegate
      - * 
      - * - *
    • The final way is to create an instance of {@link EventClientDelegate} - * and register it in the MBean Server under the standard {@linkplain - * #OBJECT_NAME name}:

      - * - *
      - * MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();  // or whatever
      - * EventClientDelegate ecd = EventClientDelegate.getEventClientDelegate(mbs);
      - * mbs.registerMBean(ecd, EventClientDelegateMBean.OBJECT_NAME);
      - * 
      - * 
    - * - * @since JMX 2.0 - */ -public interface EventClientDelegateMBean { - /** - * The string representation of {@link #OBJECT_NAME}. - */ - // This shouldn't really be necessary but an apparent javadoc bug - // meant that the {@value} tags didn't work if this was a - // field in EventClientDelegate, even a public field. - public static final String OBJECT_NAME_STRING = - "javax.management.event:type=EventClientDelegate"; - - /** - * The standard ObjectName used to register the default - * EventClientDelegateMBean. The name is - * {@value #OBJECT_NAME_STRING}. - */ - public final static ObjectName OBJECT_NAME = - ObjectName.valueOf(OBJECT_NAME_STRING); - - /** - * A unique listener identifier specified for an EventClient. - * Any notification associated with this id is intended for - * the EventClient which receives the notification, rather than - * a listener added using that EventClient. - */ - public static final int EVENT_CLIENT_LISTENER_ID = -100; - - /** - * Adds a new client to the EventClientDelegateMBean with - * a user-specified - * {@link EventForwarder} to forward notifications to the client. The - * EventForwarder is created by calling - * {@link javax.management.MBeanServer#instantiate(String, Object[], - * String[])}. - * - * @param className The class name used to create an - * {@code EventForwarder}. - * @param params An array containing the parameters of the constructor to - * be invoked. - * @param sig An array containing the signature of the constructor to be - * invoked - * @return A client identifier. - * @exception IOException Reserved for a remote call to throw on the client - * side. - * @exception MBeanException An exception thrown when creating the user - * specified EventForwarder. - */ - public String addClient(String className, Object[] params, String[] sig) - throws IOException, MBeanException; - - /** - * Adds a new client to the EventClientDelegateMBean with - * a user-specified - * {@link EventForwarder} to forward notifications to the client. The - * EventForwarder is created by calling - * {@link javax.management.MBeanServer#instantiate(String, ObjectName, - * Object[], String[])}. A user-specified class loader is used to create - * this EventForwarder. - * - * @param className The class name used to create an - * {@code EventForwarder}. - * @param classLoader An ObjectName registered as a - * ClassLoader MBean. - * @param params An array containing the parameters of the constructor to - * be invoked. - * @param sig An array containing the signature of the constructor to be - * invoked - * @return A client identifier. - * @exception IOException Reserved for a remote call to throw on the client - * side. - * @exception MBeanException An exception thrown when creating the user - * specified EventForwarder. - */ - public String addClient(String className, - ObjectName classLoader, - Object[] params, - String[] sig) throws IOException, MBeanException; - - /** - * Removes an added client. Calling this method will remove all listeners - * added with the client. - * - * @exception EventClientNotFoundException If the {@code clientId} is - * not found. - * @exception IOException Reserved for a remote call to throw on the client - * side. - */ - public void removeClient(String clientID) - throws EventClientNotFoundException, IOException; - - /** - * Returns the identifiers of listeners added or subscribed to with the - * specified client identifier. - *

    If no listener is currently registered with the client, an empty - * array is returned. - * @param clientID The client identifier with which the listeners are - * added or subscribed to. - * @return An array of listener identifiers. - * @exception EventClientNotFoundException If the {@code clientId} is - * not found. - * @exception IOException Reserved for a remote call to throw on the client - * side. - */ - public Integer[] getListenerIds(String clientID) - throws EventClientNotFoundException, IOException; - - /** - * Adds a listener to receive notifications from an MBean and returns - * a non-negative integer as the identifier of the listener. - *

    This method is called by an {@link EventClient} to implement the - * method {@link EventClient#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object)}. - * - * @param name The name of the MBean onto which the listener should be added. - * @param filter The filter object. If {@code filter} is null, - * no filtering will be performed before handling notifications. - * @param clientId The client identifier with which the listener is added. - * @return A listener identifier. - * @throws EventClientNotFoundException Thrown if the {@code clientId} is - * not found. - * @throws InstanceNotFoundException Thrown if the MBean is not found. - * @throws IOException Reserved for a remote call to throw on the client - * side. - */ - public Integer addListener(String clientId, - ObjectName name, - NotificationFilter filter) - throws InstanceNotFoundException, EventClientNotFoundException, - IOException; - - - /** - *

    Subscribes a listener to receive notifications from an MBean or a - * set of MBeans represented by an {@code ObjectName} pattern. (It is - * not an error if no MBeans match the pattern at the time this method is - * called.)

    - * - *

    Returns a non-negative integer as the identifier of the listener.

    - * - *

    This method is called by an {@link EventClient} to execute its - * method {@link EventClient#subscribe(ObjectName, NotificationListener, - * NotificationFilter, Object)}.

    - * - * @param clientId The remote client's identifier. - * @param name The name of an MBean or an {@code ObjectName} pattern - * representing a set of MBeans to which the listener should listen. - * @param filter The filter object. If {@code filter} is null, no - * filtering will be performed before notifications are handled. - * - * @return A listener identifier. - * - * @throws IllegalArgumentException If the {@code name} or - * {@code listener} is null. - * @throws EventClientNotFoundException If the client ID is not found. - * @throws IOException Reserved for a remote client to throw if - * an I/O error occurs. - * - * @see EventConsumer#subscribe(ObjectName, NotificationListener, - * NotificationFilter,Object) - * @see #removeListenerOrSubscriber(String, Integer) - */ - public Integer addSubscriber(String clientId, ObjectName name, - NotificationFilter filter) - throws EventClientNotFoundException, IOException; - - /** - * Removes a listener, to stop receiving notifications. - *

    This method is called by an {@link EventClient} to execute its - * methods {@link EventClient#removeNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object)}, - * {@link EventClient#removeNotificationListener(ObjectName, - * NotificationListener)}, and {@link EventClient#unsubscribe}. - * - * @param clientId The client identifier with which the listener was added. - * @param listenerId The listener identifier to be removed. This must be - * an identifier returned by a previous {@link #addListener addListener} - * or {@link #addSubscriber addSubscriber} call. - * - * @throws InstanceNotFoundException if the MBean on which the listener - * was added no longer exists. - * @throws ListenerNotFoundException if there is no listener with the - * given {@code listenerId}. - * @throws EventClientNotFoundException if the {@code clientId} is - * not found. - * @throws IOException Reserved for a remote call to throw on the client - * side. - */ - public void removeListenerOrSubscriber(String clientId, Integer listenerId) - throws InstanceNotFoundException, ListenerNotFoundException, - EventClientNotFoundException, IOException; - - /** - * Called by a client to fetch notifications that are to be sent to its - * listeners. - * - * @param clientId The client's identifier. - * @param startSequenceNumber The first sequence number to - * consider. - * @param timeout The maximum waiting time. - * @param maxNotifs The maximum number of notifications to return. - * - * @throws EventClientNotFoundException Thrown if the {@code clientId} is - * not found. - * @throws IllegalArgumentException if the client was {@linkplain - * #addClient(String, Object[], String[]) added} with an {@link - * EventForwarder} that is not a {@link FetchingEventForwarder}. - * @throws IOException Reserved for a remote call to throw on the client - * side. - */ - public NotificationResult fetchNotifications(String clientId, - long startSequenceNumber, - int maxNotifs, - long timeout) - throws EventClientNotFoundException, IOException; - - /** - * An {@code EventClient} calls this method to keep its {@code clientId} - * alive in this MBean. The client will be removed if the lease times out. - * - * @param clientId The client's identifier. - * @param timeout The time in milliseconds by which the lease is to be - * extended. The value zero has no special meaning, so it will cause the - * lease to time out immediately. - * - * @return The new lifetime of the lease in milliseconds. This may be - * different from the requested time. - * - * @throws EventClientNotFoundException if the {@code clientId} is - * not found. - * @throws IOException reserved for a remote call to throw on the client - * side. - * @throws IllegalArgumentException if {@code clientId} is null or - * {@code timeout} is negative. - */ - public long lease(String clientId, long timeout) - throws IOException, EventClientNotFoundException; -} diff --git a/src/share/classes/javax/management/event/EventClientNotFoundException.java b/src/share/classes/javax/management/event/EventClientNotFoundException.java deleted file mode 100644 index 22f22d731..000000000 --- a/src/share/classes/javax/management/event/EventClientNotFoundException.java +++ /dev/null @@ -1,79 +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 javax.management.event; - -import javax.management.JMException; - -/** - * Thrown if an event client identifier is unknown. - */ -public class EventClientNotFoundException extends JMException { - - /* Serial version */ - private static final long serialVersionUID = -3910667345840643089L; - - /** - *Constructs a {@code ClientNotFoundException} without a detail message. - */ - public EventClientNotFoundException() { - super(); - } - - /** - * Constructs a {@code ClientNotFoundException} with the specified detail message. - * @param message The message. - */ - public EventClientNotFoundException(String message) { - super(message); - } - - /** - * Constructs a {@code ClientNotFoundException} with the specified detail message - * and cause. - * - * @param message The message. - * @param cause The cause (which is saved for later retrieval by the - * {@code Throwable.getCause()} method). A null value is permitted, and indicates - * that the cause is non-existent or unknown. - */ - public EventClientNotFoundException(String message, Throwable cause) { - super(message); - - initCause(cause); - } - - /** - * Constructs a new exception with the specified cause. - * @param cause The cause (which is saved for later retrieval by the - * {@code Throwable.getCause()} method). A null value is permitted, and indicates - * that the cause is non-existent or unknown. - */ - public EventClientNotFoundException(Throwable cause) { - super(); - - initCause(cause); - } -} diff --git a/src/share/classes/javax/management/event/EventConsumer.java b/src/share/classes/javax/management/event/EventConsumer.java deleted file mode 100644 index c2617764e..000000000 --- a/src/share/classes/javax/management/event/EventConsumer.java +++ /dev/null @@ -1,98 +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 javax.management.event; - -import java.io.IOException; -import javax.management.ListenerNotFoundException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; - -/** - * This interface specifies methods to subscribe a listener to receive events - * from an MBean or a set of MBeans. The MBeans can already be registered in - * an MBean server, or they can be pending registration, or they can be MBeans - * that will never be registered, or they can be MBeans that will be registered - * then unregistered. - * @since JMX 2.0 - */ -public interface EventConsumer { - /** - *

    Subscribes a listener to receive events from an MBean or a set - * of MBeans represented by an {@code ObjectName} pattern.

    - * - *

    An event emitted by an MBean is forwarded to every listener that was - * subscribed with the name of that MBean, or with a pattern that matches - * that name.

    - * - * @param name The name of an MBean or an {@code ObjectName} pattern - * representing a set of MBeans to which the listener should listen. - * @param listener The listener object that will handle the - * notifications emitted by the MBeans. - * @param filter The filter object. If {@code filter} is null, no - * filtering will be performed before notification handling. - * @param handback The context to be sent to the listener when a - * notification is emitted. - * - * @throws IllegalArgumentException If the {@code name} or - * {@code listener} is null. - * @throws IOException for a remote client, thrown if - * an I/O error occurs. - * @see #unsubscribe(ObjectName, NotificationListener) - */ - public void subscribe(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws IOException; - - /** - *

    Unsubscribes a listener which is listening to an MBean or a set of - * MBeans represented by an {@code ObjectName} pattern.

    - * - *

    The listener to be removed must have been added by the {@link - * #subscribe subscribe} method with the given {@code name}. If the {@code - * name} is a pattern, then the {@code subscribe} must have used the same - * pattern. If the same listener has been subscribed more than once to the - * {@code name}, perhaps with different filters or handbacks, then all such - * listeners are removed.

    - * - * @param name The name of the MBean or an {@code ObjectName} pattern - * representing a set of MBeans to which the listener was subscribed. - * @param listener A listener that was previously subscribed to the - * MBean(s). - * - * @throws ListenerNotFoundException The given {@code listener} was not - * subscribed to the given {@code name}. - * @throws IOException for a remote client, thrown if - * an I/O error occurs. - * - * @see #subscribe - */ - public void unsubscribe(ObjectName name, - NotificationListener listener) - throws ListenerNotFoundException, IOException; -} diff --git a/src/share/classes/javax/management/event/EventForwarder.java b/src/share/classes/javax/management/event/EventForwarder.java deleted file mode 100644 index 3dff0a7bc..000000000 --- a/src/share/classes/javax/management/event/EventForwarder.java +++ /dev/null @@ -1,63 +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 javax.management.event; - -import java.io.IOException; -import javax.management.Notification; - -/** - * This interface can be used to specify a custom forwarding mechanism for - * {@code EventClientDelegateMBean} to forward events to the client. - * - * @see Custom notification - * transports - */ -public interface EventForwarder { - /** - * Forwards a notification. - * @param n The notification to be forwarded to a remote listener. - * @param listenerId The identifier of the listener to receive the notification. - * @throws IOException If it is closed or an I/O error occurs. - */ - public void forward(Notification n, Integer listenerId) - throws IOException; - - /** - * Informs the {@code EventForwarder} to shut down. - *

    After this method is called, any call to the method - * {@link #forward forward(Notification, Integer)} may get an {@code IOException}. - * @throws IOException If an I/O error occurs. - */ - public void close() throws IOException; - - /** - * Sets an event client identifier created by {@link EventClientDelegateMBean}. - *

    This method will be called just after this {@code EventForwarder} - * is constructed and before calling the {@code forward} method to forward any - * notifications. - */ - public void setClientId(String clientId) throws IOException; -} diff --git a/src/share/classes/javax/management/event/EventReceiver.java b/src/share/classes/javax/management/event/EventReceiver.java deleted file mode 100644 index 7cdd38b7f..000000000 --- a/src/share/classes/javax/management/event/EventReceiver.java +++ /dev/null @@ -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 javax.management.event; - -import javax.management.remote.NotificationResult; - -/** - * An object implementing this interface is passed by an {@link EventClient} - * to its {@link EventRelay}, to allow the {@code EventRelay} to communicate - * received notifications to the {@code EventClient}. - * - * @see Custom notification - * transports - */ -public interface EventReceiver { - - /** - * This method is implemented by {@code EventClient} as a callback to - * receive notifications from {@code EventRelay}. - *

    The notifications are included in an object specified by the class - * {@link NotificationResult}. In - * addition to a set of notifications, the class object also contains two values: - * {@code earliestSequenceNumber} and {@code nextSequenceNumber}. - * These two values determine whether any notifications have been lost. - * The {@code nextSequenceNumber} value of the last time is compared - * to the received value {@code earliestSequenceNumber}. If the - * received {@code earliesSequenceNumber} is greater, than the difference - * signifies the number of lost notifications. A sender should - * ensure the sequence of notifications sent, meaning that the value - * {@code earliestSequenceNumber} of the next return should be always equal to - * or greater than the value {@code nextSequenceNumber} of the last return. - * - * @param nr the received notifications and sequence numbers. - */ - public void receive(NotificationResult nr); - - /** - * Allows the {@link EventRelay} to report when it receives an unexpected - * exception, which may be fatal and which may make it stop receiving - * notifications. - * - * @param t The unexpected exception received while {@link EventRelay} was running. - */ - public void failed(Throwable t); - - /** - * Allows the {@link EventRelay} to report when it receives an unexpected - * exception that is not fatal. For example, a notification received is not - * serializable or its class is not found. - * - * @param e The unexpected exception received while notifications are being received. - */ - public void nonFatal(Exception e); -} diff --git a/src/share/classes/javax/management/event/EventRelay.java b/src/share/classes/javax/management/event/EventRelay.java deleted file mode 100644 index d106a1605..000000000 --- a/src/share/classes/javax/management/event/EventRelay.java +++ /dev/null @@ -1,79 +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 javax.management.event; - -import java.io.IOException; -import java.util.concurrent.Executors; // for javadoc - -/** - * This interface is used to specify a way to receive - * notifications from a remote MBean server and then to forward the notifications - * to an {@link EventClient}. - * - * @see Custom notification - * transports - */ -public interface EventRelay { - /** - * Returns an identifier that is used by this {@code EventRelay} to identify - * the client when communicating with the {@link EventClientDelegateMBean}. - *

    This identifier is obtained by calling - * {@link EventClientDelegateMBean#addClient(String, Object[], String[]) - * EventClientDelegateMBean.addClient}. - *

    It is the {@code EventRelay} that calls {@code EventClientDelegateMBean} to obtain - * the client identifier because it is the {@code EventRelay} that decides - * how to get notifications from the {@code EventClientDelegateMBean}, - * by creating the appropriate {@link EventForwarder}. - * - * @return A client identifier. - * @throws IOException If an I/O error occurs when communicating with - * the {@code EventClientDelegateMBean}. - */ - public String getClientId() throws IOException; - - /** - * This method is called by {@link EventClient} to register a callback - * to receive notifications from an {@link EventClientDelegateMBean} object. - * A {@code null} value is allowed, which means that the {@code EventClient} suspends - * reception of notifications, so that the {@code EventRelay} can decide to stop receiving - * notifications from its {@code EventForwarder}. - * - * @param eventReceiver An {@link EventClient} callback to receive - * events. - */ - public void setEventReceiver(EventReceiver eventReceiver); - - /** - * Stops receiving and forwarding notifications and performs any necessary - * cleanup. After calling this method, the {@link EventClient} will never - * call any other methods of this object. - * - * @throws IOException If an I/O exception appears. - * - * @see EventClient#close - */ - public void stop() throws IOException; -} diff --git a/src/share/classes/javax/management/event/EventSubscriber.java b/src/share/classes/javax/management/event/EventSubscriber.java deleted file mode 100644 index 5a472b5ad..000000000 --- a/src/share/classes/javax/management/event/EventSubscriber.java +++ /dev/null @@ -1,376 +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 javax.management.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.io.IOException; -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerNotification; -import javax.management.Notification; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.Query; -import javax.management.QueryEval; -import javax.management.QueryExp; - -/** - *

    An object that can be used to subscribe for notifications from all MBeans - * in an MBeanServer that match a pattern. For example, to listen for - * notifications from all MBeans in the MBeanServer {@code mbs} that match - * {@code com.example:type=Controller,name=*} you could write:

    - * - *
    - * EventSubscriber subscriber = EventSubscriber.getEventSubscriber(mbs);
    - * ObjectName pattern = new ObjectName("com.example:type=Controller,name=*");
    - * NotificationListener myListener = ...;
    - * NotificationFilter myFilter = null;  // or whatever
    - * Object handback = null;              // or whatever
    - * subscriber.subscribe(pattern, myListener, myFilter, myHandback);
    - * 
    - */ -public class EventSubscriber implements EventConsumer { - /** - * Returns an {@code EventSubscriber} object to subscribe for notifications - * from the given {@code MBeanServer}. Calling this method more - * than once with the same parameter may or may not return the same object. - * - * @param mbs the {@code MBeanServer} containing MBeans to be subscribed to. - * @return An {@code EventSubscriber} object. - * - * @throws NullPointerException if mbs is null. - */ - public static EventSubscriber getEventSubscriber(MBeanServer mbs) { - if (mbs == null) - throw new NullPointerException("Null MBeanServer"); - - EventSubscriber eventSubscriber = null; - synchronized (subscriberMap) { - final WeakReference wrf = subscriberMap.get(mbs); - eventSubscriber = (wrf == null) ? null : wrf.get(); - - if (eventSubscriber == null) { - eventSubscriber = new EventSubscriber(mbs); - - subscriberMap.put(mbs, - new WeakReference(eventSubscriber)); - } - } - - return eventSubscriber; - } - - private EventSubscriber(final MBeanServer mbs) { - logger.trace("EventSubscriber", "create a new one"); - this.mbeanServer = mbs; - - Exception x = null; - try { - AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public Void run() throws Exception { - mbs.addNotificationListener( - MBeanServerDelegate.DELEGATE_NAME, - myMBeanServerListener, null, null); - return null; - } - }); - } catch (PrivilegedActionException ex) { - x = ex.getException(); - } - - // handle possible exceptions. - // - // Fail unless x is null or x is instance of InstanceNotFoundException - // The logic here is that if the MBeanServerDelegate is not present, - // we will assume that the connection will not emit any - // MBeanServerNotifications. - // - if (x != null && !(x instanceof InstanceNotFoundException)) { - if (x instanceof RuntimeException) - throw (RuntimeException) x; - throw new RuntimeException( - "Can't add listener to MBean server delegate: " + x, x); - } - } - - public void subscribe(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws IOException { - - if (logger.traceOn()) - logger.trace("subscribe", "" + name); - - if (name == null) - throw new IllegalArgumentException("Null MBean name"); - - if (listener == null) - throw new IllegalArgumentException("Null listener"); - - final MyListenerInfo li = new MyListenerInfo(listener, filter, handback); - List list; - - Map> map; - Set names; - if (name.isPattern()) { - map = patternSubscriptionMap; - names = mbeanServer.queryNames(name, notificationBroadcasterExp); - } else { - map = exactSubscriptionMap; - names = Collections.singleton(name); - } - - synchronized (map) { - list = map.get(name); - if (list == null) { - list = new ArrayList(); - map.put(name, list); - } - list.add(li); - } - - for (ObjectName mbeanName : names) { - try { - mbeanServer.addNotificationListener(mbeanName, - listener, - filter, - handback); - } catch (Exception e) { - logger.fine("subscribe", "addNotificationListener", e); - } - } - } - - public void unsubscribe(ObjectName name, - NotificationListener listener) - throws ListenerNotFoundException, IOException { - if (logger.traceOn()) - logger.trace("unsubscribe", "" + name); - - if (name == null) - throw new IllegalArgumentException("Null MBean name"); - - if (listener == null) - throw new ListenerNotFoundException(); - - Map> map; - Set names; - - if (name.isPattern()) { - map = patternSubscriptionMap; - names = mbeanServer.queryNames(name, notificationBroadcasterExp); - } else { - map = exactSubscriptionMap; - names = Collections.singleton(name); - } - - List toRemove = new ArrayList(); - synchronized (map) { - List list = map.get(name); - if (list == null) { - throw new ListenerNotFoundException(); - } - - for (MyListenerInfo info : list) { - if (info.listener == listener) { - toRemove.add(info); - } - } - - if (toRemove.isEmpty()) { - throw new ListenerNotFoundException(); - } - - for (MyListenerInfo info : toRemove) { - list.remove(info); - } - - if (list.isEmpty()) - map.remove(name); - } - - for (ObjectName mbeanName : names) { - for (MyListenerInfo i : toRemove) { - try { - mbeanServer.removeNotificationListener(mbeanName, - i.listener, i.filter, i.handback); - } catch (Exception e) { - logger.fine("unsubscribe", "removeNotificationListener", e); - } - } - } - } - - // --------------------------------- - // private stuff - // --------------------------------- - // used to receive MBeanServerNotification - private NotificationListener myMBeanServerListener = - new NotificationListener() { - public void handleNotification(Notification n, Object hb) { - if (!(n instanceof MBeanServerNotification) || - !MBeanServerNotification. - REGISTRATION_NOTIFICATION.equals(n.getType())) { - return; - } - - final ObjectName name = - ((MBeanServerNotification)n).getMBeanName(); - try { - if (!mbeanServer.isInstanceOf(name, - NotificationBroadcaster.class.getName())) { - return; - } - } catch (Exception e) { - // The only documented exception is InstanceNotFoundException, - // which could conceivably happen if the MBean is unregistered - // immediately after being registered. - logger.fine("myMBeanServerListener.handleNotification", - "isInstanceOf", e); - return; - } - - final List listeners = new ArrayList(); - - // If there are subscribers for the exact name that has just arrived - // then add their listeners to the list. - synchronized (exactSubscriptionMap) { - List exactListeners = exactSubscriptionMap.get(name); - if (exactListeners != null) - listeners.addAll(exactListeners); - } - - // For every subscription pattern that matches the new name, - // add all the listeners for that pattern to "listeners". - synchronized (patternSubscriptionMap) { - for (ObjectName on : patternSubscriptionMap.keySet()) { - if (on.apply(name)) { - listeners.addAll(patternSubscriptionMap.get(on)); - } - } - } - - // Add all the listeners just found to the new MBean. - for (MyListenerInfo li : listeners) { - try { - mbeanServer.addNotificationListener( - name, - li.listener, - li.filter, - li.handback); - } catch (Exception e) { - logger.fine("myMBeanServerListener.handleNotification", - "addNotificationListener", e); - } - } - } - }; - - private static class MyListenerInfo { - public final NotificationListener listener; - public final NotificationFilter filter; - public final Object handback; - - public MyListenerInfo(NotificationListener listener, - NotificationFilter filter, - Object handback) { - - if (listener == null) - throw new IllegalArgumentException("Null listener"); - - this.listener = listener; - this.filter = filter; - this.handback = handback; - } - } - - // --------------------------------- - // private methods - // --------------------------------- - // --------------------------------- - // private variables - // --------------------------------- - private final MBeanServer mbeanServer; - - private final Map> exactSubscriptionMap = - new HashMap>(); - private final Map> patternSubscriptionMap = - new HashMap>(); - - - - // trace issues - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventSubscriber"); - - // Compatibility code, so we can run on Tiger: - private static final QueryExp notificationBroadcasterExp; - static { - QueryExp broadcasterExp; - try { - final Method m = Query.class.getMethod("isInstanceOf", String.class); - broadcasterExp = (QueryExp)m.invoke(Query.class, - new Object[] {NotificationBroadcaster.class.getName()}); - } catch (Exception e) { - broadcasterExp = new BroadcasterQueryExp(); - } - notificationBroadcasterExp = broadcasterExp; - } - private static class BroadcasterQueryExp extends QueryEval implements QueryExp { - private static final long serialVersionUID = 1234L; - public boolean apply(ObjectName name) { - try { - return getMBeanServer().isInstanceOf( - name, NotificationBroadcaster.class.getName()); - } catch (Exception e) { - return false; - } - } - } - - private static final - Map> subscriberMap = - new WeakHashMap>(); -} diff --git a/src/share/classes/javax/management/event/FetchingEventForwarder.java b/src/share/classes/javax/management/event/FetchingEventForwarder.java deleted file mode 100644 index fd0ae6de3..000000000 --- a/src/share/classes/javax/management/event/FetchingEventForwarder.java +++ /dev/null @@ -1,151 +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 javax.management.event; - -import com.sun.jmx.event.EventBuffer; -import com.sun.jmx.remote.util.ClassLogger; -import java.io.IOException; -import java.util.List; -import javax.management.Notification; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - -/** - * This class is used by {@link FetchingEventRelay}. When - * {@link FetchingEventRelay} calls {@link - * EventClientDelegateMBean#addClient(String, Object[], String[])} to get a new - * client identifier, it uses - * this class name as the first argument to ask {@code EventClientDelegateMBean} - * to create an object of this class. - * Then {@code EventClientDelegateMBean} forwards client notifications - * to this object. - * When {@link FetchingEventRelay} calls - * {@link EventClientDelegateMBean#fetchNotifications(String, long, int, long)} - * to fetch notifications, the {@code EventClientDelegateMBean} will forward - * the call to this object. - */ -public class FetchingEventForwarder implements EventForwarder { - - /** - * Construct a new {@code FetchingEventForwarder} with the given - * buffer size. - * @param bufferSize the size of the buffer that will store notifications - * until they have been fetched and acknowledged by the client. - */ - public FetchingEventForwarder(int bufferSize) { - if (logger.traceOn()) { - logger.trace("Constructor", "buffer size is "+bufferSize); - } - - buffer = new EventBuffer(bufferSize); - this.bufferSize = bufferSize; - } - - /** - * Called by an {@link EventClientDelegateMBean} to forward a user call - * {@link EventClientDelegateMBean#fetchNotifications(String, long, int, long)}. - * A call of this method is considered to acknowledge reception of all - * notifications whose sequence numbers are less the - * {@code startSequenceNumber}, so all these notifications can be deleted - * from this object. - * - * @param startSequenceNumber The first sequence number to - * consider. - * @param timeout The maximum waiting time in milliseconds. - * If no notifications have arrived after this period of time, the call - * will return with an empty list of notifications. - * @param maxNotifs The maximum number of notifications to return. - */ - public NotificationResult fetchNotifications(long startSequenceNumber, - int maxNotifs, long timeout) { - if (logger.traceOn()) { - logger.trace("fetchNotifications", - startSequenceNumber+" "+ - maxNotifs+" "+ - timeout); - } - - return buffer.fetchNotifications(startSequenceNumber, - timeout, - maxNotifs); - } - - /** - * {@inheritDoc} - * In this implementation, the notification is stored in the local buffer - * waiting for {@link #fetchNotifications fetchNotifications} to pick - * it up. - */ - public void forward(Notification n, Integer listenerId) throws IOException { - if (logger.traceOn()) { - logger.trace("forward", n+" "+listenerId); - } - - buffer.add(new TargetedNotification(n, listenerId)); - } - - public void close() throws IOException { - if (logger.traceOn()) { - logger.trace("close", ""); - } - - buffer.close(); - } - - public void setClientId(String clientId) throws IOException { - if (logger.traceOn()) { - logger.trace("setClientId", clientId); - } - this.clientId = clientId; - } - - /** - * Sets a user specific list to save notifications in server side - * before forwarding to an FetchingEventRelay in client side. - *

    This method should be called before any notification is - * forwarded to this forwader. - * - * @param list a user specific list to save notifications - */ - protected void setList(List list) { - if (logger.traceOn()) { - logger.trace("setList", ""); - } - - if (clientId == null) { - buffer = new EventBuffer(bufferSize, list); - } else { - throw new IllegalStateException(); - } - } - - private EventBuffer buffer; - private int bufferSize; - private String clientId; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "FetchingEventForwarder"); -} diff --git a/src/share/classes/javax/management/event/FetchingEventRelay.java b/src/share/classes/javax/management/event/FetchingEventRelay.java deleted file mode 100644 index cbec8aa82..000000000 --- a/src/share/classes/javax/management/event/FetchingEventRelay.java +++ /dev/null @@ -1,391 +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 javax.management.event; - -import com.sun.jmx.event.DaemonThreadFactory; -import com.sun.jmx.event.RepeatedSingletonJob; -import com.sun.jmx.remote.util.ClassLogger; -import java.io.IOException; -import java.io.NotSerializableException; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import javax.management.MBeanException; -import javax.management.remote.NotificationResult; - -/** - *

    This class is an implementation of the {@link EventRelay} interface. It calls - * {@link EventClientDelegateMBean#fetchNotifications - * fetchNotifications(String, long, int, long)} to get - * notifications and then forwards them to an {@link EventReceiver} object.

    - * - *

    A {@code fetchExecutor} parameter can be specified when creating a - * {@code FetchingEventRelay}. That is then the {@code Executor} that will - * be used to perform the {@code fetchNotifications} operation. Only one - * job at a time will be submitted to this {@code Executor}. The behavior - * is unspecified if {@link Executor#execute} throws an exception, including - * {@link java.util.concurrent.RejectedExecutionException - * RejectedExecutionException}. - * - * @since JMX 2.0 - */ -public class FetchingEventRelay implements EventRelay { - /** - * The default buffer size: {@value #DEFAULT_BUFFER_SIZE}. - */ - public final static int DEFAULT_BUFFER_SIZE = 1000; - - /** - * The default waiting timeout: {@value #DEFAULT_WAITING_TIMEOUT} - * in millseconds when fetching notifications from - * an {@code EventClientDelegateMBean}. - */ - public final static long DEFAULT_WAITING_TIMEOUT = 60000; - - /** - * The default maximum notifications to fetch every time: - * {@value #DEFAULT_MAX_NOTIFICATIONS}. - */ - public final static int DEFAULT_MAX_NOTIFICATIONS = DEFAULT_BUFFER_SIZE; - - /** - * Constructs a default {@code FetchingEventRelay} object by using the default - * configuration: {@code DEFAULT_BUFFER_SIZE}, {@code DEFAULT_WAITING_TIMEOUT} - * {@code DEFAULT_MAX_NOTIFICATIONS}. A single thread is created - * to do fetching. - * - * @param delegate The {@code EventClientDelegateMBean} to work with. - * @throws IOException If failed to work with the {@code delegate}. - * @throws MBeanException if unable to add a client to the remote - * {@code EventClientDelegateMBean} (see {@link - * EventClientDelegateMBean#addClient(String, Object[], String[]) - * EventClientDelegateMBean.addClient}). - * @throws IllegalArgumentException If {@code delegate} is {@code null}. - */ - public FetchingEventRelay(EventClientDelegateMBean delegate) - throws IOException, MBeanException { - this(delegate, null); - } - - /** - * Constructs a {@code FetchingEventRelay} object by using the default - * configuration: {@code DEFAULT_BUFFER_SIZE}, {@code DEFAULT_WAITING_TIMEOUT} - * {@code DEFAULT_MAX_NOTIFICATIONS}, with a user-specific executor to do - * the fetching. - * - * @param delegate The {@code EventClientDelegateMBean} to work with. - * @param fetchExecutor Used to do the fetching. A new thread is created if - * {@code null}. - * @throws IOException If failed to work with the {@code delegate}. - * @throws MBeanException if unable to add a client to the remote - * {@code EventClientDelegateMBean} (see {@link - * EventClientDelegateMBean#addClient(String, Object[], String[]) - * EventClientDelegateMBean.addClient}). - * @throws IllegalArgumentException If {@code delegate} is {@code null}. - */ - public FetchingEventRelay(EventClientDelegateMBean delegate, - Executor fetchExecutor) throws IOException, MBeanException { - this(delegate, - DEFAULT_BUFFER_SIZE, - DEFAULT_WAITING_TIMEOUT, - DEFAULT_MAX_NOTIFICATIONS, - fetchExecutor); - } - - /** - * Constructs a {@code FetchingEventRelay} object with user-specific - * configuration and executor to fetch notifications via the - * {@link EventClientDelegateMBean}. - * - * @param delegate The {@code EventClientDelegateMBean} to work with. - * @param bufferSize The buffer size for saving notifications in - * {@link EventClientDelegateMBean} before they are fetched. - * @param timeout The waiting time in millseconds when fetching - * notifications from an {@code EventClientDelegateMBean}. - * @param maxNotifs The maximum notifications to fetch every time. - * @param fetchExecutor Used to do the fetching. A new thread is created if - * {@code null}. - * @throws IOException if failed to communicate with the {@code delegate}. - * @throws MBeanException if unable to add a client to the remote - * {@code EventClientDelegateMBean} (see {@link - * EventClientDelegateMBean#addClient(String, Object[], String[]) - * EventClientDelegateMBean.addClient}). - * @throws IllegalArgumentException If {@code delegate} is {@code null}. - */ - public FetchingEventRelay(EventClientDelegateMBean delegate, - int bufferSize, - long timeout, - int maxNotifs, - Executor fetchExecutor) throws IOException, MBeanException { - this(delegate, - bufferSize, - timeout, - maxNotifs, - fetchExecutor, - FetchingEventForwarder.class.getName(), - new Object[] {bufferSize}, - new String[] {int.class.getName()}); - } - - /** - * Constructs a {@code FetchingEventRelay} object with user-specific - * configuration and executor to fetch notifications via the - * {@link EventClientDelegateMBean}. - * - * @param delegate The {@code EventClientDelegateMBean} to work with. - * @param bufferSize The buffer size for saving notifications in - * {@link EventClientDelegateMBean} before they are fetched. - * @param timeout The waiting time in millseconds when fetching - * notifications from an {@code EventClientDelegateMBean}. - * @param maxNotifs The maximum notifications to fetch every time. - * @param fetchExecutor Used to do the fetching. - * @param forwarderName the class name of a user specific EventForwarder - * to create in server to forward notifications to this object. The class - * should be a subclass of the class {@link FetchingEventForwarder}. - * @param params the parameters passed to create {@code forwarderName} - * @param sig the signature of the {@code params} - * @throws IOException if failed to communicate with the {@code delegate}. - * @throws MBeanException if unable to add a client to the remote - * {@code EventClientDelegateMBean} (see {@link - * EventClientDelegateMBean#addClient(String, Object[], String[]) - * EventClientDelegateMBean.addClient}). - * @throws IllegalArgumentException if {@code bufferSize} or - * {@code maxNotifs} is less than {@code 1} - * @throws NullPointerException if {@code delegate} is {@code null}. - */ - public FetchingEventRelay(EventClientDelegateMBean delegate, - int bufferSize, - long timeout, - int maxNotifs, - Executor fetchExecutor, - String forwarderName, - Object[] params, - String[] sig) throws IOException, MBeanException { - - if (logger.traceOn()) { - logger.trace("FetchingEventRelay", "delegateMBean "+ - bufferSize+" "+ - timeout+" "+ - maxNotifs+" "+ - fetchExecutor+" "+ - forwarderName+" "); - } - - if (delegate == null) { - throw new NullPointerException("Null EventClientDelegateMBean!"); - } - - - if (bufferSize<=1) { - throw new IllegalArgumentException( - "The bufferSize cannot be less than 1, no meaning."); - } - - if (maxNotifs<=1) { - throw new IllegalArgumentException( - "The maxNotifs cannot be less than 1, no meaning."); - } - - clientId = delegate.addClient( - forwarderName, - params, - sig); - - this.delegate = delegate; - this.timeout = timeout; - this.maxNotifs = maxNotifs; - - if (fetchExecutor == null) { - ScheduledThreadPoolExecutor executor = - new ScheduledThreadPoolExecutor(1, daemonThreadFactory); - executor.setKeepAliveTime(1, TimeUnit.SECONDS); - executor.allowCoreThreadTimeOut(true); - fetchExecutor = executor; - this.defaultExecutor = executor; - } else - this.defaultExecutor = null; - this.fetchExecutor = fetchExecutor; - - startSequenceNumber = 0; - fetchingJob = new MyJob(); - } - - public synchronized void setEventReceiver(EventReceiver eventReceiver) { - if (logger.traceOn()) { - logger.trace("setEventReceiver", ""+eventReceiver); - } - - EventReceiver old = this.eventReceiver; - this.eventReceiver = eventReceiver; - if (old == null && eventReceiver != null) - fetchingJob.resume(); - } - - public String getClientId() { - return clientId; - } - - public synchronized void stop() { - if (logger.traceOn()) { - logger.trace("stop", ""); - } - if (stopped) { - return; - } - - stopped = true; - clientId = null; - if (defaultExecutor != null) - defaultExecutor.shutdown(); - } - - private class MyJob extends RepeatedSingletonJob { - public MyJob() { - super(fetchExecutor); - } - - public boolean isSuspended() { - boolean b; - synchronized(FetchingEventRelay.this) { - b = stopped || - (eventReceiver == null) || - (clientId == null); - } - - if (logger.traceOn()) { - logger.trace("-MyJob-isSuspended", ""+b); - } - return b; - } - - public void task() { - logger.trace("MyJob-task", ""); - long fetchTimeout = timeout; - NotificationResult nr = null; - Throwable failedExcep = null; - try { - nr = delegate.fetchNotifications( - clientId, - startSequenceNumber, - maxNotifs, - fetchTimeout); - } catch (Exception e) { - if (isSerialOrClassNotFound(e)) { - try { - nr = fetchOne(); - } catch (Exception ee) { - failedExcep = e; - } - } else { - failedExcep = e; - } - } - - if (failedExcep != null && - !isSuspended()) { - logger.fine("MyJob-task", - "Failed to fetch notification, stopping...", failedExcep); - try { - eventReceiver.failed(failedExcep); - } catch (Exception e) { - logger.trace( - "MyJob-task", "exception from eventReceiver.failed", e); - } - - stop(); - } else if (nr != null) { - try { - eventReceiver.receive(nr); - } catch (RuntimeException e) { - logger.trace( - "MyJob-task", - "exception delivering notifs to EventClient", e); - } finally { - startSequenceNumber = nr.getNextSequenceNumber(); - } - } - } - } - - private NotificationResult fetchOne() throws Exception { - logger.trace("fetchOne", ""); - - while (true) { - try { - // 1 notif to skip possible missing class - return delegate.fetchNotifications( - clientId, - startSequenceNumber, - 1, - timeout); - } catch (Exception e) { - if (isSerialOrClassNotFound(e)) { // skip and continue - if (logger.traceOn()) { - logger.trace("fetchOne", "Ignore", e); - } - eventReceiver.nonFatal(e); - startSequenceNumber++; - } else { - throw e; - } - } - } - } - - static boolean isSerialOrClassNotFound(Exception e) { - Throwable cause = e.getCause(); - - while (cause != null && - !(cause instanceof ClassNotFoundException) && - !(cause instanceof NotSerializableException)) { - cause = cause.getCause(); - } - - return (cause instanceof ClassNotFoundException || - cause instanceof NotSerializableException); - } - - private long startSequenceNumber = 0; - private EventReceiver eventReceiver = null; - private final EventClientDelegateMBean delegate; - private String clientId; - private boolean stopped = false; - - private final Executor fetchExecutor; - private final ExecutorService defaultExecutor; - private final MyJob fetchingJob; - - private final long timeout; - private final int maxNotifs; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", - "FetchingEventRelay"); - private static final ThreadFactory daemonThreadFactory = - new DaemonThreadFactory("JMX FetchingEventRelay executor %d"); -} diff --git a/src/share/classes/javax/management/event/ListenerInfo.java b/src/share/classes/javax/management/event/ListenerInfo.java deleted file mode 100644 index 9c7a8fc59..000000000 --- a/src/share/classes/javax/management/event/ListenerInfo.java +++ /dev/null @@ -1,169 +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 javax.management.event; - -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; - -/** - * This class specifies all the information required to register a user listener into - * a remote MBean server. This class is not serializable because a user listener - * is not serialized in order to be sent to the remote server. - * - * @since JMX 2.0 - */ -public class ListenerInfo { - - /** - * Constructs a {@code ListenerInfo} object. - * - * @param name The name of the MBean to which the listener should - * be added. - * @param listener The listener object which will handle the - * notifications emitted by the MBean. - * @param filter The filter object. If the filter is null, no - * filtering will be performed before notifications are handled. - * @param handback The context to be sent to the listener when a - * notification is emitted. - * @param isSubscription If true, the listener is subscribed via - * an {@code EventManager}. Otherwise it is added to a registered MBean. - */ - public ListenerInfo(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback, - boolean isSubscription) { - this.name = name; - this.listener = listener; - this.filter = filter; - this.handback = handback; - this.isSubscription = isSubscription; - } - - /** - * Returns an MBean or an MBean pattern that the listener listens to. - * - * @return An MBean or an MBean pattern. - */ - public ObjectName getObjectName() { - return name; - } - - /** - * Returns the listener. - * - * @return The listener. - */ - public NotificationListener getListener() { - return listener; - } - - /** - * Returns the listener filter. - * - * @return The filter. - */ - public NotificationFilter getFilter() { - return filter; - } - - /** - * Returns the listener handback. - * - * @return The handback. - */ - public Object getHandback() { - return handback; - } - - /** - * Returns true if this is a subscription listener. - * - * @return True if this is a subscription listener. - * - * @see EventClient#addListeners - */ - public boolean isSubscription() { - return isSubscription; - } - - /** - *

    Indicates whether some other object is "equal to" this one. - * The return value is true if and only if {@code o} is an instance of - * {@code ListenerInfo} and has equal values for all of its properties.

    - */ - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof ListenerInfo)) { - return false; - } - - ListenerInfo li = (ListenerInfo)o; - - boolean ret = name.equals(li.name) && - (listener == li.listener) && - (isSubscription == li.isSubscription); - - if (filter != null) { - ret &= filter.equals(li.filter); - } else { - ret &= (li.filter == null); - } - - if (handback != null) { - ret &= handback.equals(li.handback); - } else { - ret &= (li.handback == null); - } - - return ret; - } - - @Override - public int hashCode() { - return name.hashCode() + listener.hashCode(); - } - - @Override - public String toString() { - return name.toString() + "_" + - listener + "_" + - filter + "_" + - handback + "_" + - isSubscription; - } - - private final ObjectName name; - private final NotificationListener listener; - private final NotificationFilter filter; - private final Object handback; - private final boolean isSubscription; -} diff --git a/src/share/classes/javax/management/event/NotificationManager.java b/src/share/classes/javax/management/event/NotificationManager.java deleted file mode 100644 index 89edf9ba9..000000000 --- a/src/share/classes/javax/management/event/NotificationManager.java +++ /dev/null @@ -1,136 +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 javax.management.event; - -import java.io.IOException; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; - -/** - * This interface specifies methods to add and remove notification listeners - * on named MBeans. - */ -public interface NotificationManager { - /** - *

    Adds a listener to a registered MBean. - * Notifications emitted by the MBean will be forwarded - * to the listener. - * - * @param name The name of the MBean on which the listener should - * be added. - * @param listener The listener object which will handle the - * notifications emitted by the registered MBean. - * @param filter The filter object. If filter is null, no - * filtering will be performed before handling notifications. - * @param handback The context to be sent to the listener when a - * notification is emitted. - * - * @exception InstanceNotFoundException The MBean name provided - * does not match any of the registered MBeans. - * @exception IOException A communication problem occurred when - * talking to the MBean server. - * - * @see #removeNotificationListener(ObjectName, NotificationListener) - * @see #removeNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) - */ - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - IOException; - - /** - *

    Removes a listener from a registered MBean.

    - * - *

    If the listener is registered more than once, perhaps with - * different filters or callbacks, this method will remove all - * those registrations. - * - * @param name The name of the MBean on which the listener should - * be removed. - * @param listener The listener to be removed. - * - * @exception InstanceNotFoundException The MBean name provided - * does not match any of the registered MBeans. - * @exception ListenerNotFoundException The listener is not - * registered in the MBean. - * @exception IOException A communication problem occurred when - * talking to the MBean server. - * - * @see #addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, - ListenerNotFoundException, - IOException; - - /** - *

    Removes a listener from a registered MBean.

    - * - *

    The MBean must have a listener that exactly matches the - * given listener, filter, and - * handback parameters. If there is more than one - * such listener, only one is removed.

    - * - *

    The filter and handback parameters - * may be null if and only if they are null in a listener to be - * removed.

    - * - * @param name The name of the MBean on which the listener should - * be removed. - * @param listener The listener to be removed. - * @param filter The filter that was specified when the listener - * was added. - * @param handback The handback that was specified when the - * listener was added. - * - * @exception InstanceNotFoundException The MBean name provided - * does not match any of the registered MBeans. - * @exception ListenerNotFoundException The listener is not - * registered in the MBean, or it is not registered with the given - * filter and handback. - * @exception IOException A communication problem occurred when - * talking to the MBean server. - * - * @see #addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) - * - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, - ListenerNotFoundException, - IOException; -} diff --git a/src/share/classes/javax/management/event/RMIPushEventForwarder.java b/src/share/classes/javax/management/event/RMIPushEventForwarder.java deleted file mode 100644 index 636f2e57a..000000000 --- a/src/share/classes/javax/management/event/RMIPushEventForwarder.java +++ /dev/null @@ -1,198 +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 javax.management.event; - -import com.sun.jmx.event.DaemonThreadFactory; -import com.sun.jmx.event.RepeatedSingletonJob; -import com.sun.jmx.remote.util.ClassLogger; -import java.rmi.RemoteException; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.management.Notification; -import javax.management.remote.NotificationResult; -import javax.management.remote.TargetedNotification; - - -/** - * This class is used by {@link RMIPushEventRelay}. When - * {@link RMIPushEventRelay} calls {@link - * EventClientDelegateMBean#addClient(String, Object[], String[])} to get a new - * client identifier, it uses this class name as the - * first argument to ask {@code EventClientDelegateMBean} to create an object of - * this class. - * Then {@code EventClientDelegateMBean} forwards client notifications - * to this object. This object then continues forwarding the notifications - * to the {@code RMIPushEventRelay}. - */ -public class RMIPushEventForwarder implements EventForwarder { - private static final int DEFAULT_BUFFER_SIZE = 6000; - - /** - * Creates a new instance of {@code RMIPushEventForwarder}. - * - * @param receiver An RMI stub exported to receive notifications - * from this object for its {@link RMIPushEventRelay}. - * - * @param bufferSize The maximum number of notifications to store - * while waiting for the last remote send to complete. - */ - public RMIPushEventForwarder(RMIPushServer receiver, int bufferSize) { - if (logger.traceOn()) { - logger.trace("RMIEventForwarder", "new one"); - } - - if (bufferSize < 0) { - throw new IllegalArgumentException( - "Negative buffer size: " + bufferSize); - } else if (bufferSize == 0) - bufferSize = DEFAULT_BUFFER_SIZE; - - if (receiver == null) { - throw new NullPointerException(); - } - - this.receiver = receiver; - this.buffer = new ArrayBlockingQueue(bufferSize); - } - - public void forward(Notification n, Integer listenerId) { - if (logger.traceOn()) { - logger.trace("forward", "to the listener: "+listenerId); - } - synchronized(sendingJob) { - TargetedNotification tn = new TargetedNotification(n, listenerId); - while (!buffer.offer(tn)) { - buffer.remove(); - passed++; - } - sendingJob.resume(); - } - } - - public void close() { - if (logger.traceOn()) { - logger.trace("close", "called"); - } - - synchronized(sendingJob) { - ended = true; - buffer.clear(); - } - } - - public void setClientId(String clientId) { - if (logger.traceOn()) { - logger.trace("setClientId", clientId); - } - } - - private class SendingJob extends RepeatedSingletonJob { - public SendingJob() { - super(executor); - } - - public boolean isSuspended() { - return ended || buffer.isEmpty(); - } - - public void task() { - final long earliest = passed; - - List tns = - new ArrayList(buffer.size()); - synchronized(sendingJob) { - buffer.drainTo(tns); - passed += tns.size(); - } - - if (logger.traceOn()) { - logger.trace("SendingJob-task", "sending: "+tns.size()); - } - - if (!tns.isEmpty()) { - try { - TargetedNotification[] tnArray = - new TargetedNotification[tns.size()]; - tns.toArray(tnArray); - receiver.receive(new NotificationResult(earliest, passed, tnArray)); - } catch (RemoteException e) { - if (logger.debugOn()) { - logger.debug("SendingJob-task", - "Got exception to forward notifs.", e); - } - - long currentLost = passed - earliest; - if (FetchingEventRelay.isSerialOrClassNotFound(e)) { - // send one by one - long tmpPassed = earliest; - for (TargetedNotification tn : tns) { - try { - receiver.receive(new NotificationResult(earliest, - ++tmpPassed, new TargetedNotification[]{tn})); - } catch (RemoteException ioee) { - logger.trace( - "SendingJob-task", "send to remote", ioee); - // sends nonFatal notifs? - } - } - - currentLost = passed - tmpPassed; - } - - if (currentLost > 0) { // inform of the lost. - try { - receiver.receive(new NotificationResult( - passed, passed, - new TargetedNotification[]{})); - } catch (RemoteException ee) { - logger.trace( - "SendingJob-task", "receiver.receive", ee); - } - } - } - } - } - } - - private long passed = 0; - - private static final ExecutorService executor = - Executors.newCachedThreadPool( - new DaemonThreadFactory("JMX RMIEventForwarder Executor")); - private final SendingJob sendingJob = new SendingJob(); - - private final BlockingQueue buffer; - - private final RMIPushServer receiver; - private boolean ended = false; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "RMIEventForwarder"); -} diff --git a/src/share/classes/javax/management/event/RMIPushEventRelay.java b/src/share/classes/javax/management/event/RMIPushEventRelay.java deleted file mode 100644 index 1cc550955..000000000 --- a/src/share/classes/javax/management/event/RMIPushEventRelay.java +++ /dev/null @@ -1,161 +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 javax.management.event; - -import com.sun.jmx.remote.util.ClassLogger; -import java.io.IOException; -import java.rmi.NoSuchObjectException; -import java.rmi.RemoteException; -import java.rmi.server.UnicastRemoteObject; -import java.rmi.server.RMIClientSocketFactory; -import java.rmi.server.RMIServerSocketFactory; -import javax.management.MBeanException; -import javax.management.remote.NotificationResult; - -/** - * This class is an implementation of the {@link EventRelay} interface, using - * push mode. It exports an RMI object that {@link RMIPushEventForwarder} uses - * to forward notifications. - * - * @since JMX 2.0 - */ -public class RMIPushEventRelay implements EventRelay { - /** - * Constructs a default {@code RMIPushEventRelay} object - * and exports its {@linkplain RMIPushServer notification - * receiver} on any free port. This constructor is equivalent - * to {@link #RMIPushEventRelay(EventClientDelegateMBean, - * int, RMIClientSocketFactory, RMIServerSocketFactory, int) - * RMIPushEventRelay(delegate, 0, null, null, <default buffer - * size>)}. - * - * @param delegate The {@link EventClientDelegateMBean} proxy to work with. - * @throws IOException if failed to communicate with - * {@link EventClientDelegateMBean}. - * @throws MBeanException if the {@link EventClientDelegateMBean} failed - * to create an {@code EventForwarder} for this object. - */ - public RMIPushEventRelay(EventClientDelegateMBean delegate) - throws IOException, MBeanException { - this(delegate, 0, null, null, 0); - } - - /** - * Constructs a {@code RMIPushEventRelay} object and exports its - * {@linkplain RMIPushServer notification receiver} on a specified port. - * - * @param delegate The {@link EventClientDelegateMBean} proxy to work with. - * @param port The port used to export an RMI object to receive notifications - * from a server. If the port is zero, an anonymous port is used. - * @param csf The client socket factory used to export the RMI object. - * Can be null. - * @param ssf The server socket factory used to export the RMI object. - * Can be null. - * @param bufferSize The number of notifications held on the server - * while waiting for the previous transmission to complete. A value of - * zero means the default buffer size. - * - * @throws IOException if failed to communicate with - * {@link EventClientDelegateMBean}. - * @throws MBeanException if the {@link EventClientDelegateMBean} failed - * to create an {@code EventForwarder} for this object. - * - * @see RMIPushEventForwarder#RMIPushEventForwarder(RMIPushServer, int) - */ - public RMIPushEventRelay(EventClientDelegateMBean delegate, - int port, - RMIClientSocketFactory csf, - RMIServerSocketFactory ssf, - int bufferSize) - throws IOException, MBeanException { - - UnicastRemoteObject.exportObject(exportedReceiver, port, csf, ssf); - - clientId = delegate.addClient( - RMIPushEventForwarder.class.getName(), - new Object[] {exportedReceiver, bufferSize}, - new String[] {RMIPushServer.class.getName(), - int.class.getName()}); - } - - public String getClientId() { - return clientId; - } - - public void setEventReceiver(EventReceiver receiver) { - if (logger.traceOn()) { - logger.trace("setEventReceiver", ""+receiver); - } - synchronized(lock) { - this.receiver = receiver; - } - } - - public void stop() { - if (logger.traceOn()) { - logger.trace("stop", ""); - } - synchronized(lock) { - if (stopped) { - return; - } else { - stopped = true; - } - - if (clientId == null) { - return; - } - - try { - UnicastRemoteObject.unexportObject(exportedReceiver, true); - } catch (NoSuchObjectException nsoe) { - logger.fine("RMIPushEventRelay.stop", "unexport", nsoe); - // OK: we wanted it unexported, and apparently it already is - } - } - } - - private volatile String clientId; - private volatile EventReceiver receiver; - - private RMIPushServer exportedReceiver = new RMIPushServer() { - public void receive(NotificationResult nr) throws RemoteException { - if (logger.traceOn()) { - logger.trace("EventPusherImpl-receive",""); - } - receiver.receive(nr); - // Any exception will be sent back to the client. - } - }; - - private boolean stopped = false; - - private final int[] lock = new int[0]; - - private static final ClassLogger logger = - new ClassLogger("javax.management.event", - "PushEventRelay"); -} diff --git a/src/share/classes/javax/management/event/RMIPushServer.java b/src/share/classes/javax/management/event/RMIPushServer.java deleted file mode 100644 index 253498459..000000000 --- a/src/share/classes/javax/management/event/RMIPushServer.java +++ /dev/null @@ -1,48 +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 javax.management.event; - -import java.rmi.Remote; -import java.rmi.RemoteException; -import javax.management.remote.NotificationResult; - -/** - * The {@link RMIPushEventRelay} exports an RMI object of this class and - * sends a client stub for that object to the associated - * {@link RMIPushEventForwarder} in a remote MBean server. The - * {@code RMIPushEventForwarder} then sends notifications to the - * RMI object. - */ -public interface RMIPushServer extends Remote { - /** - *

    Dispatch the notifications in {@code nr} to the {@link RMIPushEventRelay} - * associated with this object.

    - * @param nr the notification result to dispatch. - * @throws java.rmi.RemoteException if the remote invocation of this method - * failed. - */ - public void receive(NotificationResult nr) throws RemoteException; -} diff --git a/src/share/classes/javax/management/event/package-info.java b/src/share/classes/javax/management/event/package-info.java deleted file mode 100644 index 728b09513..000000000 --- a/src/share/classes/javax/management/event/package-info.java +++ /dev/null @@ -1,312 +0,0 @@ -/** - *

    Defines the Event Service, which provides extended support - * for JMX notifications.

    - * - *

    The Event Service provides greater control over - * notification handling than the default technique using {@link - * javax.management.MBeanServer#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object) - * MBeanServer.addNotificationListener} or {@link - * javax.management.MBeanServerConnection#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object) - * MBeanServerConnection.addNotificationListener}.

    - * - *

    Here are some reasons you may want to use the Event Service:

    - * - *
      - *
    • To receive notifications from a set of MBeans defined by an - * ObjectName pattern, such as {@code com.example.config:type=Cache,*}. - * - *
    • When the notification-handling behavior of the connector you are - * using does not match your requirements. For example, with the standard - * RMI connector you can lose notifications if there are very many of them - * in the MBean Server you are connected to, even if you are only listening - * for a small proportion of them. - * - *
    • To change the threading behavior of notification dispatch. - * - *
    • To define a different transport for notifications, for example to - * arrange for them to be delivered through the Java Message Service (JMS). The Event Service comes with - * one alternative transport as standard, a "push-mode" RMI transport. - * - *
    • To handle notifications on behalf of MBeans (often virtual) in a - * namespace. - *
    - * - *

    The Event Service is new in version 2.0 of the JMX API, which is the - * version introduced in version 7 of the Java SE platform. It is not usually - * possible to use the Event Service when connecting remotely to an - * MBean Server that is running an earlier version.

    - * - * - *

    Handling remote notifications with the Event - * Service

    - * - *

    Prior to version 2.0 of the JMX API, every connector - * had to include logic to handle notifications. The standard {@linkplain - * javax.management.remote.rmi RMI} and JMXMP connectors defined by JSR 160 handle notifications - * in a way that is not always appropriate for applications. Specifically, - * the connector server adds one listener to every MBean that might emit - * notifications, and adds all received notifications to a fixed-size - * buffer. This means that if there are very many notifications, a - * remote client may miss some, even if it is only registered for a - * very small subset of notifications. Furthermore, since every {@link - * javax.management.NotificationBroadcaster NotificationBroadcaster} MBean - * gets a listener from the connector server, MBeans cannot usefully optimize - * by only sending notifications when there is a listener. Finally, since - * the connector server uses just one listener per MBean, MBeans cannot - * impose custom behavior per listener, such as security checks or localized - * notifications.

    - * - *

    The Event Service does not have these restrictions. The RMI connector - * that is included in this version of the JMX API uses the Event Service by - * default, although it can be configured to have the previous behavior if - * required.

    - * - *

    The Event Service can be used with any connector via the - * method {@link javax.management.event.EventClient#getEventClientConnection - * EventClient.getEventClientConnection}, like this:

    - * - *
    - * JMXConnector conn = ...;
    - * MBeanServerConnection mbsc = conn.getMBeanServerConnection();
    - * MBeanServerConnection eventMbsc = EventClient.getEventClientConnection(mbsc);
    - * 
    - * - *

    If you add listeners using {@code eventMbsc.addNotificationListener} - * instead of {@code mbsc.addNotificationListener}, then they will be handled - * by the Event Service rather than by the connector's notification system.

    - * - *

    For the Event Service to work, either the {@link - * javax.management.event.EventClientDelegateMBean EventClientDelegateMBean} - * must be registered in the MBean Server, or the connector server must - * be configured to simulate the existence of this MBean, for example - * using {@link javax.management.event.EventClientDelegate#newForwarder - * EventClientDelegate.newForwarder}. The standard RMI connector is so - * configured by default. The {@code EventClientDelegateMBean} documentation - * has further details.

    - * - * - *

    Receiving notifications from a set of MBeans

    - * - *

    The Event Server allows you to receive notifications from every MBean - * that matches an {@link javax.management.ObjectName ObjectName} pattern. - * For local clients (in the same JVM as the MBean Server), the {@link - * javax.management.event.EventSubscriber EventSubscriber} class can be used for - * this. For remote clients, or if the same code is to be used locally and - * remotely, use an - * {@link javax.management.event.EventClient EventClient}.

    - * - *

    EventSubscriber and EventClient correctly handle the case where a new - * MBean is registered under a name that matches the pattern. Notifications - * from the new MBean will also be received.

    - * - *

    Here is how to receive notifications from all MBeans in a local - * {@code MBeanServer} that match {@code com.example.config:type=Cache,*}:

    - * - *
    - * MBeanServer mbs = ...;
    - * NotificationListener listener = ...;
    - * ObjectName pattern = new ObjectName("com.example.config:type=Cache,*");
    - * EventSubscriber esub = EventSubscriber.getEventSubscriber(mbs);
    - * esub.{@link javax.management.event.EventSubscriber#subscribe
    - * subscribe}(pattern, listener, null, null);
    - * 
    - * - *

    Here is how to do the same thing remotely:

    - * - *
    - * MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
    - * EventClient events = new EventClient(mbsc);
    - * NotificationListener listener = ...;
    - * ObjectName pattern = new ObjectName("com.example.config:type=Cache,*");
    - * events.{@link javax.management.event.EventClient#subscribe
    - * subscribe}(pattern, listener, null, null);
    - * 
    - * - * - *

    Controlling threading behavior for notification - * dispatch

    - * - *

    The EventClient class can be used to control threading of listener - * dispatch. For example, to arrange for all listeners to be invoked - * in the same thread, you can create an {@code EventClient} like this:

    - * - *
    - * MBeanServerConnection mbsc = ...;
    - * Executor singleThreadExecutor = {@link
    - * java.util.concurrent.Executors#newSingleThreadExecutor()
    - * Executors.newSingleThreadExecutor}();
    - * EventClient events = new EventClient(
    - *         mbsc, null, singleThreadExecutor, EventClient.DEFAULT_LEASE_TIMEOUT);
    - * events.addNotificationListener(...);
    - * events.subscribe(...);
    - * 
    - * - * - *

    Leasing

    - * - *

    The {@code EventClient} uses a lease mechanism to ensure - * that resources are eventually released on the server even if the client - * does not explicitly clean up. (This can happen through network - * partitioning, for example.)

    - * - *

    When an {@code EventClient} registers with the {@code - * EventClientDelegateMBean} using one of the {@code addClient} methods, - * an initial lease is created with a default expiry time. The {@code - * EventClient} requests an explicit lease shortly after that, with a - * configurable expiry time. Then the {@code EventClient} periodically - * renews the lease before it expires, typically about half way - * through the lifetime of the lease. If at any point the lease reaches - * the expiry time of the last renewal then it expires, and {@code - * EventClient} is unregistered as if it had called the {@link - * javax.management.event.EventClientDelegateMBean#removeClient removeClient} - * method.

    - * - * - *

    Custom notification transports

    - * - *

    When you create an {@code EventClient}, you can define the transport - * that it uses to deliver notifications. The transport might use the - * Java Message Service (JMS) or - * any other communication system. Specifying a transport is useful for - * example when you want different network behavior from the default, or - * different reliability guarantees. The default transport calls {@link - * javax.management.event.EventClientDelegateMBean#fetchNotifications - * EventClientDelegateMBean.fetchNotifications} repeatedly, which usually means - * that there must be a network connection permanently open between the client - * and the server. If the same client is connected to many servers this can - * cause scalability problems. If notifications are relatively rare, then - * JMS or the {@linkplain javax.management.event.RMIPushEventRelay push-mode - * RMI transport} may be more suitable.

    - * - *

    A transport is implemented by an {@link javax.management.event.EventRelay - * EventRelay} on the client side and a corresponding {@link - * javax.management.event.EventForwarder EventForwarder} - * on the server side. An example is the {@link - * javax.management.event.RMIPushEventRelay RMIPushEventRelay} and its - * {@link javax.management.event.RMIPushEventForwarder RMIPushEventForwarder}.

    - * - *

    To use a given transport with an {@code EventClient}, you first create - * an instance of its {@code EventRelay}. Typically the {@code EventRelay}'s - * constructor will have a parameter of type {@code MBeanServerConnection} - * or {@code EventClientDelegateMBean}, so that it can communicate with the - * {@code EventClientDelegateMBean} in the server. For example, the {@link - * javax.management.event.RMIPushEventForwarder RMIPushEventForwarder}'s constructors - * all take an {@code EventClientDelegateMBean} parameter, which is expected to - * be a {@linkplain javax.management.JMX#newMBeanProxy(MBeanServerConnection, - * ObjectName, Class) proxy} for the {@code EventClientDelegateMBean} in the - * server.

    - * - *

    When it is created, the {@code EventRelay} will call - * {@link javax.management.event.EventClientDelegateMBean#addClient(String, - * Object[], String[]) EventClientDelegateMBean.addClient}. It passes the - * name of the {@code EventForwarder} class and its constructor parameters. - * The {@code EventClientDelegateMBean} will instantiate this class using - * {@link javax.management.MBeanServer#instantiate(String, Object[], String[]) - * MBeanServer.instantiate}, and it will return a unique client id.

    - * - *

    Then you pass the newly-created {@code EventRelay} to one of the {@code - * EventClient} constructors, and you have an {@code EventClient} that uses the - * chosen transport.

    - * - *

    For example, when you create an {@code RMIPushEventRelay}, it - * uses {@code MBeanServerDelegateMBean.addClient} to create an {@code - * RMIEventForwarder} in the server. Notifications will then be delivered - * through an RMI communication from the {@code RMIEventForwarder} to the - * {@code RMIPushEventRelay}.

    - * - * - *

    Writing a custom transport

    - * - *

    To write a custom transport, you need to understand the sequence - * of events when an {@code EventRelay} and its corresponding {@code - * EventForwarder} are created, and when a notification is sent from the {@code - * EventForwarder} to the {@code EventRelay}.

    - * - *

    When an {@code EventRelay} is created:

    - * - *
      - *
    • The {@code EventRelay} must call {@code - * EventClientDelegateMBean.addClient} with the name of the {@code - * EventForwarder} and the constructor parameters.

      - * - *
    • {@code EventClientDelegateMBean.addClient} will do the following - * steps:

      - * - *
        - *
      • create the {@code EventForwarder} using {@code MBeanServer.instantiate}; - *
      • allocate a unique client id; - *
      • call the new {@code EventForwarder}'s {@link - * javax.management.event.EventForwarder#setClientId setClientId} method with - * the new client id; - *
      • return the client id to the caller. - *
      - * - *
    - * - *

    When an {@code EventClient} is created with an {@code EventRelay} - * parameter, it calls {@link javax.management.event.EventRelay#setEventReceiver - * EventRelay.setEventReceiver} with an {@code EventReceiver} that the - * {@code EventRelay} will use to deliver notifications.

    - * - *

    When a listener is added using the {@code EventClient}, the - * {@code EventRelay} and {@code EventForwarder} are not involved.

    - * - *

    When an MBean emits a notification and a listener has been added - * to that MBean using the {@code EventClient}:

    - * - *
      - *
    • The {@code EventForwarder}'s - * {@link javax.management.event.EventForwarder#forward forward} method - * is called with the notification and a listener id.

      - * - *
    • The {@code EventForwarder} sends the notification and listener id - * to the {@code EventRelay} using the custom transport.

      - * - *
    • The {@code EventRelay} delivers the notification by calling - * {@link javax.management.event.EventReceiver#receive EventReceiver.receive}.

      - *
    - * - *

    When the {@code EventClient} is closed ({@link - * javax.management.event.EventClient#close EventClient.close}):

    - * - *
      - *
    • The {@code EventClient} calls {@link - * javax.management.event.EventRelay#stop EventRelay.stop}.

      - * - *
    • The {@code EventClient} calls {@link - * javax.management.event.EventClientDelegateMBean#removeClient - * EventClientDelegateMBean.removeClient}.

      - * - *
    • The {@code EventClientDelegateMBean} removes any listeners it - * had added on behalf of this {@code EventClient}.

      - * - *
    • The {@code EventClientDelegateMBean} calls - * {@link javax.management.event.EventForwarder#close EventForwarder.close}.

      - *
    - * - * - *

    Threading and buffering

    - * - *

    The {@link javax.management.event.EventForwarder#forward - * EventForwarder.forward} method may be called in the thread that the - * source MBean is using to send its notification. MBeans can expect - * that notification sending does not block. Therefore a {@code forward} - * method will typically add the notification to a queue, with a separate - * thread that takes notifications off the queue and sends them.

    - * - *

    An {@code EventRelay} does not usually need to buffer notifications - * before giving them to - * {@link javax.management.event.EventReceiver#receive EventReceiver.receive}. - * Although by default each such notification will be sent to potentially-slow - * listeners, if this is a problem then an {@code Executor} can be given to - * the {@code EventClient} constructor to cause the listeners to be called - * in a different thread.

    - * - * @since 1.7 - */ - -package javax.management.event; diff --git a/src/share/classes/javax/management/modelmbean/DescriptorSupport.java b/src/share/classes/javax/management/modelmbean/DescriptorSupport.java index aa364c226..ee8e3030e 100644 --- a/src/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/src/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -229,10 +229,9 @@ public class DescriptorSupport init(inDescr.descriptorMap); } + /** - *

    Descriptor constructor taking an XML String or a - * fieldName=fieldValue format String. The String parameter is - * parsed as XML if it begins with a '<' character.

    + *

    Descriptor constructor taking an XML String.

    * *

    The format of the XML string is not defined, but an * implementation must ensure that the string returned by @@ -245,20 +244,17 @@ public class DescriptorSupport * programmer will have to reset or convert these fields * correctly.

    * - * @param inStr An XML-format or a fieldName=fieldValue formatted string - * used to populate this Descriptor. The XML format is not defined, but any + * @param inStr An XML-formatted string used to populate this + * Descriptor. The format is not defined, but any * implementation must ensure that the string returned by * method {@link #toXMLString toXMLString} on an existing * descriptor can be used to instantiate an equivalent * descriptor when instantiated using this constructor. * - * @exception RuntimeOperationsException If the String inStr passed in - * parameter is null or, when it is not an XML string, if the field name or - * field value is illegal. If inStr is not an XML string then it must - * contain an "=". "fieldValue", "fieldName", and "fieldValue" are illegal. - * FieldName cannot be empty. "fieldName=" will cause the value to be empty. + * @exception RuntimeOperationsException If the String inStr + * passed in parameter is null * @exception XMLParseException XML parsing problem while parsing - * the XML-format input String + * the input String * @exception MBeanException Wraps a distributed communication Exception. */ /* At some stage we should rewrite this code to be cleverer. Using @@ -287,27 +283,14 @@ public class DescriptorSupport throw new RuntimeOperationsException(iae, msg); } - // parse parameter string into structures - - init(null); - - if(!inStr.startsWith("<")) { - parseNamesValues(inStr); - if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { - MODELMBEAN_LOGGER.logp(Level.FINEST, - DescriptorSupport.class.getName(), - "Descriptor(name=value)", "Exit"); - } - return; - } - final String lowerInStr = inStr.toLowerCase(); if (!lowerInStr.startsWith("") || !lowerInStr.endsWith("")) { throw new XMLParseException("No , pair"); } - + // parse xmlstring into structures + init(null); // create dummy descriptor: should have same size // as number of fields in xmlstring // loop through structures and put them in descriptor @@ -471,16 +454,6 @@ public class DescriptorSupport init(null); - parseNamesValues(fields); - - if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { - MODELMBEAN_LOGGER.logp(Level.FINEST, - DescriptorSupport.class.getName(), - "Descriptor(String... fields)", "Exit"); - } - } - - private void parseNamesValues(String... fields) { for (int i=0; i < fields.length; i++) { if ((fields[i] == null) || (fields[i].equals(""))) { continue; @@ -522,6 +495,11 @@ public class DescriptorSupport setField(fieldName,fieldValue); } + if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { + MODELMBEAN_LOGGER.logp(Level.FINEST, + DescriptorSupport.class.getName(), + "Descriptor(String... fields)", "Exit"); + } } private void init(Map initMap) { diff --git a/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java b/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java index 9ee9a6b46..9caedb3f0 100644 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java @@ -231,16 +231,14 @@ public class ModelMBeanAttributeInfo * @param descriptor An instance of Descriptor containing the * appropriate metadata for this instance of the Attribute. If * it is null, then a default descriptor will be created. If - * the descriptor does not contain all the following fields, - * the missing ones are added with their default values: - * displayName, name, descriptorType. + * the descriptor does not contain the field "displayName" this field is added + * in the descriptor with its default value. * @exception IntrospectionException There is a consistency * problem in the definition of this attribute. * @exception RuntimeOperationsException Wraps an - * IllegalArgumentException. The descriptor is invalid, or - * descriptor field "name" is present but not equal to name - * parameter, or descriptor field "descriptorType" is present - * but not equal to "attribute". + * IllegalArgumentException. The descriptor is invalid, or descriptor + * field "name" is not equal to name parameter, or descriptor field + * "descriptorType" is not equal to "attribute". * */ @@ -295,7 +293,7 @@ public class ModelMBeanAttributeInfo } /** - * Constructs a ModelMBeanAttributeInfo object with a default descriptor. + * Constructs a ModelMBeanAttributeInfo object. * * @param name The name of the attribute * @param type The type or class name of the attribute @@ -306,14 +304,12 @@ public class ModelMBeanAttributeInfo * @param descriptor An instance of Descriptor containing the * appropriate metadata for this instance of the Attribute. If * it is null then a default descriptor will be created. If - * the descriptor does not contain all the following fields, - * the missing ones are added with their default values: - * displayName, name, descriptorType. + * the descriptor does not contain the field "displayName" this field + * is added in the descriptor with its default value. * @exception RuntimeOperationsException Wraps an - * IllegalArgumentException. The descriptor is invalid, or - * descriptor field "name" is present but not equal to name - * parameter, or descriptor field "descriptorType" is present - * but not equal to "attribute". + * IllegalArgumentException. The descriptor is invalid, or descriptor + * field "name" is not equal to name parameter, or descriptor field + * "descriptorType" is not equal to "attribute". * */ public ModelMBeanAttributeInfo(String name, @@ -392,9 +388,6 @@ public class ModelMBeanAttributeInfo * assigned. If the new Descriptor is invalid, then a * RuntimeOperationsException wrapping an * IllegalArgumentException is thrown. - * If the descriptor does not contain all the following fields, the - * missing ones are added with - * their default values: displayName, name, descriptorType. * @param inDescriptor replaces the Descriptor associated with the * ModelMBeanAttributeInfo * @@ -415,6 +408,7 @@ public class ModelMBeanAttributeInfo * fails for any reason, this exception will be thrown. */ + @Override public Object clone() { if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { @@ -429,6 +423,7 @@ public class ModelMBeanAttributeInfo * Returns a human-readable version of the * ModelMBeanAttributeInfo instance. */ + @Override public String toString() { return @@ -456,7 +451,8 @@ public class ModelMBeanAttributeInfo private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { Descriptor clone; - if (in == null) { + boolean defaulted = (in == null); + if (defaulted) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); } else { @@ -464,11 +460,11 @@ public class ModelMBeanAttributeInfo } //Setting defaults. - if (clone.getFieldValue("name")==null) { + if (defaulted && clone.getFieldValue("name")==null) { clone.setField("name", this.getName()); MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName()); } - if (clone.getFieldValue("descriptorType")==null) { + if (defaulted && clone.getFieldValue("descriptorType")==null) { clone.setField("descriptorType", "attribute"); MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"attribute\""); } @@ -483,13 +479,13 @@ public class ModelMBeanAttributeInfo "The isValid() method of the Descriptor object itself returned false,"+ "one or more required fields are invalid. Descriptor:" + clone.toString()); } - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) { + if (!getName().equalsIgnoreCase((String)clone.getFieldValue("name"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"name\" field does not match the object described. " + " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name")); } - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("attribute")) { + if (!"attribute".equalsIgnoreCase((String)clone.getFieldValue("descriptorType"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"descriptorType\" field does not match the object described. " + " Expected: \"attribute\" ," + " was: " + clone.getFieldValue("descriptorType")); diff --git a/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java b/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java index ecf8ecf00..5fd0ccba5 100644 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java @@ -78,9 +78,7 @@ import javax.management.RuntimeOperationsException; * are meaningless for constructors, but are not considered invalid.

    * *

    The default descriptor will have the {@code name}, {@code - * descriptorType}, {@code displayName} and {@code role} fields. The - * default value of the {@code name} and {@code displayName} fields is - * the name of the constructor. + * descriptorType}, {@code displayName} and {@code role} fields. * *

    The serialVersionUID of this class is 3862947819818064362L. * @@ -193,14 +191,14 @@ public class ModelMBeanConstructorInfo * appropriate metadata for this instance of the * ModelMBeanConstructorInfo. If it is null, then a default * descriptor will be created. If the descriptor does not - * contain all the following fields, the missing ones are added with - * their default values: displayName, name, role, descriptorType. + * contain the field "displayName" this field is added in the + * descriptor with its default value. * * @exception RuntimeOperationsException Wraps an * IllegalArgumentException. The descriptor is invalid, or - * descriptor field "name" is present but not equal to name - * parameter, or descriptor field "descriptorType" is present - * but not equal to "operation" or descriptor field "role" is + * descriptor field "name" is not equal to name + * parameter, or descriptor field "descriptorType" is + * not equal to "operation" or descriptor field "role" is * present but not equal to "constructor". */ @@ -250,15 +248,14 @@ public class ModelMBeanConstructorInfo * @param signature MBeanParameterInfo objects describing the parameters(arguments) of the constructor. * @param descriptor An instance of Descriptor containing the appropriate metadata * for this instance of the MBeanConstructorInfo. If it is null then a default descriptor will be created. - * If the descriptor does not - * contain all the following fields, the missing ones are added with - * their default values: displayName, name, role, descriptorType. + * If the descriptor does not contain the field "displayName" this field + * is added in the descriptor with its default value. * * @exception RuntimeOperationsException Wraps an * IllegalArgumentException. The descriptor is invalid, or - * descriptor field "name" is present but not equal to name - * parameter, or descriptor field "descriptorType" is present - * but not equal to "operation" or descriptor field "role" is + * descriptor field "name" is not equal to name + * parameter, or descriptor field "descriptorType" is + * not equal to "operation" or descriptor field "role" is * present but not equal to "constructor". */ @@ -300,6 +297,7 @@ public class ModelMBeanConstructorInfo * Creates and returns a new ModelMBeanConstructorInfo which is a duplicate of this ModelMBeanConstructorInfo. * */ + @Override public Object clone () { if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { @@ -320,6 +318,7 @@ public class ModelMBeanConstructorInfo */ + @Override public Descriptor getDescriptor() { if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { @@ -368,6 +367,7 @@ public class ModelMBeanConstructorInfo /** * Returns a string containing the entire contents of the ModelMBeanConstructorInfo in human readable form. */ + @Override public String toString() { if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { @@ -404,8 +404,9 @@ public class ModelMBeanConstructorInfo * @exception RuntimeOperationsException if Descriptor is invalid */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { - Descriptor clone; - if (in == null) { + Descriptor clone; + boolean defaulted = (in == null); + if (defaulted) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); } else { @@ -413,11 +414,11 @@ public class ModelMBeanConstructorInfo } //Setting defaults. - if (clone.getFieldValue("name")==null) { + if (defaulted && clone.getFieldValue("name")==null) { clone.setField("name", this.getName()); MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName()); } - if (clone.getFieldValue("descriptorType")==null) { + if (defaulted && clone.getFieldValue("descriptorType")==null) { clone.setField("descriptorType", "operation"); MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"operation\""); } @@ -436,12 +437,12 @@ public class ModelMBeanConstructorInfo "The isValid() method of the Descriptor object itself returned false,"+ "one or more required fields are invalid. Descriptor:" + clone.toString()); } - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) { + if (!getName().equalsIgnoreCase((String) clone.getFieldValue("name"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"name\" field does not match the object described. " + " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name")); } - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("operation")) { + if (!"operation".equalsIgnoreCase((String) clone.getFieldValue("descriptorType"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"descriptorType\" field does not match the object described. " + " Expected: \"operation\" ," + " was: " + clone.getFieldValue("descriptorType")); diff --git a/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java b/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java index 3655daadd..ad705ffb1 100644 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java @@ -945,7 +945,8 @@ public class ModelMBeanInfoSupport extends MBeanInfo implements ModelMBeanInfo { */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { Descriptor clone; - if (in == null) { + boolean defaulted = (in == null); + if (defaulted) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); } else { @@ -953,11 +954,11 @@ public class ModelMBeanInfoSupport extends MBeanInfo implements ModelMBeanInfo { } //Setting defaults. - if (clone.getFieldValue("name")==null) { + if (defaulted && clone.getFieldValue("name")==null) { clone.setField("name", this.getClassName()); MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getClassName()); } - if (clone.getFieldValue("descriptorType")==null) { + if (defaulted && clone.getFieldValue("descriptorType")==null) { clone.setField("descriptorType", MMB); MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"" + MMB + "\""); } diff --git a/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java b/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java index 4b637ee08..16b52b80d 100644 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java @@ -186,14 +186,14 @@ public class ModelMBeanNotificationInfo * @param descriptor An instance of Descriptor containing the * appropriate metadata for this instance of the * MBeanNotificationInfo. If it is null a default descriptor - * will be created. If the descriptor does not contain all the - * fields "name", "descriptorType", "displayName" and "severity", + * will be created. If the descriptor does not contain the + * fields "displayName" or "severity", * the missing ones are added with their default values. * * @exception RuntimeOperationsException Wraps an * {@link IllegalArgumentException}. The descriptor is invalid, or - * descriptor field "name" is present but not equal to parameter name, or - * descriptor field "descriptorType" is present but not equal to "notification". + * descriptor field "name" is not equal to parameter name, or + * descriptor field "descriptorType" is not equal to "notification". * **/ public ModelMBeanNotificationInfo(String[] notifTypes, @@ -341,7 +341,8 @@ public class ModelMBeanNotificationInfo */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { Descriptor clone; - if (in == null) { + boolean defaulted = (in == null); + if (defaulted) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); } else { @@ -349,11 +350,11 @@ public class ModelMBeanNotificationInfo } //Setting defaults. - if (clone.getFieldValue("name")==null) { + if (defaulted && clone.getFieldValue("name")==null) { clone.setField("name", this.getName()); MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName()); } - if (clone.getFieldValue("descriptorType")==null) { + if (defaulted && clone.getFieldValue("descriptorType")==null) { clone.setField("descriptorType", "notification"); MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"notification\""); } @@ -372,12 +373,12 @@ public class ModelMBeanNotificationInfo "The isValid() method of the Descriptor object itself returned false,"+ "one or more required fields are invalid. Descriptor:" + clone.toString()); } - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) { + if (!getName().equalsIgnoreCase((String) clone.getFieldValue("name"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"name\" field does not match the object described. " + " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name")); } - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("notification")) { + if (!"notification".equalsIgnoreCase((String) clone.getFieldValue("descriptorType"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"descriptorType\" field does not match the object described. " + " Expected: \"notification\" ," + " was: " + clone.getFieldValue("descriptorType")); diff --git a/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java b/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java index 6ebea4995..4cda6b7b2 100644 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java @@ -208,16 +208,16 @@ public class ModelMBeanOperationInfo extends MBeanOperationInfo * appropriate metadata for this instance of the * ModelMBeanOperationInfo. If it is null a default * descriptor will be created. If the descriptor does not - * contain all the fields "name", "descriptorType", - * "displayName", and "role", the missing ones are added with + * contain the fields + * "displayName" or "role", the missing ones are added with * their default values. * * @exception RuntimeOperationsException Wraps an * IllegalArgumentException. The descriptor is invalid; or - * descriptor field "name" is present but not equal to + * descriptor field "name" is not equal to * operation name; or descriptor field "DescriptorType" is - * present but not equal to "operation"; or descriptor - * optional field "role" is not equal to "operation", + * not equal to "operation"; or descriptor + * optional field "role" is present but not equal to "operation", * "getter", or "setter". * */ @@ -281,16 +281,16 @@ public class ModelMBeanOperationInfo extends MBeanOperationInfo * @param descriptor An instance of Descriptor containing the * appropriate metadata for this instance of the * MBeanOperationInfo. If it is null then a default descriptor - * will be created. If the descriptor does not contain all the - * fields "name", "descriptorType", "displayName", and "role", + * will be created. If the descriptor does not contain + * fields "displayName" or "role", * the missing ones are added with their default values. * * @exception RuntimeOperationsException Wraps an * IllegalArgumentException. The descriptor is invalid; or - * descriptor field "name" is present but not equal to + * descriptor field "name" is not equal to * operation name; or descriptor field "DescriptorType" is - * present but not equal to "operation"; or descriptor optional - * field "role" is not equal to "operation", "getter", or + * not equal to "operation"; or descriptor optional + * field "role" is present but not equal to "operation", "getter", or * "setter". */ @@ -446,7 +446,8 @@ public class ModelMBeanOperationInfo extends MBeanOperationInfo private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { Descriptor clone; - if (in == null) { + boolean defaulted = (in == null); + if (defaulted) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); } else { @@ -454,11 +455,11 @@ public class ModelMBeanOperationInfo extends MBeanOperationInfo } //Setting defaults. - if (clone.getFieldValue("name")==null) { + if (defaulted && clone.getFieldValue("name")==null) { clone.setField("name", this.getName()); MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName()); } - if (clone.getFieldValue("descriptorType")==null) { + if (defaulted && clone.getFieldValue("descriptorType")==null) { clone.setField("descriptorType", "operation"); MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"operation\""); } @@ -477,15 +478,15 @@ public class ModelMBeanOperationInfo extends MBeanOperationInfo "The isValid() method of the Descriptor object itself returned false,"+ "one or more required fields are invalid. Descriptor:" + clone.toString()); } - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) { + if (!getName().equalsIgnoreCase((String) clone.getFieldValue("name"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"name\" field does not match the object described. " + " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name")); } - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("operation")) { + if (!"operation".equalsIgnoreCase((String) clone.getFieldValue("descriptorType"))) { throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), "The Descriptor \"descriptorType\" field does not match the object described. " + - " Expected: \"attribute\" ," + " was: " + clone.getFieldValue("descriptorType")); + " Expected: \"operation\" ," + " was: " + clone.getFieldValue("descriptorType")); } final String role = (String)clone.getFieldValue("role"); if (!(role.equalsIgnoreCase("operation") || diff --git a/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java index b9bec5ecc..40f2ac158 100644 --- a/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -23,7 +23,7 @@ * have any questions. */ /* - * @(#)author IBM Corp. + * @author IBM Corp. * * Copyright IBM Corp. 1999-2000. All rights reserved. */ @@ -55,7 +55,6 @@ import javax.management.AttributeChangeNotificationFilter; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.Descriptor; -import javax.management.DynamicWrapperMBean; import javax.management.InstanceNotFoundException; import javax.management.InvalidAttributeValueException; import javax.management.ListenerNotFoundException; @@ -116,7 +115,7 @@ import sun.reflect.misc.ReflectUtil; */ public class RequiredModelMBean - implements ModelMBean, MBeanRegistration, NotificationEmitter, DynamicWrapperMBean { + implements ModelMBean, MBeanRegistration, NotificationEmitter { /*************************************/ /* attributes */ @@ -134,8 +133,6 @@ public class RequiredModelMBean * and operations will be executed */ private Object managedResource = null; - /* true if getWrappedObject returns the wrapped resource */ - private boolean visible; /* records the registering in MBeanServer */ private boolean registered = false; @@ -322,13 +319,9 @@ public class RequiredModelMBean * * @param mr Object that is the managed resource * @param mr_type The type of reference for the managed resource. - *
    Can be: "ObjectReference", "VisibleObjectReference", - * "Handle", "IOR", "EJBHandle", or "RMIReference". - *
    In this implementation only "ObjectReference" and - * "VisibleObjectReference" are supported. The two - * types are equivalent except for the behavior of the - * {@link #getWrappedObject()} and {@link #getWrappedClassLoader()} - * methods. + *
    Can be: "ObjectReference", "Handle", "IOR", "EJBHandle", + * or "RMIReference". + *
    In this implementation only "ObjectReference" is supported. * * @exception MBeanException The initializer of the object has * thrown an exception. @@ -348,11 +341,10 @@ public class RequiredModelMBean "setManagedResource(Object,String)","Entry"); } - visible = "visibleObjectReference".equalsIgnoreCase(mr_type); - // check that the mr_type is supported by this JMXAgent // only "objectReference" is supported - if (!"objectReference".equalsIgnoreCase(mr_type) && !visible) { + if ((mr_type == null) || + (! mr_type.equalsIgnoreCase("objectReference"))) { if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { MODELMBEAN_LOGGER.logp(Level.FINER, RequiredModelMBean.class.getName(), @@ -377,51 +369,6 @@ public class RequiredModelMBean } } - /** - *

    Get the managed resource for this Model MBean. For compatibility - * reasons, the managed resource is only returned if the resource type - * specified to {@link #setManagedResource setManagedResource} was {@code - * "visibleObjectReference"}. Otherwise, {@code this} is returned.

    - * - * @return The value that was specified to {@link #setManagedResource - * setManagedResource}, if the resource type is {@code - * "visibleObjectReference"}. Otherwise, {@code this}. - */ - public Object getWrappedObject() { - if (visible) - return managedResource; - else - return this; - } - - /** - *

    Get the ClassLoader of the managed resource for this Model MBean. For - * compatibility reasons, the ClassLoader of the managed resource is only - * returned if the resource type specified to {@link #setManagedResource - * setManagedResource} was {@code "visibleObjectReference"}. Otherwise, - * {@code this.getClass().getClassLoader()} is returned.

    - * - * @return The ClassLoader of the value that was specified to - * {@link #setManagedResource setManagedResource}, if the resource - * type is {@code "visibleObjectReference"}. Otherwise, {@code - * this.getClass().getClassLoader()}. - */ - public ClassLoader getWrappedClassLoader() { - return getWrappedObject().getClass().getClassLoader(); - } - - private static boolean isTrue(Descriptor d, String field) { - if (d == null) - return false; - Object x = d.getFieldValue(field); - if (x instanceof Boolean) - return (Boolean) x; - if (!(x instanceof String)) - return false; - String s = (String) x; - return ("true".equalsIgnoreCase(s) || "T".equalsIgnoreCase(s)); - } - /** *

    Instantiates this MBean instance with the data found for * the MBean in the persistent store. The data loaded could include diff --git a/src/share/classes/javax/management/monitor/MonitorNotification.java b/src/share/classes/javax/management/monitor/MonitorNotification.java index f0d65c6da..744d7434f 100644 --- a/src/share/classes/javax/management/monitor/MonitorNotification.java +++ b/src/share/classes/javax/management/monitor/MonitorNotification.java @@ -201,7 +201,7 @@ public class MonitorNotification extends javax.management.Notification { * @param derGauge The derived gauge. * @param trigger The threshold/string (depending on the monitor type) that triggered the notification. */ - public MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, + MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, ObjectName obsObj, String obsAtt, Object derGauge, Object trigger) { super(type, source, sequenceNumber, timeStamp, msg); diff --git a/src/share/classes/javax/management/namespace/JMXDomain.java b/src/share/classes/javax/management/namespace/JMXDomain.java deleted file mode 100644 index ca108bf12..000000000 --- a/src/share/classes/javax/management/namespace/JMXDomain.java +++ /dev/null @@ -1,378 +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 javax.management.namespace; - -import java.io.IOException; -import javax.management.ListenerNotFoundException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.ObjectName; - -/** - * A special {@link JMXNamespace} that can handle part of - * the MBeanServer local name space. - *

    - * A {@code JMXDomain} makes a domain X of a - * {@linkplain #getSourceServer() source MBean server} appear in the same domain - * X of a containing {@code MBeanServer} in which the - * {@code JMXDomain} MBean {@linkplain #getMBeanServer() is registered}. - *

    - *

    - * The JMX infrastructure of the containing {@code MBeanServer} takes care of - * routing all calls to MBeans whose names have domain X to the - * {@linkplain #getSourceServer() source MBean server} exported by the - * {@code JMXDomain} MBean in charge of domain X. - *

    - *

    - * The {@linkplain #getSourceServer() source MBean server} of a {@code JMXDomain} - * can, but need not be a regular {@code MBeanServer} created through - * the {@link javax.management.MBeanServerFactory}. It could also be, - * for instance, an instance of a subclass of {@link MBeanServerSupport}, - * or a custom object implementing the {@link MBeanServer} interface. - *

    - * - *

    Differences between {@code JMXNamespace} and {@code JMXDomain}

    - * - *

    - * A {@code JMXDomain} is a special kind of {@code JMXNamespace}. - * A {@code JMXNamespace} such as {@code foo//} is triggered by an - * {@code ObjectName} that begins with the string {@code foo//}, for example - * {@code foo//bar:type=Baz}. A {@code JMXDomain} such as {@code foo} is - * triggered by an {@code ObjectName} with that exact domain, for example - * {@code foo:type=Baz}. A client can immediately see that an MBean is - * handled by a {@code JMXNamespace} because of the {@code //} in the name. - * A client cannot see whether a name such as {@code foo:type=Baz} is an - * ordinary MBean or is handled by a {@code JMXDomain}. - *

    - * - *

    - * A {@linkplain MBeanServer#queryNames query} on the containing {@code - * MBeanserver} will return all MBeans from the {@code JMXDomain} that match - * the query. In particular, {@code queryNames(null, null)} will return all - * MBeans including those from {@code JMXDomain} domains. On the other hand, - * a query will not include MBeans from a {@code JMXNamespace} unless the - * {@code ObjectName} pattern in the query starts with the name of that - * namespace. - *

    - * - *

    Permission checks

    - * - *

    - * When a JMXDomain MBean is registered in a containing - * MBean server created through the default {@link - * javax.management.MBeanServerBuilder}, and if a {@link - * SecurityManager SecurityManager} is - * {@linkplain System#getSecurityManager() present}, the containing MBeanServer will - * check an {@link javax.management.MBeanPermission} before invoking - * any method on the {@linkplain #getSourceServer() source MBeanServer} of the - * JMXDomain. - *

    - * - *

    First, if there is no security manager ({@link - * System#getSecurityManager()} is null), that containing - * {@code MBeanServer} is free not to make any checks. - *

    - * - *

    - * Assuming that there is a security manager, or that the - * implementation chooses to make checks anyway, the containing - * {@code MBeanServer} will perform - * {@link javax.management.MBeanPermission MBeanPermission} checks - * for access to the MBeans in domain X handled by a {@code JMXDomain} - * in the same way that it would do for MBeans registered in its own local - * repository, and as described in - * the MBeanServer interface, with the following exceptions: - *

    - * - *

    - * For those permissions that require a {@code className}, the - * className is the - * string returned by {@link #getSourceServer() getSourceServer()}. - * {@link MBeanServer#getObjectInstance(ObjectName) - * getObjectInstance(mbeanName)}. - * {@link javax.management.ObjectInstance#getClassName() getClassName()}, - * except for {@code createMBean} and {@code registerMBean} operations, - * for which the permission checks are performed as follows: - *

    - *
      - *
    • For {@code createMBean} operations, the {@code className} of the - * permission you need is the {@code className} passed as first parameter - * to {@code createMBean}.

      - * - *
    • For {@code registerMBean} operations, the {@code className} of the - * permission you need is the name of the class of the mbean object, as - * returned by {@code mbean.getClass().getClassName()}, where - * {@code mbean} is the mbean reference passed as first parameter - * to {@code registerMBean}.

      - * - *
    • In addition, for {@code createMBean} and {@code registerMBean}, the - * permission you need is checked with the {@linkplain ObjectName object name} of - * the mbean that is passed as second parameter to the {@code createMBean} or - * {@code registerMBean} operation. - *

      - * - *
    • Contrarily to what is done for regular MBeans registered in the - * MBeanServer local repository, the containing MBeanServer will not - * check the {@link javax.management.MBeanTrustPermission#MBeanTrustPermission(String) - * MBeanTrustPermission("register")} against the protection domain - * of the MBean's class. This check can be performed by the - * {@linkplain #getSourceServer source MBean server} implementation, - * if necessary. - *

      - *
    - * - *

    If a security check fails, the method throws {@link - * SecurityException}.

    - * - *

    For methods that can throw {@link InstanceNotFoundException}, - * this exception is thrown for a non-existent MBean, regardless of - * permissions. This is because a non-existent MBean has no - * className.

    - * - * All these checks are performed by the containing {@code MBeanServer}, - * before accessing the JMXDomain {@linkplain #getSourceServer source MBean server}. - * The implementation of the JMXDomain {@linkplain #getSourceServer source MBean - * server} is free to make any additional checks. In fact, if the JMXDomain - * {@linkplain #getSourceServer source MBean server} is an {@code MBeanServer} - * obtained through the {@link javax.management.MBeanServerFactory}, it will - * again make permission checks as described in the - * MBeanServer interface. - * - *

    See the MBeanServer interface - * for more details on permission checks.

    - * - * @since 1.7 - */ -public class JMXDomain extends JMXNamespace { - - - /** - * This constant contains the value of the {@code type} - * key used in defining a standard JMXDomain MBean object name. - * By definition, a standard JMXDomain MBean object name must be of - * the form: - *
    -     * {@code ":"}+{@value javax.management.namespace.JMXDomain#TYPE_ASSIGNMENT}
    -     * 
    - */ - public static final String TYPE = "JMXDomain"; - - /** - * This constant contains the value of the standard - * {@linkplain javax.management.ObjectName#getKeyPropertyListString() key - * property list string} for JMXDomain MBean object names. - * By definition, a standard JMXDomain MBean object name must be of - * the form: - *
    -     * {@code }+":"+{@value javax.management.namespace.JMXDomain#TYPE_ASSIGNMENT}
    -     * 
    - */ - public static final String TYPE_ASSIGNMENT = "type="+TYPE; - - - - /** - * Creates a new instance of JMXDomain. The MBeans contained in this - * domain are handled by the {@code virtualServer} object given to - * this constructor. Frequently, this will be an instance of - * {@link MBeanServerSupport}. - * @param virtualServer The virtual server that acts as a container for - * the MBeans handled by this JMXDomain object. Frequently, this will - * be an instance of {@link MBeanServerSupport} - * @see JMXNamespace#JMXNamespace(MBeanServer) - */ - public JMXDomain(MBeanServer virtualServer) { - super(virtualServer); - } - - /** - * Return the name of domain handled by this JMXDomain. - * @return the domain handled by this JMXDomain. - * @throws IOException - if the domain cannot be determined, - * for instance, if the MBean is not registered yet. - */ - @Override - public final String getDefaultDomain() { - final ObjectName name = getObjectName(); - if (name == null) - throw new IllegalStateException("DefaultDomain is not yet known"); - final String dom = name.getDomain(); - return dom; - } - - /** - * Returns a singleton array, containing the only domain handled by - * this JMXDomain object. This is - * {@code new String[] {getDefaultDomain()}}. - * @return the only domain handled by this JMXDomain. - * @throws IOException if the domain cannot be determined, - * for instance, if the MBean is not registered yet. - * @see #getDefaultDomain() - */ - @Override - public final String[] getDomains() { - return new String[] {getDefaultDomain()}; - } - - /** - * This method returns the number of MBeans in the domain handled - * by this JMXDomain object. The default implementation is: - *
    -     *    getSourceServer().queryNames(
    -     *        new ObjectName(getObjectName().getDomain()+":*"), null).size();
    -     * 
    - * If this JMXDomain is not yet registered, this method returns 0. - * Subclasses can override the above behavior and provide a better - * implementation. - *

    - * The getMBeanCount() method is called when computing the number - * of MBeans in the {@linkplain #getMBeanServer() containing MBeanServer}. - * @return the number of MBeans in this domain, or 0. - */ - @Override - public Integer getMBeanCount() { - final ObjectName name = getObjectName(); - if (name == null) return 0; - try { - return getSourceServer(). - queryNames(ObjectName.WILDCARD.withDomain(name.getDomain()), - null).size(); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException("Unexpected exception: "+x,x); - } - } - - - - /** - * Return a canonical handler name for the provided local - * domain name, or null if the provided domain name is - * {@code null}. - * If not null, the handler name returned will be - * {@code domain+":type="+}{@link #TYPE TYPE}, for example - * {@code foo:type=JMXDomain}. - * @param domain A domain name - * @return a canonical ObjectName for a domain handler. - * @throws IllegalArgumentException if the provided - * domain is not valid - e.g it contains "//". - */ - public static ObjectName getDomainObjectName(String domain) { - if (domain == null) return null; - if (domain.contains(NAMESPACE_SEPARATOR)) - throw new IllegalArgumentException("domain contains " + - NAMESPACE_SEPARATOR+": "+domain); - return ObjectName.valueOf(domain, "type", TYPE); - } - - - /** - * Validate the ObjectName supplied to preRegister. - * This method is introduced to allow standard subclasses to use - * an alternate naming scheme. For instance - if we want to - * reuse JMXNamespace in order to implement sessions... - * It is however only available for subclasses in this package. - **/ - @Override - ObjectName validateHandlerName(ObjectName suppliedName) { - if (suppliedName == null) - throw new IllegalArgumentException("Must supply a valid name"); - final String dirName = JMXNamespaces. - normalizeNamespaceName(suppliedName.getDomain()); - final ObjectName handlerName = getDomainObjectName(dirName); - if (!suppliedName.equals(handlerName)) - throw new IllegalArgumentException("invalid name space name: "+ - suppliedName); - - return suppliedName; - } - - /** - * This method is called by the JMX framework to register a - * NotificationListener that will forward {@linkplain - * javax.management.MBeanServerNotification mbean server notifications} - * through the delegate of the {@linkplain #getMBeanServer() - * containing MBeanServer}. - * The default implementation of this method is to call - *

    -     *    getSourceServer().addNotificationListener(
    -     *           MBeanServerDelegate.DELEGATE_NAME, listener, filter, null);
    -     * 
    - * Subclasses can redefine this behavior if needed. In particular, - * subclasses can send their own instances of {@link - * javax.management.MBeanServerNotification} by calling - * {@code listener.handleNotification()}. - * - * @param listener The MBeanServerNotification listener for this domain. - * @param filter A notification filter. - */ - public void addMBeanServerNotificationListener( - NotificationListener listener, NotificationFilter filter) { - try { - getSourceServer().addNotificationListener( - MBeanServerDelegate.DELEGATE_NAME, listener, filter, null); - } catch(InstanceNotFoundException x) { - throw new UnsupportedOperationException( - "Unexpected exception: " + - "Emission of MBeanServerNotification disabled.", x); - } - } - - /** - * This method is called by the JMX framework to remove the - * NotificationListener that was added with {@link - * #addMBeanServerNotificationListener addMBeanServerNotificationListener}. - * The default implementation of this method is to call - *
    -     *    getSourceServer().removeNotificationListener(
    -     *           MBeanServerDelegate.DELEGATE_NAME, listener);
    -     * 
    - * Subclasses can redefine this behavior if needed. - * - * @param listener The MBeanServerNotification listener for this domain. - * @throws ListenerNotFoundException if the listener is not found. - */ - public void removeMBeanServerNotificationListener( - NotificationListener listener) - throws ListenerNotFoundException { - try { - getSourceServer().removeNotificationListener( - MBeanServerDelegate.DELEGATE_NAME, listener); - } catch(InstanceNotFoundException x) { - throw new UnsupportedOperationException( - "Unexpected exception: " + - "Emission of MBeanServerNotification disabled.", x); - } - } - -} diff --git a/src/share/classes/javax/management/namespace/JMXNamespace.java b/src/share/classes/javax/management/namespace/JMXNamespace.java deleted file mode 100644 index 23f3004eb..000000000 --- a/src/share/classes/javax/management/namespace/JMXNamespace.java +++ /dev/null @@ -1,666 +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 javax.management.namespace; - - -import java.io.IOException; - -import java.util.UUID; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.ObjectName; - -/** - * MBean Servers can be federated into a single hierarchical name space: - * A JMXNamespace is an MBean that handles a sub name space in that - * hierarchical name space. - *

    - * A name space is created simply by registering a {@code JMXNamespace} - * MBean in the MBean Server. The name of the created name space is defined - * by the {@linkplain JMXNamespaces#getNamespaceObjectName name of the JMXNamespace} - * that handles it. A name space is equivalent to - * an MBean Server within an MBean Server. When creating a {@code JMXNamespace}, - * the MBean Server within is passed to the constructor. - *

    - *

    - * The {@code JMXNamespace} class is the base class for implementing - * all name space handlers. All name space handlers must be instances of - * {@code JMXNamespace} or a subclass of it. - *

    - *

    - * A concrete example of a {@code JMXNamespace} MBean subclass - * is the {@link JMXRemoteNamespace JMXRemoteNamespace} MBean which - * is able to mirror all MBeans contained in a remote MBean server known by its - * {@link javax.management.remote.JMXServiceURL}. - *

    - *

    - * You can create a local namespace by supplying a newly created MBean Server - * to an instance of {@code JMXNamespace}. For instance: - *

    - * final String namespace = "foo";
    - * final ObjectName namespaceName = {@link JMXNamespaces#getNamespaceObjectName
    - *       JMXNamespaces.getNamespaceObjectName(namespace)};
    - * server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
    - *                      namespaceName);
    - * 
    - *

    - *

    - * Note: A JMXNamespace MBean cannot be registered - * simultaneously in two different - * MBean servers, or indeed in the same MBean Server with two - * different names. It is however possible to give the same MBeanServer - * instance to two different JMXNamespace MBeans, and thus create a graph - * rather than a tree. - *

    - * - *

    To view the content of a namespace, you will usually use an - * instance of {@link JMXNamespaceView}. For instance, given the - * namespace {@code "foo"} created above, you would do: - *

    - *
    - * final JMXNamespaceView view = new JMXNamespaceView(server);
    - * System.out.println("List of namespaces: "+Arrays.toString({@link JMXNamespaceView#list() view.list()}));
    - *
    - * final JMXNamespaceView foo  = {@link JMXNamespaceView#down view.down("foo")};
    - * System.out.println({@link JMXNamespaceView#where() foo.where()}+" contains: " +
    - *        {@link JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
    - * 
    - * - *

    JMX Namespace Permission Checks

    - * - *

    A special {@link JMXNamespacePermission} is defined to check access - * to MBean within namespaces.

    - *

    When a JMXNamespace MBean is registered in an - * MBean server created through the default {@link - * javax.management.MBeanServerBuilder}, and if a {@link - * SecurityManager SecurityManager} is - * {@linkplain System#getSecurityManager() present}, the MBeanServer will - * check a {@link JMXNamespacePermission} before invoking - * any method on the {@linkplain #getSourceServer source MBeanServer} of the - * JMXNamespace. - * {@linkplain JMXNamespacePermission JMX Namespace Permissions} are similar to - * {@linkplain javax.management.MBeanPermission MBean Permissions}, except - * that you usually cannot specify an MBean class name. You can however - * specify object name patterns - which will allow you for example to only grant - * permissions for MBeans having a specific {@code type=} key - * in their object name. - *

    - * Another difference is that {@link JMXNamespacePermission - * JMXNamespacePermission} also specifies from which namespace and which - * MBean server the permission is granted. - *

    - *

    In the rest of this document, the following terms are used:

    - *
      - *
    • {@code server name} is the - * name of the - * MBeanServer in which the permission is granted. - * The name of an {@code MBeanServer} can be obtained by calling {@link - * javax.management.MBeanServerFactory#getMBeanServerName - * MBeanServerFactory.getMBeanServerName(mbeanServer)} - *

      - *
    • {@code namespace} is the name of the namespace - * in the named MBean server for which the - * permission is granted. It doesn't contain any - * {@link JMXNamespaces#NAMESPACE_SEPARATOR namespace separator}. - *

      - *
    • {@code mbean} is the name - * of the MBean in that {@code namespace}. This is the name of the MBean - * in the namespace's {@link JMXNamespace#getSourceServer() source mbean server}. - * It might contain no, one, or several {@link - * JMXNamespaces#NAMESPACE_SEPARATOR namespace separators}. - *

      - *
    - * - *

    For instance let's assume that some piece of code calls:

    - *
    - *     final MBeanServer mbeanServer = ...;
    - *     final ObjectName  name   = new ObjectName("a//b//c//D:k=v");
    - *     mbeanServer.getAttribute(name,"Foo");
    - * 
    - *

    - * Assuming that there is a security manager, or that the - * implementation chooses to make checks anyway, the checks that will - * be made in that case are: - *

    - *
      - *
    1. - * JMXNamespacePermission(mbeanServerName, "Foo", "a//b//c//D:k=v", - * "getAttribute") - * (where {@code mbeanServerName=MBeanServerFactory.getMBeanServerName(mbeanServer)}, - * namespace="a", and {@code mbean="b//c//D:k=v"}) - *
    2. - *
    3. and in addition if namespace {@code "a"} is local, - * JMXNamespacePermission(aSourceServerName,"Foo","b//c//D:k=v", - * "getAttribute")} - * (where - * {@code aSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(a))}, - * namespace="b", and {@code mbean="c//D:k=v"}), - *
    4. - *
    5. and in addition if namespace {@code "b"} is also local, - * JMXNamespacePermission(bSourceServerName,"Foo","c//D:k=v", - * "getAttribute")} - * (where - * {@code bSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(b))}, - * namespace="c", and {@code mbean="D:k=v"}), - *
    6. - *
    7. and in addition if the source mbean server of namespace - * {@code "c"} is a also a local MBeanServer in this JVM, - * {@code MBeanPermission(cSourceServerName,,"Foo","D:k=v","getAttrinute")}, - * (where - * {@code cSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(c))}). - *
    8. - *
    - *

    For any of these MBean servers, if no name was supplied when - * creating that MBeanServer the {@link JMXNamespacePermission} is - * created with an {@code mbeanServerName} equal to - * {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}. - *

    - *

    If the namespace {@code a} is in fact a remote {@code MBeanServer}, - * for instance because namespace {@code a} is implemented by a {@link - * JMXRemoteNamespace} pointing to a distant MBeanServer located in - * another JMX agent, then checks 2, - * 3, and 4 will not - * be performed in the local JVM. They might or might not be performed in - * the remote agent, depending on how access control and permission - * checking are configured in the remote agent, and how authentication - * is configured in the connector used by the {@link - * JMXRemoteNamespace}. - *

    - *

    In all cases, {@linkplain JMXNamespacePermission JMX Namespace Permissions} - * are checked as follows:

    - *

    First, if there is no security manager ({@link - * System#getSecurityManager()} is null), then an implementation of - * of MBeanServer that supports JMX namespaces is free not to make any - * checks.

    - * - *

    Assuming that there is a security manager, or that the - * implementation chooses to make checks anyway, the checks are made - * as detailed below.

    - * - *

    If a security check fails, the method throws {@link - * SecurityException}.

    - * - *
      - * - *
    • For the {@link MBeanServer#invoke invoke} method, the caller's - * permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <operation name>, <namespace>//<mbean>, "invoke")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#getAttribute getAttribute} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <attribute>, <namespace>//<mbean>, "getAttribute")}. - *

      - * - *
    • For the {@link MBeanServer#getAttributes getAttributes} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <null>, <namespace>//<mbean>, "getAttribute")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - * Additionally, for each attribute att in the {@link - * javax.management.AttributeList}, if the caller's permissions do not - * imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, att, - * <namespace>//<mbean>, "getAttribute")}, the - * MBean server will behave as if that attribute had not been in the - * supplied list.

      - * - *
    • For the {@link MBeanServer#setAttribute setAttribute} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <attrName>, <namespace>//<mbean>, "setAttribute")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace, and - * attrName is {@link javax.management.Attribute#getName() - * attribute.getName()}.

      - * - *
    • For the {@link MBeanServer#setAttributes setAttributes} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, "setAttribute")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - * Additionally, for each attribute att in the {@link - * javax.management.AttributeList}, if the caller's permissions do not - * imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, att, <namespace>//<mbean>, "setAttribute")}, - * the MBean server will behave as if that attribute had not been in the - * supplied list.

      - * - *
    • For the addNotificationListener methods, - * the caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "addNotificationListener")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the removeNotificationListener methods, - * the caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "removeNotificationListener")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#getMBeanInfo getMBeanInfo} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "getMBeanInfo")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#getObjectInstance getObjectInstance} method, - * the caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "getObjectInstance")}, - * where mbean server name/a> is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#isInstanceOf isInstanceOf} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "isInstanceOf")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#queryMBeans queryMBeans} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, null, - * "queryMBeans")}. - * Additionally, for each MBean {@code mbean} that matches {@code pattern}, - * if the caller's permissions do not imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "queryMBeans")}, the - * MBean server will behave as if that MBean did not exist.

      - * - *

      Certain query elements perform operations on the MBean server. - * However these operations are usually performed by the MBeanServer at the - * bottom of the namespace path, and therefore, do not involve any - * {@link JMXNamespacePermission} permission check. They might involve - * {@link javax.management.MBeanPermission} checks depending on how security - * in the JVM in which the bottom MBeanServer resides is implemented. - * See {@link javax.management.MBeanServer} for more details. - *

      - * - *
    • For the {@link MBeanServer#queryNames queryNames} method, the checks - * are the same as for queryMBeans except that - * "queryNames" is used instead of - * "queryMBeans" in the JMXNamespacePermission - * objects. Note that a "queryMBeans" permission implies - * the corresponding "queryNames" permission.

      - * - *
    • For the {@link MBeanServer#getClassLoader getClassLoader} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<loaderName>, - * "getClassLoader")}, - * where mbean server name/a> is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * loaderName is the name of the ClassLoader MBean - * which is accessed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#getClassLoaderFor getClassLoaderFor} method, - * the caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "getClassLoaderFor")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which the action - * is performed, in that namespace. - *

      - * - *
    • For the {@link MBeanServer#registerMBean registerMBean} method, the - * caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>, - * "registerMBean")}. Here - * class name is the string returned by {@code - * obj.getClass().getName()} where {@code obj} is the mbean reference, - * is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean which is being - * registered, relative to that namespace. - * - *

    • For the createMBean methods, the caller's - * permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>, - * "instantiate")} and - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>, - * "registerMBean")}, where - * class name is the string passed as first argument to the {@code - * createMBean} method, - * mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean which is being - * created, relative to that namespace. - * - *

    • For the {@link MBeanServer#unregisterMBean unregisterMBean} method, - * the caller's permissions must imply {@link - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String) - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, - * "unregisterMBean")}, - * where mbean server name is the name of the - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of - * namespace is registered, and - * mbean is the name of the MBean on which is - * being unregistered, relative to that namespace. - *

      - *
    - *

    - *

    It must be noted that if all namespaces are local, and all - * local namespaces are implemented by regular MBean servers, that is, there - * are no {@linkplain MBeanServerSupport Virtual Namespaces}, then - * simple {@linkplain javax.management.MBeanPermission MBean Permission} - * checks might be enough to secure an application. - * In that case, it is possible to specify the following {@link - * JMXNamespacePermission} permission in the policy file, which implies all - * other JMX namespace permissions: - *

    - *
    - *     permission javax.management.namespace.JMXNamespacePermission "*::*[]", "*";
    - * 
    - * - * @since 1.7 - */ -public class JMXNamespace - implements JMXNamespaceMBean, MBeanRegistration { - - /** - * The standard value of the {@code type} - * property key that must be used to construct valid {@link - * JMXNamespaceMBean} ObjectNames.
    - * This is {@value #TYPE}. - **/ - public static final String TYPE = "JMXNamespace"; - - /** - * The {@link ObjectName#getKeyPropertyListString keyPropertyListString} - * that must be used to construct valid {@link JMXNamespaceMBean} - * ObjectNames.
    - * This is - * {@value #TYPE_ASSIGNMENT}. - **/ - public static final String TYPE_ASSIGNMENT = "type="+TYPE; - - private volatile MBeanServer mbeanServer; // the mbean server in which - // this MBean is registered. - private volatile ObjectName objectName; // the ObjectName of this MBean. - private final MBeanServer sourceServer; // the MBeanServer within = the - // name space (or the MBean server - // that contains it). - private final String uuid; - - /** - * Creates a new JMXNamespace implemented by means of an MBean Server. - * A namespace is equivalent to an MBeanServer within an MBean Server. - * The {@code sourceServer} provided to this constructor is the MBean Server - * within. - * @param sourceServer the MBean server that implemented by this namespace. - * @see #getSourceServer - */ - public JMXNamespace(MBeanServer sourceServer) { - this.sourceServer = sourceServer; - this.uuid = UUID.randomUUID().toString(); - } - - /** - * This method is part of the {@link MBeanRegistration} interface. - * The {@link JMXNamespace} class uses the {@link MBeanRegistration} - * interface in order to get a reference to the MBean server in which it is - * registered. It also checks the validity of its own ObjectName. - *

    - * This method is called by the MBean server. - * Application classes should never call this method directly. - *

    - * If this method is overridden, the overriding method should call - * {@code super.preRegister(server,name)}. - * @see MBeanRegistration#preRegister MBeanRegistration - * @see JMXNamespaces#getNamespaceObjectName getNamespaceObjectName - * @param name The object name of the MBean. name must be a - * syntactically valid JMXNamespace name, as returned by - * {@link JMXNamespaces#getNamespaceObjectName(java.lang.String) - * getNamespaceObjectName(namespace)}. - * @return The name under which the MBean is to be registered. - * @throws IllegalArgumentException if the name supplied is not valid. - * @throws Exception can be thrown by subclasses. - */ - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - // need to synchronize to protect against multiple registration. - synchronized(this) { - if (objectName != null && ! objectName.equals(name)) - throw new IllegalStateException( - "Already registered under another name: " + objectName); - objectName = validateHandlerName(name); - mbeanServer = server; - } - return name; - } - - /** - * Validate the ObjectName supplied to preRegister. - * This method is introduced to allow standard subclasses to use - * an alternate naming scheme. For instance - if we want to - * reuse JMXNamespace in order to implement sessions... - * It is however only available for subclasses in this package. - **/ - ObjectName validateHandlerName(ObjectName suppliedName) { - if (suppliedName == null) - throw new IllegalArgumentException("Must supply a valid name"); - final String dirName = JMXNamespaces. - normalizeNamespaceName(suppliedName.getDomain()); - final ObjectName handlerName = - JMXNamespaces.getNamespaceObjectName(dirName); - if (!suppliedName.equals(handlerName)) - throw new IllegalArgumentException("invalid name space name: "+ - suppliedName); - return suppliedName; - } - - /** - * This method is part of the {@link MBeanRegistration} interface. - * The {@link JMXNamespace} class uses the {@link MBeanRegistration} - * interface in order to get a reference to the MBean server in which it is - * registered. - *

    - * This method is called by the MBean server. Application classes should - * not call this method directly. Subclasses are free to override this - * method with their own specific behavior - but the overriding method - * shoud still call {@code super.postRegister(registrationDone)}. - * @see MBeanRegistration#postRegister MBeanRegistration - */ - public void postRegister(Boolean registrationDone) { - // nothing to do - } - - /** - * This method is part of the {@link MBeanRegistration} interface. - * The {@link JMXNamespace} class uses the {@link MBeanRegistration} - * interface in order to get a reference to the MBean server in which it is - * registered. - *

    - * This method is called by the MBean server. Application classes should - * not call this method directly. Subclasses are free to override this - * method with their own specific behavior - but the overriding method - * shoud still call {@code super.preDeregister()}. - * @see MBeanRegistration#preDeregister MBeanRegistration - */ - public void preDeregister() throws Exception { - // nothing to do - } - - /** - * This method is part of the {@link MBeanRegistration} interface. - * It allows the {@code JMXNamespace} MBean to perform any operations - * needed after having been unregistered in the MBean server. - *

    - * This method is called by the MBean server. Application classes should - * not call this method directly. If a subclass overrides this - * method, the overriding method shoud call {@code super.postDeregister()}. - * @see MBeanRegistration#postDeregister MBeanRegistration - */ - public void postDeregister() { - // need to synchronize to protect against multiple registration. - synchronized(this) { - mbeanServer = null; - objectName = null; - } - } - - - /** - * Returns the MBeanServer in which this MBean is registered, - * or null. Chiefly of interest for subclasses. - * @return the MBeanServer supplied to {@link #preRegister}. - **/ - public final MBeanServer getMBeanServer() { - return mbeanServer; - } - - /** - * Returns the MBeanServer that contains or emulates the source - * namespace. When a JMXNamespace MBean is registered in an - * MBean server created through the default {@link - * javax.management.MBeanServerBuilder}, the MBeanServer will - * check {@link JMXNamespacePermission} before invoking - * any method on the source MBeanServer of the JMXNamespace. - * See JMX Namespace Permission Checks - * above. - * @return an MBeanServer view of the source namespace - **/ - public MBeanServer getSourceServer() { - return sourceServer; - } - - /** - * Returns the ObjectName with which this MBean was registered, - * or null. Chiefly of interest for subclasses. - * @return the ObjectName supplied to {@link #preRegister}. - **/ - public final ObjectName getObjectName() { - return objectName; - } - - /** - * HandlerName used in traces. - **/ - String getHandlerName() { - final ObjectName name = getObjectName(); - if (name != null) return name.toString(); - return this.toString(); - } - - /** - * In this class, this method returns {@link #getSourceServer - * getSourceServer()}.{@link javax.management.MBeanServer#getMBeanCount - * getMBeanCount()}. - *
    This default behaviour may be redefined in subclasses. - * @throws java.io.IOException can be thrown by subclasses. - */ - public Integer getMBeanCount() throws IOException { - return getSourceServer().getMBeanCount(); - } - - /** - * In this class, this method returns {@link #getSourceServer - * getSourceServer()}.{@link javax.management.MBeanServer#getDomains - * getDomains()}. - *
    This default behaviour may be redefined in subclasses. - * @throws java.io.IOException can be thrown by subclasses. - */ - public String[] getDomains() throws IOException { - return getSourceServer().getDomains(); - } - - /** - * In this class, this method returns {@link #getSourceServer - * getSourceServer()}.{@link javax.management.MBeanServer#getDefaultDomain - * getDefaultDomain()}. - *
    This default behaviour may be redefined in subclasses. - * @throws java.io.IOException can be thrown by subclasses. - */ - public String getDefaultDomain() throws IOException { - return getSourceServer().getDefaultDomain(); - } - - public final String getUUID() { - return uuid; - } - -} diff --git a/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java b/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java deleted file mode 100644 index 4632b410a..000000000 --- a/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java +++ /dev/null @@ -1,96 +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 javax.management.namespace; - -import java.io.IOException; -import java.util.UUID; - -/** - * A {@link JMXNamespace} is an MBean that handles a name space in the - * MBeanServer hierarchical name space. - * @see JMXNamespace - * @since 1.7 - */ -public interface JMXNamespaceMBean { - - // Note: since getDomains(), getDefaultDomain(), and getMBeanCount() - // don't take any ObjectName parameters, the only efficient way - // to get these data is to call the corresponding method on the - // JMXNamespaceMBean that handles the name space. - // - // We need these methods to implement 'cd' (JMXNamespaces.narrowToNamespace) - // correctly. - // - - /** - * Returns the list of domains currently implemented in the name space - * handled by this {@link JMXNamespace}. - * @throws IOException if the domain list cannot be obtained due to - * I/O problems (communication failures etc...). - * @return the list of domains currently implemented in the name space - * handled by this {@link JMXNamespace}. - * @see javax.management.MBeanServerConnection#getDomains - * MBeanServerConnection.getDomains - **/ - public String[] getDomains() throws IOException; - - /** - * Returns the default domain for the name space handled by - * this {@link JMXNamespace}. - * @throws IOException if the default domain cannot be obtained due to - * I/O problems (communication failures etc...). - * @return the default domain for the name space handled by - * this {@link JMXNamespace}. - * @see javax.management.MBeanServerConnection#getDefaultDomain - * MBeanServerConnection.getDefaultDomain - **/ - public String getDefaultDomain() throws IOException; - - /** - * Returns the number of MBeans registered in the name space handled by - * this {@link JMXNamespace}. - * - * @return the number of MBeans registered in the name space handled by - * this {@link JMXNamespace}. - * - * @throws IOException if the MBean count cannot be obtained due to - * I/O problems (communication failures etc...). - * @see javax.management.MBeanServerConnection#getMBeanCount - * MBeanServerConnection.getMBeanCount - */ - public Integer getMBeanCount() throws IOException; - - /** - * Returns a {@link java.util.UUID UUID string} which uniquely identifies - * this {@linkplain JMXNamespace} MBean. - * This information can be used to detect loops in the JMX name space graph. - * @return A unique ID identifying this MBean. - * @throws IOException if the MBean UUID cannot be obtained due to - * I/O problems (communication failures etc...). - */ - public String getUUID() throws IOException; - -} diff --git a/src/share/classes/javax/management/namespace/JMXNamespacePermission.java b/src/share/classes/javax/management/namespace/JMXNamespacePermission.java deleted file mode 100644 index 62608cb06..000000000 --- a/src/share/classes/javax/management/namespace/JMXNamespacePermission.java +++ /dev/null @@ -1,1446 +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 javax.management.namespace; - -import javax.management.*; -import com.sun.jmx.mbeanserver.Util; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.security.Permission; - -/** - *

    A permission controlling access to MBeans located in namespaces. - * If a security manager has been set using {@link - * System#setSecurityManager}, most operations on an MBean mounted in a - * namespace require that the caller's permissions imply a - * JMXNamespacePermission appropriate for the operation. - * This is described in detail in the - * documentation for the - * JMXNamespace - * class.

    - * - *

    As with other {@link Permission} objects, - * a JMXNamespacePermission can represent either a permission that - * you have or a permission that you need. - * When a sensitive operation is being checked for permission, - * a JMXNamespacePermission is constructed - * representing the permission you need. The operation is only - * allowed if the permissions you have {@linkplain #implies imply} the - * permission you need.

    - * - *

    A JMXNamespacePermission contains four items of information:

    - * - *
      - * - *
    • The action.

      - *

      For a permission you need, - * this is one of the actions in the list below. For a permission you have, this is - * a comma-separated list of those actions, or *, - * representing all actions.

      - * - *

      The action is returned by {@link #getActions()}.

      - * - *
    • The MBean Server name.

      - * - *

      For a permission you need, this is the {@linkplain - * javax.management.MBeanServerFactory#getMBeanServerName - * name of the MBeanServer} - * from which the MBean is accessed.

      - * - *

      For a permission you have, this is either the {@linkplain - * javax.management.MBeanServerFactory#getMBeanServerName - * name of the MBeanServer} from which the MBean - * for which you have this permission is accessed, - * or a pattern against which that MBean Server name will be matched.
      - * An {@code mbeanServername} pattern can also be empty, or the single - * character {@code "*"}, both of which match any {@code MBeanServer} name. - * The string {@code "-"} doesn't match any MBeanServer name. - *

      - * - *

      Example:

      - *
      - *   // grant permission to invoke the operation "stop" on any MBean
      - *   // whose name matches "a//**//*:type=JMXConnectorServer" when
      - *   // accessed from any MBeanServer whose name matches myapp.*"
      - *   permission javax.management.namespace.JMXNamespacePermission "myapp.*::stop[a//**//*:type=JMXConnectorServer]", "invoke";
      - * 
      - * - *
    • The member.

      - * - *

      For a permission you need, this is the name of the attribute or - * operation you are accessing. For operations that do not reference - * an attribute or operation, the member is null.

      - * - *

      For a permission you have, this is either the name of an attribute - * or operation you can access, or it is empty or the single character - * "*", both of which grant access to any member.

      - * - *

      There is a special case for actions {@code registerMBean} and - * {@code instantiate}, where for a permission you need, {@code member} - * indicates the name of the class for which you are trying - * to create, instantiate, or register an MBean instance. For a - * permission you have, it is a pattern that will be matched against - * the full class name of the MBean being created, instantiated, or - * registered. - *

      - * - * - *
    • The object name.

      - * - *

      For a permission you need, this is the {@link ObjectName} of the - * MBean you are accessing. It is of the form {@code //} - * where {@code } is the name of the name space for which the - * permission is checked, and {@code } is the name of the MBean - * within that namespace. - *
      - * For operations that do not reference a - * single MBean, the object name is null. It is never an object - * name pattern. - *

      - * - *

      For a permission you have, this is the {@link ObjectName} of the - * MBean or MBeans you can access. It is of the form - * {@code //} - * where {@code } is the name of the name space for which the - * permission is checked, and - * {@code } is the name of the MBean - * within that namespace. Both {@code } and {@code } - * can be patterns. The object name - * may also be empty, which grants access to all MBeans whatever their - * name and namespace. - * When included in a namespace path the special path element - * ** matches any number of sub namespaces - * recursively, but only if used as a complete namespace path element, - * as in **//b//c//D:k=v or a//**//c//D:k=v - * - see ObjectName documentation - * for more details. - *

      - * - * - *
    - * - *

    If you have a JMXNamespacePermission, it allows operations only - * if all four of the items match.

    - * - *

    The MBeanServer name, - * member, and object name - * can be written together - * as a single string, which is the name of this permission. - * The name of the permission is the string returned by {@link - * java.security.Permission#getName() getName()}. - * The format of the string is:

    - * - *
    - * {@code ::[//]} - *
    - * - *

    - * The {@code } is optional. If omitted, {@code "*"} is - * assumed, and these three permission names - * are thus equivalent: - *

    - *
    - * {@code *::[//]}
    - * {@code ::[//]}
    - * {@code [//]}
    - *
    - *

    - * The {@code //} string can be in the form - * of a traditional ObjectName - * pattern - meaning that ? will match any single - * character, and * will match any sequence of characters, - * except {@value - * javax.management.namespace.JMXNamespaces#NAMESPACE_SEPARATOR} - * In addition, when included in a namespace path the special - * path element ** matches any number of sub namespaces - * recursively. - * A {@code //} string of the form - * **//*:* thus means that the permission is - * granted for all MBeans in all namespaces, recursively (see - * below for more details. - *

    - *

    Namespace permission checking may be tricky to configure, depending - * on whether the namespaces crossed to reach the MBean are local or - * remote.
    - * For instance, let a//b//D:k=v be an MBean exposing an - * attribute Foo. - * If namespace a is a plain JMXNamespace pointing to - * a local MBeanServer in the same JVM, then the permissions you need - * to get the attribute Foo will be: - *

    - *
    - *    // granting permission to access attribute 'Foo' of MBean a//b//D:k=v
    - *    // from MBeanServer named 'srv1'
    - *    // This permission will be checked by the MBeanServer that contains 'a'.
    - *    srv1::Foo[a//b//D:k=v]
    - *
    - *    // Since a is local, you also need the following additional permission,
    - *    // which will be checked by the MBeanServer 'srv2' that contains 'b':
    - *    //
    - *    // granting permission to access attribute 'Foo' of MBean b//D:k=v from
    - *    // 'srv2'
    - *    srv2::Foo[b//D:k=v]
    - * 
    - *

    On the other hand, if namespace a is a JMXRemoteNamespace - * pointing to an MBeanServer in a remote JVM, then the only permission you - * need to get the attribute Foo will be: - *

    - *
    - *    // granting permission to access attribute 'Foo' of MBean a//b//D:k=v
    - *    // from 'srv1'
    - *    srv1::Foo[a//b//D:k=v]
    - * 
    - *

    The namespace b resides in the remote JVM, and - * therefore the permissions concerning access to MBeans from - * namespace 'b' will only be checked in the remote JVM, if that JVM is - * configured to do so. - *

    - * - *

    The {@code } is written using the usual syntax for {@link - * ObjectName}. It may contain any legal characters, including - * ]. It is terminated by a ] character - * that is the last character in the string. - *

    - *

    Below are some examples of permission names:

    - *
    - *    // allows access to Foo in 'a//b//*:*' from any MBeanServer in the JVM.
    - *    Foo[a//b//*:*]
    - *
    - *    // allows access to Foo in all subnamespaces of 'a//b', but only for
    - *    // MBeanServers whose name matches 'myapp.*'
    - *    myapp.*::Foo[a//b//**//*:*]
    - *
    - *    // allows access to Foo from all namespaces in the MBeanServer named
    - *    // 'myapp.srv1' - but not recursively.
    - *    myapp.srv1::Foo[*//*:*]
    - * 
    - *

    For instance, the first two permissions listed above - * will let through {@code getAttribute("a//b//D:k=v","Foo");} in - * all MBeanServers, but will block access to - * {@code getAttribute("a//b//c//D:k=v","Foo");} in MBeanServers whose - * name do not start with {@code "myapp."}. - *

    - *

    Depending on how your namespace hierarchy - * is defined some of these wildcard permission names can be useful:

    - *
    - *    // allows access to Foo in all namespaces, recursively.
    - *    //
    - *    *::Foo[**//*:*]
    - *
    - *    // This permission name is the equivalent to the permission names above:
    - *    // Foo[**//*:*] and Foo[] are equivalent.
    - *    //
    - *    Foo[]
    - *
    - *    // This permission name is the equivalent to the two permission names
    - *    // above:
    - *    // Foo[**//*:*], Foo[], Foo are equivalent.
    - *    //
    - *    Foo
    - *
    - *    // allows access to Foo from all namespaces - but not recursively.
    - *    // This wildcard permission complements the previous one: it allows
    - *    // access to 'Foo' from an MBean directly registered in any local namespace.
    - *    //
    - *    Foo[*//*:*]
    - *
    - * 
    - *

    Note on wildcards: In an object name pattern, a path element - * of exactly ** corresponds to a meta - * wildcard that will match any number of sub namespaces. - * See ObjectName documentation - * for more details.

    - * - *

    If {@code ::} is omitted, then one of - * member or object name may be omitted. - * If the object name is omitted, - * the [] may be too (but does not have to be). It is - * not legal to omit all items, that is to have a name - * which is the empty string.

    - *

    If {@code } is present, it must be followed by - * the {@code "::"} separator - otherwise it will be interpreted as - * a {@code member name}. - *

    - * - *

    - * One or more of the MBean Server name, - * member - * or object name may be the character "-", - * which is equivalent to a null value. A null value is implied by - * any value (including another null value) but does not imply any - * other value. - *

    - * - *

    The possible actions are these:

    - * - *
      - *
    • addNotificationListener
    • - *
    • getAttribute
    • - *
    • getClassLoader
    • - *
    • getClassLoaderFor
    • - *
    • getClassLoaderRepository
    • - *
    • getMBeanInfo
    • - *
    • getObjectInstance
    • - *
    • instantiate
    • - *
    • invoke
    • - *
    • isInstanceOf
    • - *
    • queryMBeans
    • - *
    • queryNames
    • - *
    • registerMBean
    • - *
    • removeNotificationListener
    • - *
    • setAttribute
    • - *
    • unregisterMBean
    • - *
    - * - *

    In a comma-separated list of actions, spaces are allowed before - * and after each action.

    - * - * @since 1.7 - */ -public class JMXNamespacePermission extends Permission { - - private static final long serialVersionUID = -2416928705275160661L; - - private static final String WILDPATH = "**" + - JMXNamespaces.NAMESPACE_SEPARATOR + "*"; - - /** - * Actions list. - */ - private static final int AddNotificationListener = 0x00001; - private static final int GetAttribute = 0x00002; - private static final int GetClassLoader = 0x00004; - private static final int GetClassLoaderFor = 0x00008; - private static final int GetClassLoaderRepository = 0x00010; - // No GetDomains because it is not possible to route a call to - // getDomains() on a NamespaceInterceptor - getDomains() doesn't - // have any ObjectName. - // private static final int GetDomains = 0x00020; - private static final int GetMBeanInfo = 0x00040; - private static final int GetObjectInstance = 0x00080; - private static final int Instantiate = 0x00100; - private static final int Invoke = 0x00200; - private static final int IsInstanceOf = 0x00400; - private static final int QueryMBeans = 0x00800; - private static final int QueryNames = 0x01000; - private static final int RegisterMBean = 0x02000; - private static final int RemoveNotificationListener = 0x04000; - private static final int SetAttribute = 0x08000; - private static final int UnregisterMBean = 0x10000; - - /** - * No actions. - */ - private static final int NONE = 0x00000; - - /** - * All actions. - */ - // No GetDomains because it is not possible to route a call to - // getDomains() on a NamespaceInterceptor - getDomains() doesn't - // have any ObjectName. - // - private static final int ALL = - AddNotificationListener | - GetAttribute | - GetClassLoader | - GetClassLoaderFor | - GetClassLoaderRepository | - GetMBeanInfo | - GetObjectInstance | - Instantiate | - Invoke | - IsInstanceOf | - QueryMBeans | - QueryNames | - RegisterMBean | - RemoveNotificationListener | - SetAttribute | - UnregisterMBean; - - /** - * The actions string. - */ - private String actions; - - /** - * The actions mask. - */ - private transient int mask; - - /** - * The name of the MBeanServer in which this permission is checked, or - * granted. If null, is implied by any MBean server name - * but does not imply any non-null MBean server name. - */ - private transient String mbeanServerName; - - /** - * The member that must match. If null, is implied by any member - * but does not imply any non-null member. - */ - private transient String member; - - /** - * The objectName that must match. If null, is implied by any - * objectName but does not imply any non-null objectName. - */ - private transient ObjectName objectName; - - /** - * If objectName is missing from name, then allnames will be - * set to true. - */ - private transient boolean allnames = false; - - /** - * Parse actions parameter. - */ - private void parseActions() { - - int amask; - - if (actions == null) - throw new IllegalArgumentException("JMXNamespaceAccessPermission: " + - "actions can't be null"); - if (actions.equals("")) - throw new IllegalArgumentException("JMXNamespaceAccessPermission: " + - "actions can't be empty"); - - amask = getMask(actions); - - if ((amask & ALL) != amask) - throw new IllegalArgumentException("Invalid actions mask"); - if (amask == NONE) - throw new IllegalArgumentException("Invalid actions mask"); - this.mask = amask; - } - - /** - * Parse name parameter. - */ - private void parseName() { - String name = getName(); - - if (name == null) - throw new IllegalArgumentException("JMXNamespaceAccessPermission name " + - "cannot be null"); - - if (name.equals("")) - throw new IllegalArgumentException("JMXNamespaceAccessPermission name " + - "cannot be empty"); - final int sepIndex = name.indexOf("::"); - if (sepIndex < 0) { - setMBeanServerName("*"); - } else { - setMBeanServerName(name.substring(0,sepIndex)); - } - - /* The name looks like "mbeanServerName::member[objectname]". - We subtract elements from the right as we parse, so after - parsing the objectname we have "class#member" and after parsing the - member we have "class". Each element is optional. */ - - // Parse ObjectName - - final int start = (sepIndex<0)?0:sepIndex+2; - int openingBracket = name.indexOf("[",start); - if (openingBracket == -1) { - // If "[on]" missing then ObjectName("*:*") - // - objectName = null; - allnames = true; - openingBracket=name.length(); - } else { - if (!name.endsWith("]")) { - throw new IllegalArgumentException("JMXNamespaceAccessPermission: " + - "The ObjectName in the " + - "target name must be " + - "included in square " + - "brackets"); - } else { - // Create ObjectName - // - String on = name.substring(openingBracket + 1, - name.length() - 1); - try { - // If "[]" then allnames are implied - // - final ObjectName target; - final boolean all; - if (on.equals("")) { - target = null; - all = true; - } else if (on.equals("-")) { - target = null; - all = false; - } else { - target = new ObjectName(on); - all = false; - } - setObjectName(target,all); - } catch (MalformedObjectNameException e) { - throw new IllegalArgumentException( - "JMXNamespaceAccessPermission: " + - "The target name does " + - "not specify a valid " + - "ObjectName", e); - } - } - } - - final String memberName = name.substring(start,openingBracket); - setMember(memberName); - } - - private void setObjectName(ObjectName target, boolean all) { - if (target != null && - !Util.wildpathmatch(target.getDomain(), WILDPATH)) { - throw new IllegalArgumentException( - "The target name does not contain " + - "any namespace: "+String.valueOf(target)); - } else if (target != null) { - final String domain = target.getDomain(); - final int seplen = JMXNamespaces.NAMESPACE_SEPARATOR.length(); - final int sepc = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR); - if (sepc < 0 || (sepc+seplen)==domain.length()) { - throw new IllegalArgumentException(String.valueOf(target)+ - ": no namespace in domain"); - } - } - objectName = target; - allnames = all; - } - - /** - * Assign fields based on className, member, and objectName - * parameters. - */ -// private void initName(String namespaceName, String member, -// ObjectName objectName, boolean allnames) { -// setNamespace(namespaceName); - private void initName(String mbeanServerName, String member, - ObjectName mbeanName, boolean all) { - setMBeanServerName(mbeanServerName); - setMember(member); - setObjectName(mbeanName, all); - } - - private void setMBeanServerName(String mbeanServerName) { - if (mbeanServerName == null || mbeanServerName.equals("-")) { - this.mbeanServerName = null; - } else if (mbeanServerName.equals("")) { - this.mbeanServerName = "*"; - } else { - this.mbeanServerName = mbeanServerName; - } - } - - private void setMember(String member) { - if (member == null || member.equals("-")) - this.member = null; - else if (member.equals("")) - this.member = "*"; - else - this.member = member; - } - - /** - *

    Create a new JMXNamespacePermission object with the - * specified target name and actions.

    - * - *

    The target name is of the form - * "mbeanServerName::member[objectName]" where each part is - * optional. This target name must not be empty or null. - * If objectName is present, it is of - * the form namespace//MBeanName. - *

    - *

    - * For a permission you need, {@code mbeanServerName} is the - * name of the MBeanServer from - * which {@code objectName} is being accessed. - *

    - *

    - * For a permission you have, {@code mbeanServerName} is the - * name of the MBeanServer from - * which access to {@code objectName} is granted. - * It can also be a pattern, and if omitted, {@code "*"} is assumed, - * meaning that access to {@code objectName} is granted in all - * MBean servers in the JVM. - *

    - * - *

    The actions parameter contains a comma-separated list of the - * desired actions granted on the target name. It must not be - * empty or null.

    - * - * @param name the triplet "mbeanServerName::member[objectName]". - * If objectName is present, it is of - * the form namespace//MBeanName. - * @param actions the action string. - * - * @exception IllegalArgumentException if the name or - * actions is invalid. - */ - public JMXNamespacePermission(String name, String actions) { - super(name); - - parseName(); - - this.actions = actions; - parseActions(); - } - - /** - *

    Create a new JMXNamespacePermission object with the specified - * target name (namespace name, member, object name) and actions.

    - * - *

    The {@code MBeanServer} name, member and object name - * parameters define a target name of the form - * "mbeanServerName::member[objectName]" where each - * part is optional. This will be the result of {@link #getName()} on the - * resultant JMXNamespacePermission. - * If the mbeanServerName is empty or exactly {@code "*"}, then - * "{@code mbeanServerName::}" is omitted in that result. - *

    - * - *

    The actions parameter contains a comma-separated list of the - * desired actions granted on the target name. It must not be - * empty or null.

    - * - * @param mbeanServerName the name of the {@code MBeanServer} to which this - * permission applies. - * May be null or "-", which represents an MBeanServer name - * that is implied by any MBeanServer name but does not imply any other - * MBeanServer name. - * @param member the member to which this permission applies. May - * be null or "-", which represents a member that is - * implied by any member but does not imply any other member. - * @param objectName the object name to which this permission - * applies. - * May be null, which represents an object name that is - * implied by any object name but does not imply any other object - * name. If not null, the {@code objectName} must be of the - * form {@code //} - where {@code } - * can be a domain pattern, and {@code } can be an ObjectName - * pattern. - * For a permission you need, {@code } is the name of the - * name space for which the permission is checked, and {@code } - * is the name of the MBean in that namespace. - * The composed name {@code //} thus represents the - * name of the MBean as seen by the {@code mbeanServerName} containing - * {@code }. - * - * @param actions the action string. - */ - public JMXNamespacePermission( - String mbeanServerName, - String member, - ObjectName objectName, - String actions) { - this(mbeanServerName, member, objectName, false, actions); -// this(member, objectName, false, actions); - } - - /** - *

    Create a new JMXNamespacePermission object with the specified - * MBean Server name, member, and actions.

    - * - *

    The {@code MBeanServer} name and member - * parameters define a target name of the form - * "mbeanServerName::member[]" where each - * part is optional. This will be the result of {@link #getName()} on the - * resultant JMXNamespacePermission. - * If the mbeanServerName is empty or exactly {@code "*"}, then - * "{@code mbeanServerName::}" is omitted in that result. - *

    - * - *

    The actions parameter contains a comma-separated list of the - * desired actions granted on the target name. It must not be - * empty or null.

    - * - * @param mbeanServerName the name of the {@code MBeanServer} to which this - * permission applies. - * May be null or "-", which represents an MBeanServer name - * that is implied by any MBeanServer name but does not imply any other - * MBeanServer name. - * @param member the member to which this permission applies. May - * be null or "-", which represents a member that is - * implied by any member but does not imply any other member. - * @param actions the action string. - */ - public JMXNamespacePermission(String mbeanServerName, - String member, - String actions) { - this(mbeanServerName,member,null,true,actions); - // this(member,null,allnames,actions); - } - - /** - *

    Create a new JMXNamespacePermission object with the specified - * target name (namespace name, member, object name) and actions.

    - * - *

    The MBean Server name, member and object name parameters define a - * target name of the form - * "mbeanServerName::member[objectName]" where each part is - * optional. This will be the result of {@link - * java.security.Permission#getName() getName()} on the - * resultant JMXNamespacePermission.

    - * - *

    The actions parameter contains a comma-separated list of the - * desired actions granted on the target name. It must not be - * empty or null.

    - * - * @param mbeanServerName the name of the {@code MBeanServer} to which this - * permission applies. - * May be null or "-", which represents an MBeanServer name - * that is implied by any MBeanServer name but does not imply any other - * MBeanServer name. - * @param member the member to which this permission applies. May - * be null or "-", which represents a member that is - * implied by any member but does not imply any other member. - * @param objectName the object name to which this permission - * applies. If null, and allnames is false, represents an object - * name that is implied by any object name but does not imply any - * other object name. Otherwise, if allnames is true, it represents - * a meta wildcard that matches all object names. It is equivalent to - * a missing objectName ("[]") in the {@link - * java.security.Permission#getName() name} property. - * @param allnames represent a meta wildcard indicating that the - * objectName was not specified. This implies all objectnames - * that match "*:*" and all object names that match - * "**//*:*" - * @param actions the action string. - */ - private JMXNamespacePermission(String mbeanServerName, - String member, - ObjectName objectName, - boolean allnames, - String actions) { - - super(makeName(mbeanServerName, - member, objectName, allnames)); - initName(mbeanServerName, - member, objectName, allnames); - - this.actions = actions; - parseActions(); - } - - private static String makeName(String mbeanServerName, - String memberName, ObjectName objName, boolean allMBeans) { - final StringBuilder name = new StringBuilder(); - if (mbeanServerName == null) - mbeanServerName = "-"; - if (!mbeanServerName.equals("") && !mbeanServerName.equals("*")) - name.append(mbeanServerName).append("::"); - if (memberName == null) - memberName = "-"; - name.append(memberName); - if (objName == null) { - if (allMBeans) - name.append("[]"); - else - name.append("[-]"); - } else { - final String domain = objName.getDomain(); - final int seplen = JMXNamespaces.NAMESPACE_SEPARATOR.length(); - final int sepc = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR); - if (sepc < 0 || (sepc+seplen)==domain.length()) { - throw new IllegalArgumentException(String.valueOf(objName)+ - ": no namespace in domain"); - } - final String can = objName.getCanonicalName(); - name.append("[").append(can).append("]"); - } - return name.toString(); - } - - /** - * Returns the "canonical string representation" of the actions. That is, - * this method always returns actions in alphabetical order. - * - * @return the canonical string representation of the actions. - */ - public String getActions() { - - if (actions == null) - actions = getActions(this.mask); - - return actions; - } - - /** - * Returns the "canonical string representation" - * of the actions from the mask. - */ - private static String getActions(int mask) { - final StringBuilder sb = new StringBuilder(); - boolean comma = false; - - if ((mask & AddNotificationListener) == AddNotificationListener) { - comma = true; - sb.append("addNotificationListener"); - } - - if ((mask & GetAttribute) == GetAttribute) { - if (comma) sb.append(','); - else comma = true; - sb.append("getAttribute"); - } - - if ((mask & GetClassLoader) == GetClassLoader) { - if (comma) sb.append(','); - else comma = true; - sb.append("getClassLoader"); - } - - if ((mask & GetClassLoaderFor) == GetClassLoaderFor) { - if (comma) sb.append(','); - else comma = true; - sb.append("getClassLoaderFor"); - } - - if ((mask & GetClassLoaderRepository) == GetClassLoaderRepository) { - if (comma) sb.append(','); - else comma = true; - sb.append("getClassLoaderRepository"); - } - - if ((mask & GetMBeanInfo) == GetMBeanInfo) { - if (comma) sb.append(','); - else comma = true; - sb.append("getMBeanInfo"); - } - - if ((mask & GetObjectInstance) == GetObjectInstance) { - if (comma) sb.append(','); - else comma = true; - sb.append("getObjectInstance"); - } - - if ((mask & Instantiate) == Instantiate) { - if (comma) sb.append(','); - else comma = true; - sb.append("instantiate"); - } - - if ((mask & Invoke) == Invoke) { - if (comma) sb.append(','); - else comma = true; - sb.append("invoke"); - } - - if ((mask & IsInstanceOf) == IsInstanceOf) { - if (comma) sb.append(','); - else comma = true; - sb.append("isInstanceOf"); - } - - if ((mask & QueryMBeans) == QueryMBeans) { - if (comma) sb.append(','); - else comma = true; - sb.append("queryMBeans"); - } - - if ((mask & QueryNames) == QueryNames) { - if (comma) sb.append(','); - else comma = true; - sb.append("queryNames"); - } - - if ((mask & RegisterMBean) == RegisterMBean) { - if (comma) sb.append(','); - else comma = true; - sb.append("registerMBean"); - } - - if ((mask & RemoveNotificationListener) == RemoveNotificationListener) { - if (comma) sb.append(','); - else comma = true; - sb.append("removeNotificationListener"); - } - - if ((mask & SetAttribute) == SetAttribute) { - if (comma) sb.append(','); - else comma = true; - sb.append("setAttribute"); - } - - if ((mask & UnregisterMBean) == UnregisterMBean) { - if (comma) sb.append(','); - else comma = true; - sb.append("unregisterMBean"); - } - - // No GetDomains because it is not possible to route a call to - // getDomains() on a NamespaceInterceptor - getDomains() doesn't - // have any ObjectName. - - return sb.toString(); - } - - @Override - public int hashCode() { - return this.getName().hashCode() + this.getActions().hashCode(); - } - - /** - * Converts an action String to an integer action mask. - * - * @param action the action string. - * @return the action mask. - */ - private static int getMask(String action) { - - /* - * BE CAREFUL HERE! PARSING ORDER IS IMPORTANT IN THIS ALGORITHM. - * - * The 'string length' test must be performed for the lengthiest - * strings first. - * - * In this permission if the "unregisterMBean" string length test is - * performed after the "registerMBean" string length test the algorithm - * considers the 'unregisterMBean' action as being the 'registerMBean' - * action and a parsing error is returned. - */ - - int mask = NONE; - - if (action == null) { - return mask; - } - - if (action.equals("*")) { - return ALL; - } - - char[] a = action.toCharArray(); - - int i = a.length - 1; - if (i < 0) - return mask; - - while (i != -1) { - char c; - - // skip whitespace - while ((i!=-1) && ((c = a[i]) == ' ' || - c == '\r' || - c == '\n' || - c == '\f' || - c == '\t')) - i--; - - // check for the known strings - int matchlen; - - // No GetDomains because it is not possible to route a call to - // getDomains() on a NamespaceInterceptor - getDomains() doesn't - // have any ObjectName. - - if (i >= 25 && /* removeNotificationListener */ - (a[i-25] == 'r') && - (a[i-24] == 'e') && - (a[i-23] == 'm') && - (a[i-22] == 'o') && - (a[i-21] == 'v') && - (a[i-20] == 'e') && - (a[i-19] == 'N') && - (a[i-18] == 'o') && - (a[i-17] == 't') && - (a[i-16] == 'i') && - (a[i-15] == 'f') && - (a[i-14] == 'i') && - (a[i-13] == 'c') && - (a[i-12] == 'a') && - (a[i-11] == 't') && - (a[i-10] == 'i') && - (a[i-9] == 'o') && - (a[i-8] == 'n') && - (a[i-7] == 'L') && - (a[i-6] == 'i') && - (a[i-5] == 's') && - (a[i-4] == 't') && - (a[i-3] == 'e') && - (a[i-2] == 'n') && - (a[i-1] == 'e') && - (a[i] == 'r')) { - matchlen = 26; - mask |= RemoveNotificationListener; - } else if (i >= 23 && /* getClassLoaderRepository */ - (a[i-23] == 'g') && - (a[i-22] == 'e') && - (a[i-21] == 't') && - (a[i-20] == 'C') && - (a[i-19] == 'l') && - (a[i-18] == 'a') && - (a[i-17] == 's') && - (a[i-16] == 's') && - (a[i-15] == 'L') && - (a[i-14] == 'o') && - (a[i-13] == 'a') && - (a[i-12] == 'd') && - (a[i-11] == 'e') && - (a[i-10] == 'r') && - (a[i-9] == 'R') && - (a[i-8] == 'e') && - (a[i-7] == 'p') && - (a[i-6] == 'o') && - (a[i-5] == 's') && - (a[i-4] == 'i') && - (a[i-3] == 't') && - (a[i-2] == 'o') && - (a[i-1] == 'r') && - (a[i] == 'y')) { - matchlen = 24; - mask |= GetClassLoaderRepository; - } else if (i >= 22 && /* addNotificationListener */ - (a[i-22] == 'a') && - (a[i-21] == 'd') && - (a[i-20] == 'd') && - (a[i-19] == 'N') && - (a[i-18] == 'o') && - (a[i-17] == 't') && - (a[i-16] == 'i') && - (a[i-15] == 'f') && - (a[i-14] == 'i') && - (a[i-13] == 'c') && - (a[i-12] == 'a') && - (a[i-11] == 't') && - (a[i-10] == 'i') && - (a[i-9] == 'o') && - (a[i-8] == 'n') && - (a[i-7] == 'L') && - (a[i-6] == 'i') && - (a[i-5] == 's') && - (a[i-4] == 't') && - (a[i-3] == 'e') && - (a[i-2] == 'n') && - (a[i-1] == 'e') && - (a[i] == 'r')) { - matchlen = 23; - mask |= AddNotificationListener; - } else if (i >= 16 && /* getClassLoaderFor */ - (a[i-16] == 'g') && - (a[i-15] == 'e') && - (a[i-14] == 't') && - (a[i-13] == 'C') && - (a[i-12] == 'l') && - (a[i-11] == 'a') && - (a[i-10] == 's') && - (a[i-9] == 's') && - (a[i-8] == 'L') && - (a[i-7] == 'o') && - (a[i-6] == 'a') && - (a[i-5] == 'd') && - (a[i-4] == 'e') && - (a[i-3] == 'r') && - (a[i-2] == 'F') && - (a[i-1] == 'o') && - (a[i] == 'r')) { - matchlen = 17; - mask |= GetClassLoaderFor; - } else if (i >= 16 && /* getObjectInstance */ - (a[i-16] == 'g') && - (a[i-15] == 'e') && - (a[i-14] == 't') && - (a[i-13] == 'O') && - (a[i-12] == 'b') && - (a[i-11] == 'j') && - (a[i-10] == 'e') && - (a[i-9] == 'c') && - (a[i-8] == 't') && - (a[i-7] == 'I') && - (a[i-6] == 'n') && - (a[i-5] == 's') && - (a[i-4] == 't') && - (a[i-3] == 'a') && - (a[i-2] == 'n') && - (a[i-1] == 'c') && - (a[i] == 'e')) { - matchlen = 17; - mask |= GetObjectInstance; - } else if (i >= 14 && /* unregisterMBean */ - (a[i-14] == 'u') && - (a[i-13] == 'n') && - (a[i-12] == 'r') && - (a[i-11] == 'e') && - (a[i-10] == 'g') && - (a[i-9] == 'i') && - (a[i-8] == 's') && - (a[i-7] == 't') && - (a[i-6] == 'e') && - (a[i-5] == 'r') && - (a[i-4] == 'M') && - (a[i-3] == 'B') && - (a[i-2] == 'e') && - (a[i-1] == 'a') && - (a[i] == 'n')) { - matchlen = 15; - mask |= UnregisterMBean; - } else if (i >= 13 && /* getClassLoader */ - (a[i-13] == 'g') && - (a[i-12] == 'e') && - (a[i-11] == 't') && - (a[i-10] == 'C') && - (a[i-9] == 'l') && - (a[i-8] == 'a') && - (a[i-7] == 's') && - (a[i-6] == 's') && - (a[i-5] == 'L') && - (a[i-4] == 'o') && - (a[i-3] == 'a') && - (a[i-2] == 'd') && - (a[i-1] == 'e') && - (a[i] == 'r')) { - matchlen = 14; - mask |= GetClassLoader; - } else if (i >= 12 && /* registerMBean */ - (a[i-12] == 'r') && - (a[i-11] == 'e') && - (a[i-10] == 'g') && - (a[i-9] == 'i') && - (a[i-8] == 's') && - (a[i-7] == 't') && - (a[i-6] == 'e') && - (a[i-5] == 'r') && - (a[i-4] == 'M') && - (a[i-3] == 'B') && - (a[i-2] == 'e') && - (a[i-1] == 'a') && - (a[i] == 'n')) { - matchlen = 13; - mask |= RegisterMBean; - } else if (i >= 11 && /* getAttribute */ - (a[i-11] == 'g') && - (a[i-10] == 'e') && - (a[i-9] == 't') && - (a[i-8] == 'A') && - (a[i-7] == 't') && - (a[i-6] == 't') && - (a[i-5] == 'r') && - (a[i-4] == 'i') && - (a[i-3] == 'b') && - (a[i-2] == 'u') && - (a[i-1] == 't') && - (a[i] == 'e')) { - matchlen = 12; - mask |= GetAttribute; - } else if (i >= 11 && /* getMBeanInfo */ - (a[i-11] == 'g') && - (a[i-10] == 'e') && - (a[i-9] == 't') && - (a[i-8] == 'M') && - (a[i-7] == 'B') && - (a[i-6] == 'e') && - (a[i-5] == 'a') && - (a[i-4] == 'n') && - (a[i-3] == 'I') && - (a[i-2] == 'n') && - (a[i-1] == 'f') && - (a[i] == 'o')) { - matchlen = 12; - mask |= GetMBeanInfo; - } else if (i >= 11 && /* isInstanceOf */ - (a[i-11] == 'i') && - (a[i-10] == 's') && - (a[i-9] == 'I') && - (a[i-8] == 'n') && - (a[i-7] == 's') && - (a[i-6] == 't') && - (a[i-5] == 'a') && - (a[i-4] == 'n') && - (a[i-3] == 'c') && - (a[i-2] == 'e') && - (a[i-1] == 'O') && - (a[i] == 'f')) { - matchlen = 12; - mask |= IsInstanceOf; - } else if (i >= 11 && /* setAttribute */ - (a[i-11] == 's') && - (a[i-10] == 'e') && - (a[i-9] == 't') && - (a[i-8] == 'A') && - (a[i-7] == 't') && - (a[i-6] == 't') && - (a[i-5] == 'r') && - (a[i-4] == 'i') && - (a[i-3] == 'b') && - (a[i-2] == 'u') && - (a[i-1] == 't') && - (a[i] == 'e')) { - matchlen = 12; - mask |= SetAttribute; - } else if (i >= 10 && /* instantiate */ - (a[i-10] == 'i') && - (a[i-9] == 'n') && - (a[i-8] == 's') && - (a[i-7] == 't') && - (a[i-6] == 'a') && - (a[i-5] == 'n') && - (a[i-4] == 't') && - (a[i-3] == 'i') && - (a[i-2] == 'a') && - (a[i-1] == 't') && - (a[i] == 'e')) { - matchlen = 11; - mask |= Instantiate; - } else if (i >= 10 && /* queryMBeans */ - (a[i-10] == 'q') && - (a[i-9] == 'u') && - (a[i-8] == 'e') && - (a[i-7] == 'r') && - (a[i-6] == 'y') && - (a[i-5] == 'M') && - (a[i-4] == 'B') && - (a[i-3] == 'e') && - (a[i-2] == 'a') && - (a[i-1] == 'n') && - (a[i] == 's')) { - matchlen = 11; - mask |= QueryMBeans; - } else if (i >= 9 && /* queryNames */ - (a[i-9] == 'q') && - (a[i-8] == 'u') && - (a[i-7] == 'e') && - (a[i-6] == 'r') && - (a[i-5] == 'y') && - (a[i-4] == 'N') && - (a[i-3] == 'a') && - (a[i-2] == 'm') && - (a[i-1] == 'e') && - (a[i] == 's')) { - matchlen = 10; - mask |= QueryNames; - } else if (i >= 5 && /* invoke */ - (a[i-5] == 'i') && - (a[i-4] == 'n') && - (a[i-3] == 'v') && - (a[i-2] == 'o') && - (a[i-1] == 'k') && - (a[i] == 'e')) { - matchlen = 6; - mask |= Invoke; - } else { - // parse error - throw new IllegalArgumentException("Invalid permission: " + - action); - } - - // make sure we didn't just match the tail of a word - // like "ackbarfaccept". Also, skip to the comma. - boolean seencomma = false; - while (i >= matchlen && !seencomma) { - switch(a[i-matchlen]) { - case ',': - seencomma = true; - break; - case ' ': case '\r': case '\n': - case '\f': case '\t': - break; - default: - throw new IllegalArgumentException("Invalid permission: " + - action); - } - i--; - } - - // point i at the location of the comma minus one (or -1). - i -= matchlen; - } - - return mask; - } - - /** - *

    Checks if this JMXNamespacePermission object "implies" the - * specified permission.

    - * - *

    More specifically, this method returns true if:

    - * - *
      - * - *
    • p is an instance of JMXNamespacePermission; and
    • - * - *
    • p has a null mbeanServerName or p's mbeanServerName - * matches this object's mbeanServerName; and
    • - * - *
    • p has a null member or p's member matches this - * object's member; and
    • - * - *
    • p has a null object name or p's - * object name matches this object's object name; and
    • - * - *
    • p's actions are a subset of this object's actions
    • - * - *
    - * - *

    If this object's mbeanServerName is a pattern, then p's - * mbeanServerName is matched against that pattern. An empty - * mbeanServerName is equivalent to "{@code *}". A null - * mbeanServerName is equivalent to "{@code -}".

    - *

    If this object's mbeanServerName is "*" or is - * empty, p's mbeanServerName always matches it.

    - * - *

    If this object's member is "*", p's - * member always matches it.

    - * - *

    If this object's objectName n1 is an object name pattern, - * p's objectName n2 matches it if - * {@link ObjectName#equals n1.equals(n2)} or if - * {@link ObjectName#apply n1.apply(n2)}.

    - * - *

    A permission that includes the queryMBeans action - * is considered to include queryNames as well.

    - * - * @param p the permission to check against. - * @return true if the specified permission is implied by this object, - * false if not. - */ - public boolean implies(Permission p) { - if (!(p instanceof JMXNamespacePermission)) - return false; - - JMXNamespacePermission that = (JMXNamespacePermission) p; - - // Actions - // - // The actions in 'this' permission must be a - // superset of the actions in 'that' permission - // - - /* "queryMBeans" implies "queryNames" */ - if ((this.mask & QueryMBeans) == QueryMBeans) { - if (((this.mask | QueryNames) & that.mask) != that.mask) { - //System.out.println("action [with QueryNames] does not imply"); - return false; - } - } else { - if ((this.mask & that.mask) != that.mask) { - //System.out.println("action does not imply"); - return false; - } - } - - // Target name - // - // The 'mbeanServerName' check is true iff: - // 1) the mbeanServerName in 'this' permission is omitted or "*", or - // 2) the mbeanServerName in 'that' permission is omitted or "*", or - // 3) the mbeanServerName in 'this' permission does pattern - // matching with the mbeanServerName in 'that' permission. - // - // The 'member' check is true iff: - // 1) the member in 'this' member is omitted or "*", or - // 2) the member in 'that' member is omitted or "*", or - // 3) the member in 'this' permission equals the member in - // 'that' permission. - // - // The 'object name' check is true iff: - // 1) the object name in 'this' permission is omitted, or - // 2) the object name in 'that' permission is omitted, or - // 3) the object name in 'this' permission does pattern - // matching with the object name in 'that' permission. - // - - if (that.mbeanServerName == null) { - // bottom is implied - } else if (this.mbeanServerName == null) { - // bottom implies nothing but itself - return false; - } else if (that.mbeanServerName.equals(this.mbeanServerName)) { - // exact match - } else if (!Util.wildmatch(that.mbeanServerName,this.mbeanServerName)) { - return false; // no match - } - - /* Check if this.member implies that.member */ - - if (that.member == null) { - // bottom is implied - } else if (this.member == null) { - // bottom implies nothing but itself - return false; - } else if (this.member.equals("*")) { - // wildcard implies everything (including itself) - } else if (this.member.equals(that.member)) { - // exact match - } else if (!Util.wildmatch(that.member,this.member)) { - return false; // no match - } - - /* Check if this.objectName implies that.objectName */ - - if (that.objectName == null) { - // bottom is implied - } else if (this.objectName == null) { - // bottom implies nothing but itself - if (allnames == false) return false; - } else if (!this.objectName.apply(that.objectName)) { - /* ObjectName.apply returns false if that.objectName is a - wildcard so we also allow equals for that case. This - never happens during real permission checks, but means - the implies relation is reflexive. */ - if (!this.objectName.equals(that.objectName)) - return false; - } - - return true; - } - - /** - * Checks two JMXNamespacePermission objects for equality. Checks - * that obj is an JMXNamespacePermission, and has the same - * name and actions as this object. - *

    - * @param obj the object we are testing for equality with this object. - * @return true if obj is an JMXNamespacePermission, and has the - * same name and actions as this JMXNamespacePermission object. - */ - public boolean equals(Object obj) { - if (obj == this) - return true; - - if (! (obj instanceof JMXNamespacePermission)) - return false; - - JMXNamespacePermission that = (JMXNamespacePermission) obj; - - return (this.mask == that.mask) && - (this.getName().equals(that.getName())); - } - - /** - * Deserialize this object based on its name and actions. - */ - private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException { - in.defaultReadObject(); - parseName(); - parseActions(); - } -} diff --git a/src/share/classes/javax/management/namespace/JMXNamespaceView.java b/src/share/classes/javax/management/namespace/JMXNamespaceView.java deleted file mode 100644 index eacc0f4bc..000000000 --- a/src/share/classes/javax/management/namespace/JMXNamespaceView.java +++ /dev/null @@ -1,300 +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 javax.management.namespace; - -import java.io.IOException; -import java.util.Set; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -/** - * This class makes it possible to navigate easily within a hierarchical - * namespace view. - * - *

    - * MBeanServerConnnection rootConnection = ...;
    - *
    - * // create a view at the local root of the namespace hierarchy.
    - * //
    - * JMXNamespaceView view = new JMXNamespaceView(rootConnection);
    - *
    - * // list all top level namespaces
    - * String[] list = view.list();
    - *
    - * // select one namespace from the list
    - * String whereToGo = ... ;
    - *
    - * // go down to the selected namespace:
    - * view = view.down(whereToGo);
    - * System.out.println("I am now in: " + view.where());
    - * System.out.println("I can see these MBeans:" +
    - *    view.getMBeanServerConnection().queryNames(null,null));
    - *
    - * // list sub namespaces in current view ('whereToGo')
    - * list = view.list();
    - * System.out.println("Here are the sub namespaces of "+view.where()+": "+
    - *                    Arrays.toString(list));
    - *
    - * // go up one level
    - * view = view.up();
    - * System.out.println("I am now back to: " +
    - *    (view.isRoot() ? "root namespace" : view.where()));
    - * 
    - * @since 1.7 - */ -public class JMXNamespaceView { - - private static final ObjectName ALL_NAMESPACES; - static { - try { - ALL_NAMESPACES = ObjectName.getInstance("*" + - JMXNamespaces.NAMESPACE_SEPARATOR + ":"+ - JMXNamespace.TYPE_ASSIGNMENT); - } catch (MalformedObjectNameException x) { - throw new ExceptionInInitializerError(x); - } - } - private static final int NAMESPACE_SEPARATOR_LENGTH = - JMXNamespaces.NAMESPACE_SEPARATOR.length(); - - private final JMXNamespaceView parent; - private final MBeanServerConnection here; - private final String where; - - private static MBeanServerConnection checkRoot(MBeanServerConnection root) { - if (root == null) - throw new IllegalArgumentException( - "namespaceRoot: null is not a valid value"); - return root; - } - - /** - * Creates a view at the top of a JMX namespace hierarchy. - * @param namespaceRoot The {@code MBeanServerConnection} at the - * top of the hierarchy. - */ - public JMXNamespaceView(MBeanServerConnection namespaceRoot) { - this(null,checkRoot(namespaceRoot),""); - } - - // This constructor should remain private. A user can only create - // JMXNamespaceView at the top of the hierarchy. - // JMXNamespaceView sub nodes are created by their parent nodes. - private JMXNamespaceView(JMXNamespaceView parent, - MBeanServerConnection here, String where) { - this.parent = parent; - this.here = here; - this.where = where; - } - - /** - * Returns the path leading to the namespace in this view, from - * the top of the hierarchy. - * @return The path to the namespace in this view. - */ - public String where() { - return where; - } - - /** - * Lists all direct sub namespaces in this view. The returned strings - * do not contain the {@code //} separator. - * - * @return A list of direct sub name spaces accessible from this - * namespace. - * @throws IOException if the attempt to list the namespaces fails because - * of a communication problem. - */ - public String[] list() throws IOException { - final Set names = - here.queryNames(ALL_NAMESPACES,null); - final String[] res = new String[names.size()]; - int i = 0; - for (ObjectName dirName : names) { - final String dir = dirName.getDomain(); - res[i++]=dir.substring(0,dir.length()-NAMESPACE_SEPARATOR_LENGTH); - } - return res; - } - - /** - * Go down into a sub namespace. - * @param namespace the namespace to go down to. It can contain one or - * more {@code //} separators, to traverse intermediate namespaces, but - * it must not begin or end with {@code //} or contain an empty - * intermediate namespace. If it is the empty string, then {@code this} is - * returned. - * @return A view of the named sub namespace. - * @throws IllegalArgumentException if the {@code namespace} begins or - * ends with {@code //}. - */ - public JMXNamespaceView down(String namespace) { - if (namespace.equals("")) return this; - if (namespace.startsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) - throw new IllegalArgumentException(namespace+": can't start with "+ - JMXNamespaces.NAMESPACE_SEPARATOR); - - // This is a convenience to handle paths like xxx//yyy - final String[] elts = - namespace.split(JMXNamespaces.NAMESPACE_SEPARATOR); - - // Go down the path, creating all sub namespaces along the way. - // Usually there will be a single element in the given namespace - // name, but we don't want to forbid things like - // down("xxx//yyy/www"); - // - JMXNamespaceView previous = this; - String cursor = where; - for (String elt : elts) { - // empty path elements are not allowed. It means we - // had something like "xxx////yyy" - if (elt.equals("")) - throw new IllegalArgumentException(namespace+ - ": invalid path element"); - - // compute the "where" for the child. - cursor = JMXNamespaces.concat(cursor, elt); - - // create the child... - final JMXNamespaceView next = - makeJMXNamespaceView(root(), previous, cursor); - - // the current child will be the parent of the next child... - previous = next; - } - - // We return the last child that was created. - return previous; - } - - /** - * Go back up one level. If this view is at the root of the - * hierarchy, returns {@code null}. - * @return A view of the parent namespace, or {@code null} if we're at - * the root of the hierarchy. - */ - public JMXNamespaceView up() { - return parent; - } - - /** - * Tells whether this view is at the root of the hierarchy. - * @return {@code true} if this view is at the root of the hierachy. - */ - public boolean isRoot() { - return parent == null; - } - - /** - * Returns the view at the root of the hierarchy. - * If we are already at the root, this is {@code this}. - * @return the view at the root of the hierarchy. - */ - public JMXNamespaceView root() { - if (parent == null) return this; - return parent.root(); - } - - /** - * A MBeanServerConnection to the namespace shown by this view. - * This is what would have been obtained by doing: - *
    -     *   JMX.narrowToNamespace(this.root().getMBeanServerConnection(),
    -     *       this.where());
    -     * 
    - * @return A MBeanServerConnection to the namespace shown by this view. - */ - public MBeanServerConnection getMBeanServerConnection() { - return here; - } - - /** - *

    Get the name of the JMXNamespaceMBean handling the namespace shown by - * this view, relative to the root of the hierarchy. If we are at the root - * of the hierarchy, this method returns {@code null}.

    - * - *

    You can use this method to make a proxy for the JMXNamespaceMBean - * as follows:

    - * - *
    -     * JMXNamespaceView view = ...;
    -     * ObjectName namespaceMBeanName = view.getJMXNamespaceMBeanName();
    -     * JMXNamespaceMBean namespaceMBean = JMX.newMBeanProxy(
    -     *     view.root().getMBeanServerConnection(), namespaceMBeanName,
    -     *     JMXNamespaceMBean.class);
    -     * 
    - * - * @return The name of the {@code JMXNamespaceMBean} handling the namespace - * shown by this view, or {@code null}. - */ - public ObjectName getJMXNamespaceMBeanName() { - if (parent == null) - return null; - else - return JMXNamespaces.getNamespaceObjectName(where); - } - - @Override - public int hashCode() { - return where.hashCode(); - } - - /** - * Returns true if this object is equal to the given object. The - * two objects are equal if the other object is also a {@code - * JMXNamespaceView} and both objects have the same {@linkplain #root root} - * MBeanServerConnection and the same {@linkplain #where path}. - * @param o the other object to compare to. - * @return true if both objects are equal. - */ - @Override - public boolean equals(Object o) { - if (o==this) return true; - if (! (o instanceof JMXNamespaceView)) return false; - if (!where.equals(((JMXNamespaceView)o).where)) return false; - return root().getMBeanServerConnection().equals( - ((JMXNamespaceView)o).root().getMBeanServerConnection()); - } - - private JMXNamespaceView makeJMXNamespaceView(final JMXNamespaceView root, - final JMXNamespaceView directParent, final String pathFromRoot) { - if (pathFromRoot.equals("")) return root; - - return new JMXNamespaceView(directParent, - narrowToNamespace(root.getMBeanServerConnection(), - pathFromRoot),pathFromRoot); - } - - private MBeanServerConnection narrowToNamespace(MBeanServerConnection root, - String path) { - if (root instanceof MBeanServer) - return JMXNamespaces.narrowToNamespace((MBeanServer)root, path); - return JMXNamespaces.narrowToNamespace(root, path); - } - -} diff --git a/src/share/classes/javax/management/namespace/JMXNamespaces.java b/src/share/classes/javax/management/namespace/JMXNamespaces.java deleted file mode 100644 index ca7244abd..000000000 --- a/src/share/classes/javax/management/namespace/JMXNamespaces.java +++ /dev/null @@ -1,360 +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 javax.management.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.namespace.ObjectNameRouter; -import com.sun.jmx.namespace.serial.RewritingProcessor; -import com.sun.jmx.namespace.RoutingConnectionProxy; -import com.sun.jmx.namespace.RoutingServerProxy; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -/** - * Static constants and utility methods to help work with - * JMX name spaces. There are no instances of this class. - * @since 1.7 - */ -public class JMXNamespaces { - - /** - * A logger for this class. - **/ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - /** Creates a new instance of JMXNamespaces */ - private JMXNamespaces() { - } - - /** - * The name space separator. This is an alias for {@link - * ObjectName#NAMESPACE_SEPARATOR}. - **/ - public static final String NAMESPACE_SEPARATOR = - ObjectName.NAMESPACE_SEPARATOR; - private static final int NAMESPACE_SEPARATOR_LENGTH = - NAMESPACE_SEPARATOR.length(); - - - /** - * Creates a new {@code MBeanServerConnection} proxy on a - * {@linkplain javax.management.namespace sub name space} - * of the given parent. - * - * @param parent The parent {@code MBeanServerConnection} that contains - * the name space. - * @param namespace The {@linkplain javax.management.namespace - * name space} in which to narrow. - * @return A new {@code MBeanServerConnection} proxy that shows the content - * of that name space. - * @throws IllegalArgumentException if either argument is null, - * or the name space does not exist, or if a proxy for that name space - * cannot be created. The {@linkplain Throwable#getCause() cause} of - * this exception will be an {@link InstanceNotFoundException} if and only - * if the name space is found not to exist. - */ - public static MBeanServerConnection narrowToNamespace( - MBeanServerConnection parent, - String namespace) { - if (LOG.isLoggable(Level.FINER)) - LOG.finer("Making MBeanServerConnection for: " +namespace); - return RoutingConnectionProxy.cd(parent, namespace, true); - } - - /** - * Creates a new {@code MBeanServer} proxy on a - * {@linkplain javax.management.namespace sub name space} - * of the given parent. - * - * @param parent The parent {@code MBeanServer} that contains - * the name space. - * @param namespace The {@linkplain javax.management.namespace - * name space} in which to narrow. - * @return A new {@code MBeanServer} proxy that shows the content - * of that name space. - * @throws IllegalArgumentException if either argument is null, - * or the name space does not exist, or if a proxy for that name space - * cannot be created. The {@linkplain Throwable#getCause() cause} of - * this exception will be an {@link InstanceNotFoundException} if and only - * if the name space is found not to exist. - */ - public static MBeanServer narrowToNamespace(MBeanServer parent, - String namespace) { - if (LOG.isLoggable(Level.FINER)) - LOG.finer("Making MBeanServer for: " +namespace); - return RoutingServerProxy.cd(parent, namespace, true); - } - - /** - * Returns an object that is the same as the given object except that - * any {@link ObjectName} it might contain has its domain modified. - * The returned object might be identical to the given object if it - * does not contain any {@code ObjectName} values or if none of them - * were modified. - * This method will replace a prefix ({@code toRemove}) from the path of - * the ObjectNames contained in {@code obj} by another prefix - * ({@code toAdd}). - * Therefore, all contained ObjectNames must have a path that start with - * the given {@code toRemove} prefix. If one of them doesn't, an {@link - * IllegalArgumentException} is thrown. - *

    - * For instance, if {@code obj} contains the ObjectName - * {@code x//y//z//d:k=x}, and {@code toAdd} is {@code v//w}, and - * {@code toRemove} - * is {@code x//y} this method will return a copy of {@code obj} that - * contains {@code v//w//z//d:k=x}.
    - * On the other hand, if {@code obj} contains the ObjectName - * {@code x//y//z//d:k=x}, and {@code toAdd} is {@code v//w}, and - * {@code toRemove} is {@code v} this method - * will raise an exception, because {@code x//y//z//d:k=x} doesn't start - * with {@code v} - *

    - *

    Note: the default implementation of this method can use the - * Java serialization framework to clone and replace ObjectNames in the - * provided {@code obj}. It will usually fail if {@code obj} is not - * Java serializable, or contains objects which are not Java - * serializable. - *

    - * @param obj The object to deep-rewrite - * @param toRemove a prefix already present in contained ObjectNames. - * If {@code toRemove} is the empty string {@code ""}, nothing - * will be removed from the contained ObjectNames. - * @param toAdd the prefix that will replace (@code toRemove} in contained - * ObjectNames. - * If {@code toAdd} is the empty string {@code ""}, nothing - * will be added to the contained ObjectNames. - * @return the rewritten object, or possibly {@code obj} if nothing needed - * to be changed. - * @throws IllegalArgumentException if {@code obj} couldn't be rewritten or - * if {@code toRemove} or {@code toAdd} is null. - **/ - public static T deepReplaceHeadNamespace(T obj, String toRemove, String toAdd) { - final RewritingProcessor processor = - RewritingProcessor.newRewritingProcessor(toAdd,toRemove); - return processor.rewriteOutput(obj); - } - - /** - * Appends {@code namespace} to {@code path}. - * This methods appends {@code namespace} to {@code path} to obtain a - * a full path, and normalizes the result thus obtained: - *
      - *
    • If {@code path} is empty, the full path is - * {@code namespace}.
    • - *
    • Otherwise, if {@code namespace} is empty, - * the full path is {@code path}
    • - *
    • Otherwise, and this is the regular case, the full path is the - * result of the concatenation of - * {@code path}+{@value #NAMESPACE_SEPARATOR}+{@code namespace}
    • - *
    • finally, the full path is normalized: multiple consecutive - * occurrences of {@value #NAMESPACE_SEPARATOR} are replaced by a - * single {@value #NAMESPACE_SEPARATOR} in the result, and trailing - * occurences of {@value #NAMESPACE_SEPARATOR} are removed. - *
    • - *
    - * @param path a name space path prefix - * @param namespace a name space name to append to the path - * @return a syntactically valid name space path, or "" if both parameters - * are null or empty. - * @throws IllegalArgumentException if either argument is null or ends with - * an odd number of {@code /} characters. - **/ - public static String concat(String path, String namespace) { - if (path == null || namespace == null) - throw new IllegalArgumentException("Null argument"); - checkTrailingSlashes(path); - checkTrailingSlashes(namespace); - final String result; - if (path.equals("")) result=namespace; - else if (namespace.equals("")) result=path; - else result=path+NAMESPACE_SEPARATOR+namespace; - return ObjectNameRouter.normalizeNamespacePath(result,false,true,false); - } - - /** - * Returns a syntactically valid name space path. - * If the provided {@code namespace} ends with {@code "//"}, - * recursively strips trailing {@code "//"}. Each sequence of an - * even number of {@code "/"} characters is also replaced by {@code "//"}, - * for example {@code "foo//bar////baz/////buh"} will become - * {@code "foo//bar//baz///buh"}. - * - * @param namespace A name space path - * @return {@code ""} - if the provided {@code namespace} resolves to - * the empty string; otherwise a syntactically valid name space string - * stripped of trailing and redundant {@code "//"}. - * @throws IllegalArgumentException if {@code namespace} is null or - * is not syntactically valid (e.g. it contains - * invalid characters like ':', or it ends with an odd - * number of '/'). - */ - public static String normalizeNamespaceName(String namespace) { - if (namespace == null) - throw new IllegalArgumentException("Null namespace"); - final String sourcePath = - ObjectNameRouter.normalizeNamespacePath(namespace,false,true,false); - if (sourcePath.equals("")) return sourcePath; - - // Will throw an IllegalArgumentException if the namespace name - // is not syntactically valid... - // - getNamespaceObjectName(sourcePath); - return sourcePath; - } - - - /** - * Return a canonical handler name for the provided {@code namespace}, - * The handler name returned will be - * {@link #normalizeNamespaceName normalizeNamespaceName}{@code (namespace) + - * "//:type=JMXNamespace"}. - * - * @param namespace A name space path - * @return a canonical ObjectName for a name space handler. - * @see #normalizeNamespaceName - * @throws IllegalArgumentException if the provided - * {@code namespace} is null or not valid. - */ - public static ObjectName getNamespaceObjectName(String namespace) { - if (namespace == null || namespace.equals("")) - throw new IllegalArgumentException("Null or empty namespace"); - final String sourcePath = - ObjectNameRouter.normalizeNamespacePath(namespace,false, - true,false); - try { - // We could use ObjectName.valueOf here - but throwing an - // IllegalArgumentException that contains just the supplied - // namespace instead of the whole ObjectName seems preferable. - return ObjectName.getInstance(sourcePath+ - NAMESPACE_SEPARATOR+":"+ - JMXNamespace.TYPE_ASSIGNMENT); - } catch (MalformedObjectNameException x) { - throw new IllegalArgumentException("Invalid namespace: " + - namespace,x); - } - } - - /** - * Returns an ObjectName pattern that can be used to query for all MBeans - * contained in the given name space. - * For instance, if {@code namespace="foo//bar"}, this method will - * return {@code "foo//bar//*:*"} - * @return an ObjectName pattern that selects all MBeans in the given - * name space. - **/ - public static ObjectName getWildcardFor(String namespace) { - return insertPath(namespace,ObjectName.WILDCARD); - } - - - /** - * Returns an ObjectName that can be used to access an MBean - * contained in the given name space. - * For instance, if {@code path="foo//bar"}, and - * {@code to="domain:type=Thing"} this method will - * return {@code "foo//bar//domain:type=Thing"} - * @return an ObjectName that can be used to invoke an MBean located in a - * sub name space. - * @throws IllegalArgumentException if {@code path} ends with an - * odd number of {@code /} characters. - **/ - public static ObjectName insertPath(String path, ObjectName to) { - if (path == null || to == null) - throw new IllegalArgumentException("Null argument"); - checkTrailingSlashes(path); - String prefix = path; - if (!prefix.equals("")) - prefix = ObjectNameRouter.normalizeNamespacePath( - prefix + NAMESPACE_SEPARATOR,false,false,false); - return to.withDomain( - ObjectNameRouter.normalizeDomain( - prefix+to.getDomain(),false)); - } - - /** - * Returns the normalized name space path of the name space expected to - * contain {@code ObjectName}. - * For instance, for {@code "foo//domain:type=Thing"} this will be - * {@code "foo"}. For {@code "//foo//bar//domain:type=Thing"} this will be - * {@code "foo//bar"}. For {@code //foo//bar//baz//domain:type=Thing} - * this will be {@code "foo//bar//baz"}. For - * {@code //foo//bar//baz//:type=JMXNamespace} - * this will be {@code "foo//bar"}. - * - * @param name an {@code ObjectName} - * @return the name space path of the name space that could contain such - * a name. If {@code name} has no name space, returns {@code ""}. - * @throws IllegalArgumentException if {@code name} is null. - **/ - public static String getContainingNamespace(ObjectName name) { - return getNormalizedPath(name,true); - } - - - static String getNormalizedPath(ObjectName name, - boolean removeLeadingSep) { - if (name == null) - throw new IllegalArgumentException("Null name"); - String domain = - ObjectNameRouter.normalizeDomain(name.getDomain(),removeLeadingSep); - int end = domain.length(); - - // special case of domain part being a single '/' - // - if (domain.endsWith(NAMESPACE_SEPARATOR+"/")) - return domain.substring(0,end-NAMESPACE_SEPARATOR_LENGTH-1); - - // special case of namespace handler - // - if (domain.endsWith(NAMESPACE_SEPARATOR)) - domain = domain.substring(0,end-NAMESPACE_SEPARATOR_LENGTH); - - int last = domain.lastIndexOf(NAMESPACE_SEPARATOR); - if (last < 0) return ""; - if (last == 0) return domain; - - // special case of domain part starting with '/' - // last=0 is not possible - we took care of this above. - if (domain.charAt(last-1) == '/') last--; - - return domain.substring(0,last); - } - - private static void checkTrailingSlashes(String path) { - int i; - for (i = path.length() - 1; i >= 0 && path.charAt(i) == '/'; i--) - continue; - if (path.length() - i % 2 == 0) - throw new IllegalArgumentException("Path ends with odd number of /"); - } -} diff --git a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java b/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java deleted file mode 100644 index 1c4d29bae..000000000 --- a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java +++ /dev/null @@ -1,809 +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 javax.management.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.Util; -import com.sun.jmx.remote.util.EnvHelp; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.AttributeChangeNotification; - -import javax.management.ClientContext; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServerConnection; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; - -/** - * A {@link JMXNamespace} that will connect to a remote MBeanServer - * by creating a {@link javax.management.remote.JMXConnector} from a - * {@link javax.management.remote.JMXServiceURL}. - *

    - * You can call {@link #connect() connect()} and {@link #close close()} - * several times. This MBean will emit an {@link AttributeChangeNotification} - * when the value of its {@link #isConnected Connected} attribute changes. - *

    - *

    - * The JMX Remote Namespace MBean is not connected until {@link - * #connect() connect()} is explicitly called. The usual sequence of code to - * create a JMX Remote Namespace is thus: - *

    - *
    - *     final String namespace = "mynamespace";
    - *     final ObjectName name = {@link JMXNamespaces#getNamespaceObjectName
    - *       JMXNamespaces.getNamespaceObjectName(namespace)};
    - *     final JMXServiceURL remoteServerURL = .... ;
    - *     final Map optionsMap = .... ;
    - *     final MBeanServer masterMBeanServer = .... ;
    - *     final JMXRemoteNamespace namespaceMBean = {@link #newJMXRemoteNamespace
    - *        JMXRemoteNamespace.newJMXRemoteNamespace(remoteServerURL, optionsMap)};
    - *     masterMBeanServer.registerMBean(namespaceMBean, name);
    - *     namespaceMBean.connect();
    - *     // or: masterMBeanServer.invoke(name, {@link #connect() "connect"}, null, null);
    - * 
    - *

    - * The JMX Remote Namespace MBean will register for {@linkplain - * JMXConnectionNotification JMX Connection Notifications} with its underlying - * {@link JMXConnector}. When a JMX Connection Notification indicates that - * the underlying connection has failed, the JMX Remote Namespace MBean - * closes its underlying connector and switches its {@link #isConnected - * Connected} attribute to false, emitting an {@link - * AttributeChangeNotification}. - *

    - *

    - * At this point, a managing application (or an administrator connected - * through a management console) can attempt to reconnect the - * JMX Remote Namespace MBean by calling its {@link #connect() connect()} method - * again. - *

    - *

    Note that when the connection with the remote namespace fails, or when - * {@link #close} is called, then any notification subscription to - * MBeans registered in that namespace will be lost - unless a custom - * {@linkplain javax.management.event event service} supporting connection-less - * mode was used. - *

    - * @since 1.7 - */ -public class JMXRemoteNamespace - extends JMXNamespace - implements JMXRemoteNamespaceMBean, NotificationEmitter { - - /** - * A logger for this class. - */ - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER; - - - // This connection listener is used to listen for connection events from - // the underlying JMXConnector. It is used in particular to maintain the - // "connected" state in this MBean. - // - private class ConnectionListener implements NotificationListener { - private ConnectionListener() { - } - public void handleNotification(Notification notification, - Object handback) { - if (!(notification instanceof JMXConnectionNotification)) - return; - final JMXConnectionNotification cn = - (JMXConnectionNotification)notification; - final String type = cn.getType(); - if (JMXConnectionNotification.CLOSED.equals(type) - || JMXConnectionNotification.FAILED.equals(type)) { - checkState(this,cn,(JMXConnector)handback); - } - } - } - - // When the JMXRemoteNamespace is originally created, it is not connected, - // which means that the source MBeanServer should be one that throws - // exceptions for most methods. When it is subsequently connected, - // the methods should be forwarded to the MBeanServerConnection. - // We handle this using MBeanServerConnectionWrapper. The - // MBeanServerConnection that is supplied to the constructor of - // MBeanServerConnectionWrapper is ignored (and in fact it is null) - // because the one that is actually used is the one supplied by the - // override of getMBeanServerConnection(). - private static class JMXRemoteNamespaceDelegate - extends MBeanServerConnectionWrapper { - private volatile JMXRemoteNamespace parent=null; - - JMXRemoteNamespaceDelegate() { - super(null,null); - } - @Override - public MBeanServerConnection getMBeanServerConnection() { - return parent.getMBeanServerConnection(); - } - @Override - public ClassLoader getDefaultClassLoader() { - return parent.getDefaultClassLoader(); - } - - // Because this class is instantiated in the super() call from the - // constructor of JMXRemoteNamespace, it cannot be an inner class. - // This method achieves the effect that an inner class would have - // had, of giving the class a reference to the outer "this". - synchronized void initParentOnce(JMXRemoteNamespace parent) { - if (this.parent != null) - throw new UnsupportedOperationException("parent already set"); - this.parent=parent; - - } - - } - - private static final MBeanNotificationInfo connectNotification = - new MBeanNotificationInfo(new String[] { - AttributeChangeNotification.ATTRIBUTE_CHANGE}, - "Connected", - "Emitted when the Connected state of this object changes"); - - private static AtomicLong seqNumber = new AtomicLong(0); - - private final NotificationBroadcasterSupport broadcaster; - private final ConnectionListener listener; - private final JMXServiceURL jmxURL; - private final Map optionsMap; - - private volatile MBeanServerConnection server = null; - private volatile JMXConnector conn = null; - private volatile ClassLoader defaultClassLoader = null; - - /** - * Creates a new instance of {@code JMXRemoteNamespace}. - *

    - * This constructor is provided for subclasses. - * To create a new instance of {@code JMXRemoteNamespace} call - * {@link #newJMXRemoteNamespace - * JMXRemoteNamespace.newJMXRemoteNamespace(sourceURL, optionsMap)}. - *

    - * @param sourceURL a JMX service URL that can be used to {@linkplain - * #connect() connect} to the - * source MBean Server. The source MBean Server is the remote - * MBean Server which contains the MBeans that will be mirrored - * in this namespace. - * @param optionsMap the options map that will be passed to the - * {@link JMXConnectorFactory} when {@linkplain - * JMXConnectorFactory#newJMXConnector creating} the - * {@link JMXConnector} used to {@linkplain #connect() connect} - * to the remote source MBean Server. Can be null, which is - * equivalent to an empty map. - * @see #newJMXRemoteNamespace JMXRemoteNamespace.newJMXRemoteNamespace - * @see #connect - */ - protected JMXRemoteNamespace(JMXServiceURL sourceURL, - Map optionsMap) { - super(new JMXRemoteNamespaceDelegate()); - ((JMXRemoteNamespaceDelegate)super.getSourceServer()). - initParentOnce(this); - - // URL must not be null. - if (sourceURL == null) - throw new IllegalArgumentException("Null URL"); - this.jmxURL = sourceURL; - this.broadcaster = - new NotificationBroadcasterSupport(connectNotification); - - // handles options - this.optionsMap = unmodifiableMap(optionsMap); - - // handles (dis)connection events - this.listener = new ConnectionListener(); - } - - // returns un unmodifiable view of a map. - private static Map unmodifiableMap(Map aMap) { - if (aMap == null || aMap.isEmpty()) - return Collections.emptyMap(); - return Collections.unmodifiableMap(aMap); - } - - /** - * Returns the {@code JMXServiceURL} that is (or will be) used to - * connect to the remote name space.

    - * @see #connect - * @return The {@code JMXServiceURL} used to connect to the remote - * name space. - */ - public JMXServiceURL getJMXServiceURL() { - return jmxURL; - } - - /** - * In this class, this method never returns {@code null}, and the - * address returned is the {@link #getJMXServiceURL JMXServiceURL} - * that is used by this object to {@linkplain #connect} to the remote - * name space.

    - * This behaviour might be overriden by subclasses, if needed. - * For instance, a subclass might want to return {@code null} if it - * doesn't want to expose that JMXServiceURL. - */ - public JMXServiceURL getAddress() { - return getJMXServiceURL(); - } - - private Map getEnvMap() { - return optionsMap; - } - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) { - broadcaster.addNotificationListener(listener, filter, handback); - } - - /** - * A subclass that needs to send its own notifications must override - * this method in order to return an {@link MBeanNotificationInfo - * MBeanNotificationInfo[]} array containing both its own notification - * infos and the notification infos of its super class.

    - * The implementation should probably look like: - *

    -     *      final MBeanNotificationInfo[] myOwnNotifs = { .... };
    -     *      final MBeanNotificationInfo[] parentNotifs =
    -     *            super.getNotificationInfo();
    -     *      final Set mergedResult =
    -     *            new HashSet();
    -     *      mergedResult.addAll(Arrays.asList(myOwnNotifs));
    -     *      mergedResult.addAll(Arrays.asList(parentNotifs));
    -     *      return mergeResult.toArray(
    -     *             new MBeanNotificationInfo[mergedResult.size()]);
    -     * 
    - */ - public MBeanNotificationInfo[] getNotificationInfo() { - return broadcaster.getNotificationInfo(); - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - broadcaster.removeNotificationListener(listener); - } - - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - broadcaster.removeNotificationListener(listener, filter, handback); - } - - private static long getNextSeqNumber() { - return seqNumber.getAndIncrement(); - } - - - /** - * Sends a notification to registered listeners. Before the notification - * is sent, the following steps are performed: - *
    • - * If {@code n.getSequenceNumber() <= 0} set it to the next available - * sequence number.
    • - *
    • If {@code n.getSource() == null}, set it to the value returned by {@link - * #getObjectName getObjectName()}. - *
    - *

    This method can be called by subclasses in order to send their own - * notifications. - * In that case, these subclasses might also need to override - * {@link #getNotificationInfo} in order to declare their own - * {@linkplain MBeanNotificationInfo notification types}. - *

    - * @param n The notification to send to registered listeners. - * @see javax.management.NotificationBroadcasterSupport - * @see #getNotificationInfo - **/ - protected void sendNotification(Notification n) { - if (n.getSequenceNumber()<=0) - n.setSequenceNumber(getNextSeqNumber()); - if (n.getSource()==null) - n.setSource(getObjectName()); - broadcaster.sendNotification(n); - } - - private void checkState(ConnectionListener listener, - JMXConnectionNotification cn, - JMXConnector emittingConnector) { - - // Due to the asynchronous handling of notifications, it is - // possible that this method is called for a JMXConnector - // (or connection) which is already closed and replaced by a newer - // one. - // - // This method attempts to determine the real state of the - // connection - which might be different from what the notification - // says. - // - // This is quite complex logic - because we try not to hold any - // lock while evaluating the true value of the connected state, - // while anyone might also call close() or connect() from a - // different thread. - // The method switchConnection() (called from here too) also has the - // same kind of complex logic: - // - // We use the JMXConnector has a handback to the notification listener - // (emittingConnector) in order to be able to determine whether the - // notification concerns the current connector in use, or an older - // one. The 'emittingConnector' is the connector from which the - // notification originated. This could be an 'old' connector - as - // closed() and connect() could already have been called before the - // notification arrived. So what we do is to compare the - // 'emittingConnector' with the current connector, to see if the - // notification actually comes from the curent connector. - // - boolean remove = false; - - // whether the emittingConnector is already 'removed' - synchronized (this) { - if (this.conn != emittingConnector || - JMXConnectionNotification.FAILED.equals(cn.getType())) - remove = true; - } - - // We need to unregister our listener from this 'removed' connector. - // This is the only place where we remove the listener. - // - if (remove) { - try { - // This may fail if the connector is already closed. - // But better unregister anyway... - // - emittingConnector.removeConnectionNotificationListener( - listener,null, - emittingConnector); - } catch (Exception x) { - LOG.log(Level.FINE, - "Failed to unregister connection listener"+x); - LOG.log(Level.FINEST, - "Failed to unregister connection listener",x); - } - try { - // This may fail if the connector is already closed. - // But better call close twice and get an exception than - // leaking... - // - emittingConnector.close(); - } catch (Exception x) { - LOG.log(Level.FINEST, - "Failed to close old connector " + - "(failure was expected): "+x); - } - } - - // Now we checked whether our current connector is still alive. - // - boolean closed = false; - final JMXConnector thisconn = this.conn; - try { - if (thisconn != null) - thisconn.getConnectionId(); - } catch (IOException x) { - LOG.finest("Connector already closed: "+x); - closed = true; - } - - // We got an IOException - the connector is not connected. - // Need to forget it and switch our state to closed. - // - if (closed) { - switchConnection(thisconn,null,null); - try { - // Usually this will fail... Better call close twice - // and get an exception than leaking... - // - if (thisconn != emittingConnector || !remove) - thisconn.close(); - } catch (IOException x) { - LOG.log(Level.FINEST, - "Failed to close connector (failure was expected): " - +x); - } - } - } - - private final void switchConnection(JMXConnector oldc, - JMXConnector newc, - MBeanServerConnection mbs) { - boolean connect = false; - boolean close = false; - synchronized (this) { - if (oldc != conn) { - if (newc != null) { - try { - newc.close(); - } catch (IOException x) { - LOG.log(Level.FINEST, - "Failed to close connector",x); - } - } - return; - } - if (conn == null && newc != null) connect=true; - if (newc == null && conn != null) close = true; - conn = newc; - server = mbs; - } - if (connect || close) { - boolean oldstate = close; - boolean newstate = connect; - final ObjectName myName = getObjectName(); - - // In the uncommon case where the MBean is connected before - // being registered, myName can be null... - // If myName is null - we use 'this' as the source instead... - // - final Object source = (myName==null)?this:myName; - final AttributeChangeNotification acn = - new AttributeChangeNotification(source, - getNextSeqNumber(),System.currentTimeMillis(), - String.valueOf(source)+ - (newstate?" connected":" closed"), - "Connected", - "boolean", - Boolean.valueOf(oldstate), - Boolean.valueOf(newstate)); - sendNotification(acn); - } - } - - private void close(JMXConnector c) { - try { - if (c != null) c.close(); - } catch (Exception x) { - // OK: we're gonna throw the original exception later. - LOG.finest("Ignoring exception when closing connector: "+x); - } - } - - private JMXConnector connect(JMXServiceURL url, Map env) - throws IOException { - final JMXConnector c = newJMXConnector(url, env); - c.connect(env); - return c; - } - - /** - *

    Creates a new JMXConnector with the specified {@code url} and - * {@code env} options map. The default implementation of this method - * returns {@link JMXConnectorFactory#newJMXConnector - * JMXConnectorFactory.newJMXConnector(jmxURL, env)}. Subclasses can - * override this method to customize behavior.

    - * - * @param url The JMXServiceURL of the remote server. - * @param optionsMap An options map that will be passed to the - * {@link JMXConnectorFactory} when {@linkplain - * JMXConnectorFactory#newJMXConnector creating} the - * {@link JMXConnector} that can connect to the remote source - * MBean Server. - * @return A JMXConnector to use to connect to the remote server - * @throws IOException if the connector could not be created. - * @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map) - * @see #JMXRemoteNamespace - */ - protected JMXConnector newJMXConnector(JMXServiceURL url, - Map optionsMap) throws IOException { - return JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap); - } - - /** - *

    Called when a new connection is established using {@link #connect} - * so that subclasses can customize the connection. The default - * implementation of this method effectively does the following:

    - * - *
    -     * MBeanServerConnection mbsc = {@link JMXConnector#getMBeanServerConnection()
    -     *                               jmxc.getMBeanServerConnection()};
    -     * try {
    -     *     return {@link ClientContext#withDynamicContext
    -     *             ClientContext.withDynamicContext(mbsc)};
    -     * } catch (IllegalArgumentException e) {
    -     *     return mbsc;
    -     * }
    -     * 
    - * - *

    In other words, it arranges for the client context to be forwarded - * to the remote MBean Server if the remote MBean Server supports contexts; - * otherwise it ignores the client context.

    - * - *

    Example: connecting to a remote namespace

    - * - *

    A subclass that wanted to narrow into a namespace of - * the remote MBeanServer might look like this:

    - * - *
    -     * class JMXRemoteSubNamespace extends JMXRemoteNamespace {
    -     *     private final String subnamespace;
    -     *
    -     *     JMXRemoteSubNamespace(
    -     *             JMXServiceURL url, Map{@code } env, String subnamespace) {
    -     *        super(url, env);
    -     *        this.subnamespace = subnamespace;
    -     *     }
    -     *
    -     *     {@code @Override}
    -     *     protected MBeanServerConnection getMBeanServerConnection(
    -     *             JMXConnector jmxc) throws IOException {
    -     *         MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
    -     *         return {@link JMXNamespaces#narrowToNamespace(MBeanServerConnection,String)
    -     *                 JMXNamespaces.narrowToNamespace(mbsc, subnamespace)};
    -     *     }
    -     * }
    -     * 
    - * - *

    Example: using the Event Service for notifications

    - * - *

    Some connectors may have been designed to work with an earlier - * version of the JMX API, and may not have been upgraded to use - * the {@linkplain javax.management.event Event Service} defined in - * this version of the JMX API. In that case, and if the remote - * server to which this JMXRemoteNamespace connects also contains - * namespaces, it may be necessary to configure explicitly an {@linkplain - * javax.management.event.EventClientDelegate#newForwarder Event Client - * Forwarder} on the remote server side, and to force the use of an {@link - * EventClient} on this client side.

    - * - *

    A subclass of {@link JMXRemoteNamespace} can provide an - * implementation of {@code getMBeanServerConnection} that will force - * notification subscriptions to flow through an {@link EventClient} over - * a legacy protocol. It can do so by overriding this method in the - * following way:

    - * - *
    -     * class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
    -     *     JMXRemoteEventClientNamespace(JMXServiceURL url, {@code Map} env) {
    -     *         super(url, env);
    -     *     }
    -     *
    -     *     {@code @Override}
    -     *     protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
    -     *             throws IOException {
    -     *         MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
    -     *         return EventClient.getEventClientConnection(mbsc);
    -     *     }
    -     * }
    -     * 
    - * - *

    - * Note that the remote server also needs to provide an {@link - * javax.management.event.EventClientDelegateMBean}: configuring only - * the client side (this object) is not enough.

    - * - *

    In summary, this technique should be used if the remote server - * supports JMX namespaces, but uses a JMX Connector Server whose - * implementation does not transparently use the new Event Service - * (as would be the case with the JMXMPConnectorServer implementation - * from the reference implementation of the JMX Remote API 1.0 - * specification).

    - * - * @param jmxc the newly-created {@code JMXConnector}. - * - * @return an {@code MBeanServerConnection} connected to the remote - * MBeanServer. - * - * @throws IOException if the connection cannot be made. If this method - * throws {@code IOException} then the calling {@link #connect()} method - * will also fail with an {@code IOException}. - * - * @see #connect - */ - protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc) - throws IOException { - final MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); - try { - return ClientContext.withDynamicContext(mbsc); - } catch (IllegalArgumentException e) { - LOG.log(Level.FINER, "ClientContext.withDynamicContext", e); - return mbsc; - } - } - - /** - * {@inheritDoc} - * - *

    The sequence of events when this method is called includes, - * effectively, the following code:

    - * - *
    -     * JMXServiceURL url = {@link #getJMXServiceURL getJMXServiceURL}();
    -     * JMXConnector jmxc = {@link #newJMXConnector newJMXConnector}(url, env);
    -     * jmxc.connect();
    -     * MBeanServerConnection mbsc = {@link #getMBeanServerConnection(JMXConnector)
    -     *                               getMBeanServerConnection}(jmxc);
    -     * 
    - * - *

    Here, {@code env} is a {@code Map} containing the entries from the - * {@code optionsMap} that was passed to the {@linkplain #JMXRemoteNamespace - * constructor} or to the {@link #newJMXRemoteNamespace newJMXRemoteNamespace} - * factory method.

    - * - *

    Subclasses can customize connection behavior by overriding the - * {@code getJMXServiceURL}, {@code newJMXConnector}, or - * {@code getMBeanServerConnection} methods.

    - */ - public void connect() throws IOException { - LOG.fine("connecting..."); - final Map env = - new HashMap(getEnvMap()); - try { - // XXX: We should probably document this... - // This allows to specify a loader name - which will be - // retrieved from the parent MBeanServer. - defaultClassLoader = - EnvHelp.resolveServerClassLoader(env,getMBeanServer()); - } catch (InstanceNotFoundException x) { - final IOException io = - new IOException("ClassLoader not found"); - io.initCause(x); - throw io; - } - env.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,defaultClassLoader); - final JMXServiceURL url = getJMXServiceURL(); - final JMXConnector aconn = connect(url,env); - final MBeanServerConnection msc; - try { - msc = getMBeanServerConnection(aconn); - aconn.addConnectionNotificationListener(listener,null,aconn); - } catch (IOException io) { - close(aconn); - throw io; - } catch (RuntimeException x) { - close(aconn); - throw x; - } - - switchConnection(conn,aconn,msc); - - LOG.fine("connected."); - } - - public void close() throws IOException { - if (conn == null) return; - LOG.fine("closing..."); - // System.err.println(toString()+": closing..."); - conn.close(); - // System.err.println(toString()+": connector closed"); - switchConnection(conn,null,null); - LOG.fine("closed."); - // System.err.println(toString()+": closed"); - } - - MBeanServerConnection getMBeanServerConnection() { - if (conn == null) - throw newRuntimeIOException("getMBeanServerConnection: not connected"); - return server; - } - - // Better than throwing UndeclaredThrowableException ... - private RuntimeException newRuntimeIOException(String msg) { - final IllegalStateException illegal = new IllegalStateException(msg); - return Util.newRuntimeIOException(new IOException(msg,illegal)); - } - - /** - * Returns the default class loader used by the underlying - * {@link JMXConnector}. - * @return the default class loader used when communicating with the - * remote source MBean server. - **/ - ClassLoader getDefaultClassLoader() { - if (conn == null) - throw newRuntimeIOException("getMBeanServerConnection: not connected"); - return defaultClassLoader; - } - - public boolean isConnected() { - // This is a pleonasm - return (conn != null) && (server != null); - } - - - /** - * This name space handler will automatically {@link #close} its - * connection with the remote source in {@code preDeregister}. - **/ - @Override - public void preDeregister() throws Exception { - try { - close(); - } catch (IOException x) { - LOG.fine("Failed to close properly - exception ignored: " + x); - LOG.log(Level.FINEST, - "Failed to close properly - exception ignored",x); - } - super.preDeregister(); - } - - /** - * This method calls {@link - * javax.management.MBeanServerConnection#getMBeanCount - * getMBeanCount()} on the remote namespace. - * @throws java.io.IOException if an {@link IOException} is raised when - * communicating with the remote source namespace. - */ - @Override - public Integer getMBeanCount() throws IOException { - return getMBeanServerConnection().getMBeanCount(); - } - - /** - * This method returns the result of calling {@link - * javax.management.MBeanServerConnection#getDomains - * getDomains()} on the remote namespace. - * @throws java.io.IOException if an {@link IOException} is raised when - * communicating with the remote source namespace. - */ - @Override - public String[] getDomains() throws IOException { - return getMBeanServerConnection().getDomains(); - } - - /** - * This method returns the result of calling {@link - * javax.management.MBeanServerConnection#getDefaultDomain - * getDefaultDomain()} on the remote namespace. - * @throws java.io.IOException if an {@link IOException} is raised when - * communicating with the remote source namespace. - */ - @Override - public String getDefaultDomain() throws IOException { - return getMBeanServerConnection().getDefaultDomain(); - } - - /** - * Creates a new instance of {@code JMXRemoteNamespace}. - * @param sourceURL a JMX service URL that can be used to connect to the - * source MBean Server. The source MBean Server is the remote - * MBean Server which contains the MBeans that will be mirrored - * in this namespace. - * @param optionsMap An options map that will be passed to the - * {@link JMXConnectorFactory} when {@linkplain - * JMXConnectorFactory#newJMXConnector creating} the - * {@link JMXConnector} used to connect to the remote source - * MBean Server. Can be null, which is equivalent to an empty map. - * @see #JMXRemoteNamespace JMXRemoteNamespace(sourceURL,optionsMap) - * @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map) - */ - public static JMXRemoteNamespace newJMXRemoteNamespace( - JMXServiceURL sourceURL, - Map optionsMap) { - return new JMXRemoteNamespace(sourceURL, optionsMap); - } -} diff --git a/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java b/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java deleted file mode 100644 index 18b0fb86d..000000000 --- a/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java +++ /dev/null @@ -1,96 +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 javax.management.namespace; - -import java.io.IOException; -import javax.management.remote.JMXServiceURL; - -/** - * A {@link JMXNamespaceMBean} that will connect to a remote MBeanServer - * by creating a {@link javax.management.remote.JMXConnector} from a - * {@link javax.management.remote.JMXServiceURL}. - * You can call {@link #connect connect()} and {@link #close close()} - * several times. - * @since 1.7 - */ -public interface JMXRemoteNamespaceMBean - extends JMXNamespaceMBean { - - /** - * Connects to the underlying remote source name space, if not already - * {@link #isConnected connected}. - * If connected, do nothing. Otherwise, creates a new connector from the - * {@link javax.management.remote.JMXServiceURL JMXServiceURL} provided at - * creation time, and connects to the remote source name space. - *

    - * The source MBeans will not appear in the target name space until the - * JMXRemoteNamespaceMBean is connected. - *

    - * It is possible to call {@code connect()}, {@link #close close()}, and - * {@code connect()} again. - * However, closing the connection with the remote name space may cause - * notification listeners to be lost, unless the client explicitly uses - * the new {@linkplain javax.management.event JMX event service}. - *

    - * @throws IOException if connection to the remote source name space fails. - * @see #isConnected isConnected - **/ - public void connect() - throws IOException; - - /** - * Closes the connection with the remote source name space. - * If the connection is already closed, do nothing. - * Otherwise, closes the underlying {@link - * javax.management.remote.JMXConnector}. - *

    Once closed, it is possible to reopen the connection by - * calling {@link #connect connect}. - *

    - * @throws IOException if the connection to the remote source name space - * can't be closed properly. - * @see #isConnected isConnected - **/ - public void close() - throws IOException; - - /** - * Tells whether the connection to the remote source name space is opened. - * @see #connect connect - * @see #close close - * @return {@code true} if connected. - **/ - public boolean isConnected(); - - /** - * Returns the {@link JMXServiceURL} address that points to the remote name - * space mirrored by this {@link JMXNamespaceMBean JMXNamespace MBean}, - * if available. - * @return The {@link JMXServiceURL} address that points to the remote name - * space mirrored by this {@link JMXNamespaceMBean JMXNamespace MBean}, - * or {@code null}. - */ - public JMXServiceURL getAddress(); -} diff --git a/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java b/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java deleted file mode 100644 index 7eeda961e..000000000 --- a/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java +++ /dev/null @@ -1,702 +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 javax.management.namespace; - -import com.sun.jmx.mbeanserver.Util; -import java.io.IOException; -import java.io.ObjectInputStream; -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.MBeanServerConnection; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.OperationsException; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.loading.ClassLoaderRepository; - -/** - *

    An object of this class implements the MBeanServer interface - * and, for each of its methods forwards the request to a wrapped - * {@link MBeanServerConnection} object. - * Some methods of the {@link MBeanServer} interface do not have - * any equivalent in {@link MBeanServerConnection}. In that case, an - * {@link UnsupportedOperationException} will be thrown. - * - *

    A typical use of this class is to apply a {@link QueryExp} object locally, - * on an MBean that resides in a remote MBeanServer. Since an - * MBeanServerConnection is not an MBeanServer, it cannot be passed - * to the setMBeanServer() method of the {@link QueryExp} - * object. However, this object can.

    - * - * @since 1.7 - */ -public class MBeanServerConnectionWrapper - implements MBeanServer { - - private final MBeanServerConnection wrapped; - private final ClassLoader defaultCl; - - /** - * Construct a new object that implements {@link MBeanServer} by - * forwarding its methods to the given {@link MBeanServerConnection}. - * This constructor is equivalent to {@link #MBeanServerConnectionWrapper( - * MBeanServerConnection, ClassLoader) MBeanServerConnectionWrapper(wrapped, - * null)}. - * - * @param wrapped the {@link MBeanServerConnection} to which methods - * are to be forwarded. This parameter can be null, in which case the - * {@code MBeanServerConnection} will typically be supplied by overriding - * {@link #getMBeanServerConnection}. - */ - public MBeanServerConnectionWrapper(MBeanServerConnection wrapped) { - this(wrapped, null); - } - - /** - * Construct a new object that implements {@link MBeanServer} by - * forwarding its methods to the given {@link MBeanServerConnection}. - * The {@code defaultCl} parameter specifies the value to be returned - * by {@link #getDefaultClassLoader}. A null value is equivalent to - * {@link Thread#getContextClassLoader()}. - * - * @param wrapped the {@link MBeanServerConnection} to which methods - * are to be forwarded. This parameter can be null, in which case the - * {@code MBeanServerConnection} will typically be supplied by overriding - * {@link #getMBeanServerConnection}. - * @param defaultCl the value to be returned by {@link - * #getDefaultClassLoader}. A null value is equivalent to the current - * thread's {@linkplain Thread#getContextClassLoader()}. - */ - public MBeanServerConnectionWrapper(MBeanServerConnection wrapped, - ClassLoader defaultCl) { - this.wrapped = wrapped; - this.defaultCl = (defaultCl == null) ? - Thread.currentThread().getContextClassLoader() : defaultCl; - } - - /** - * Returns an MBeanServerConnection. This method is called each time - * an operation must be invoked on the underlying MBeanServerConnection. - * The default implementation returns the MBeanServerConnection that - * was supplied to the constructor of this MBeanServerConnectionWrapper. - **/ - protected MBeanServerConnection getMBeanServerConnection() { - return wrapped; - } - - /** - * Returns the default class loader passed to the constructor. If the - * value passed was null, then the returned value will be the - * {@linkplain Thread#getContextClassLoader() context class loader} at the - * time this object was constructed. - * - * @return the ClassLoader that was passed to the constructor. - **/ - public ClassLoader getDefaultClassLoader() { - return defaultCl; - } - - /** - *

    This method is called each time an IOException is raised when - * trying to forward an operation to the underlying - * MBeanServerConnection, as a result of calling - * {@link #getMBeanServerConnection()} or as a result of invoking the - * operation on the returned connection. Since the methods in - * {@link MBeanServer} are not declared to throw {@code IOException}, - * this method must return a {@code RuntimeException} to be thrown - * instead. Typically, the original {@code IOException} will be in the - * {@linkplain Throwable#getCause() cause chain} of the {@code - * RuntimeException}.

    - * - *

    Subclasses may redefine this method if they need to perform any - * specific handling of IOException (logging etc...).

    - * - * @param x The raised IOException. - * @param method The name of the method in which the exception was - * raised. This is one of the methods of the MBeanServer - * interface. - * - * @return A RuntimeException that should be thrown by the caller. - * In this default implementation, this is a - * {@link RuntimeException} wrapping x. - **/ - protected RuntimeException wrapIOException(IOException x, String method) { - return Util.newRuntimeIOException(x); - } - - // Take care of getMBeanServerConnection returning null. - // - private synchronized MBeanServerConnection connection() - throws IOException { - final MBeanServerConnection c = getMBeanServerConnection(); - if (c == null) - throw new IOException("MBeanServerConnection unavailable"); - return c; - } - - //-------------------------------------------- - //-------------------------------------------- - // - // Implementation of the MBeanServer interface - // - //-------------------------------------------- - //-------------------------------------------- - - /** - * Forward this method to the - * wrapped object. - */ - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - try { - connection().addNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw wrapIOException(x,"addNotificationListener"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public void addNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - try { - connection().addNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw wrapIOException(x,"addNotificationListener"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public ObjectInstance createMBean(String className, ObjectName name) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - try { - return connection().createMBean(className, name); - } catch (IOException x) { - throw wrapIOException(x,"createMBean"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public ObjectInstance createMBean(String className, ObjectName name, - Object params[], String signature[]) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException { - try { - return connection().createMBean(className, name, - params, signature); - } catch (IOException x) { - throw wrapIOException(x,"createMBean"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - try { - return connection().createMBean(className, name, loaderName); - } catch (IOException x) { - throw wrapIOException(x,"createMBean"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public ObjectInstance createMBean(String className, - ObjectName name, - ObjectName loaderName, - Object params[], - String signature[]) - throws - ReflectionException, - InstanceAlreadyExistsException, - MBeanRegistrationException, - MBeanException, - NotCompliantMBeanException, - InstanceNotFoundException { - try { - return connection().createMBean(className, name, loaderName, - params, signature); - } catch (IOException x) { - throw wrapIOException(x,"createMBean"); - } - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - * @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - throw new UnsupportedOperationException("deserialize"); - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - * @deprecated see {@link MBeanServer#deserialize(String,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - throw new UnsupportedOperationException("deserialize"); - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - * @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[]) - * MBeanServer} - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, - byte[] data) - throws - InstanceNotFoundException, - OperationsException, - ReflectionException { - throw new UnsupportedOperationException("deserialize"); - } - - /** - * Forward this method to the - * wrapped object. - */ - public Object getAttribute(ObjectName name, String attribute) - throws - MBeanException, - AttributeNotFoundException, - InstanceNotFoundException, - ReflectionException { - try { - return connection().getAttribute(name, attribute); - } catch (IOException x) { - throw wrapIOException(x,"getAttribute"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - try { - return connection().getAttributes(name, attributes); - } catch (IOException x) { - throw wrapIOException(x,"getAttributes"); - } - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - */ - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - throw new UnsupportedOperationException("getClassLoader"); - } - - /** - * Returns the {@linkplain #getDefaultClassLoader() default class loader}. - * This behavior can be changed by subclasses. - */ - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - return getDefaultClassLoader(); - } - - /** - *

    Returns a {@link ClassLoaderRepository} based on the class loader - * returned by {@link #getDefaultClassLoader()}.

    - * @return a {@link ClassLoaderRepository} that contains a single - * class loader, returned by {@link #getDefaultClassLoader()}. - **/ - public ClassLoaderRepository getClassLoaderRepository() { - // We return a new ClassLoaderRepository each time this method is - // called. This is by design, because there's no guarantee that - // getDefaultClassLoader() will always return the same class loader. - return Util.getSingleClassLoaderRepository(getDefaultClassLoader()); - } - - /** - * Forward this method to the - * wrapped object. - */ - public String getDefaultDomain() { - try { - return connection().getDefaultDomain(); - } catch (IOException x) { - throw wrapIOException(x,"getDefaultDomain"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public String[] getDomains() { - try { - return connection().getDomains(); - } catch (IOException x) { - throw wrapIOException(x,"getDomains"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public Integer getMBeanCount() { - try { - return connection().getMBeanCount(); - } catch (IOException x) { - throw wrapIOException(x,"getMBeanCount"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public MBeanInfo getMBeanInfo(ObjectName name) - throws - InstanceNotFoundException, - IntrospectionException, - ReflectionException { - try { - return connection().getMBeanInfo(name); - } catch (IOException x) { - throw wrapIOException(x,"getMBeanInfo"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - try { - return connection().getObjectInstance(name); - } catch (IOException x) { - throw wrapIOException(x,"getObjectInstance"); - } - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - */ - public Object instantiate(String className) - throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("instantiate"); - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - */ - public Object instantiate(String className, - Object params[], - String signature[]) - throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("instantiate"); - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - */ - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("instantiate"); - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - */ - public Object instantiate(String className, ObjectName loaderName, - Object params[], String signature[]) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("instantiate"); - } - - /** - * Forward this method to the - * wrapped object. - */ - public Object invoke(ObjectName name, String operationName, - Object params[], String signature[]) - throws - InstanceNotFoundException, - MBeanException, - ReflectionException { - try { - return connection().invoke(name,operationName,params,signature); - } catch (IOException x) { - throw wrapIOException(x,"invoke"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - try { - return connection().isInstanceOf(name, className); - } catch (IOException x) { - throw wrapIOException(x,"isInstanceOf"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public boolean isRegistered(ObjectName name) { - try { - return connection().isRegistered(name); - } catch (IOException x) { - throw wrapIOException(x,"isRegistered"); - } - } - - /** - * Forward this method to the - * wrapped object. - * If an IOException is raised, returns an empty Set. - */ - public Set queryMBeans(ObjectName name, QueryExp query) { - try { - return connection().queryMBeans(name, query); - } catch (IOException x) { - throw wrapIOException(x,"queryMBeans"); - //return Collections.emptySet(); - } - } - - /** - * Forward this method to the - * wrapped object. - * If an IOException is raised, returns an empty Set. - */ - public Set queryNames(ObjectName name, QueryExp query) { - try { - return connection().queryNames(name, query); - } catch (IOException x) { - throw wrapIOException(x,"queryNames"); - //return Collections.emptySet(); - } - } - - /** - * Throws an {@link UnsupportedOperationException}. This behavior can - * be changed by subclasses. - */ - public ObjectInstance registerMBean(Object object, ObjectName name) - throws - InstanceAlreadyExistsException, - MBeanRegistrationException, - NotCompliantMBeanException { - throw new UnsupportedOperationException("registerMBean"); - } - - /** - * Forward this method to the - * wrapped object. - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - connection().removeNotificationListener(name, listener); - } catch (IOException x) { - throw wrapIOException(x,"removeNotificationListener"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - connection().removeNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw wrapIOException(x,"removeNotificationListener"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public void removeNotificationListener(ObjectName name, - ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - connection().removeNotificationListener(name, listener); - } catch (IOException x) { - throw wrapIOException(x,"removeNotificationListener"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public void removeNotificationListener(ObjectName name, - ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - try { - connection().removeNotificationListener(name, listener, - filter, handback); - } catch (IOException x) { - throw wrapIOException(x,"removeNotificationListener"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public void setAttribute(ObjectName name, Attribute attribute) - throws - InstanceNotFoundException, - AttributeNotFoundException, - InvalidAttributeValueException, - MBeanException, - ReflectionException { - try { - connection().setAttribute(name, attribute); - } catch (IOException x) { - throw wrapIOException(x,"setAttribute"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - try { - return connection().setAttributes(name, attributes); - } catch (IOException x) { - throw wrapIOException(x,"setAttributes"); - } - } - - /** - * Forward this method to the - * wrapped object. - */ - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - try { - connection().unregisterMBean(name); - } catch (IOException x) { - throw wrapIOException(x,"unregisterMBean"); - } - } - - //---------------- - // PRIVATE METHODS - //---------------- - -} diff --git a/src/share/classes/javax/management/namespace/MBeanServerSupport.java b/src/share/classes/javax/management/namespace/MBeanServerSupport.java deleted file mode 100644 index ea070ae26..000000000 --- a/src/share/classes/javax/management/namespace/MBeanServerSupport.java +++ /dev/null @@ -1,1321 +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 javax.management.namespace; - -import com.sun.jmx.defaults.JmxProperties; -import com.sun.jmx.mbeanserver.Util; -import java.io.ObjectInputStream; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.TreeSet; -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.DynamicMBean; -import javax.management.DynamicWrapperMBean; -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.IntrospectionException; -import javax.management.InvalidAttributeValueException; -import javax.management.JMRuntimeException; -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.NotificationBroadcaster; -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.RuntimeOperationsException; -import javax.management.loading.ClassLoaderRepository; - -/** - *

    Base class for custom implementations of the {@link MBeanServer} - * interface. The commonest use of this class is as the {@linkplain - * JMXNamespace#getSourceServer() source server} for a {@link - * JMXNamespace}, although this class can be used anywhere an {@code - * MBeanServer} instance is required. Note that the usual ways to - * obtain an {@code MBeanServer} instance are either to use {@link - * java.lang.management.ManagementFactory#getPlatformMBeanServer() - * ManagementFactory.getPlatformMBeanServer()} or to use the {@code - * newMBeanServer} or {@code createMBeanServer} methods from {@link - * javax.management.MBeanServerFactory MBeanServerFactory}. {@code - * MBeanServerSupport} is for certain cases where those are not - * appropriate.

    - * - *

    There are two main use cases for this class: special-purpose MBeanServer implementations, - * and namespaces containing Virtual MBeans. The next - * sections explain these use cases.

    - * - *

    In the simplest case, a subclass needs to implement only two methods:

    - * - *
      - *
    • - * {@link #getNames getNames} which returns the name of - * all MBeans handled by this {@code MBeanServer}. - *
    • - *
    • - * {@link #getDynamicMBeanFor getDynamicMBeanFor} which returns a - * {@link DynamicMBean} that can be used to invoke operations and - * obtain meta data (MBeanInfo) on a given MBean. - *
    • - *
    - * - *

    Subclasses can create such {@link DynamicMBean} MBeans on the fly - for - * instance, using the class {@link javax.management.StandardMBean}, just for - * the duration of an MBeanServer method call.

    - * - *

    Special-purpose MBeanServer implementations

    - * - *

    In some cases - * the general-purpose {@code MBeanServer} that you get from - * {@link javax.management.MBeanServerFactory MBeanServerFactory} is not - * appropriate. You might need different security checks, or you might - * want a mock {@code MBeanServer} suitable for use in tests, or you might - * want a simplified and optimized {@code MBeanServer} for a special purpose.

    - * - *

    As an example of a special-purpose {@code MBeanServer}, the class {@link - * javax.management.QueryNotificationFilter QueryNotificationFilter} constructs - * an {@code MBeanServer} instance every time it filters a notification, - * with just one MBean that represents the notification. Although it could - * use {@code MBeanServerFactory.newMBeanServer}, a special-purpose {@code - * MBeanServer} will be quicker to create, use less memory, and have simpler - * methods that execute faster.

    - * - *

    Here is an example of a special-purpose {@code MBeanServer} - * implementation that contains exactly one MBean, which is specified at the - * time of creation.

    - * - *
    - * public class SingletonMBeanServer extends MBeanServerSupport {
    - *     private final ObjectName objectName;
    - *     private final DynamicMBean mbean;
    - *
    - *     public SingletonMBeanServer(ObjectName objectName, DynamicMBean mbean) {
    - *         this.objectName = objectName;
    - *         this.mbean = mbean;
    - *     }
    - *
    - *     @Override
    - *     protected {@code Set} {@link #getNames getNames}() {
    - *         return Collections.singleton(objectName);
    - *     }
    - *
    - *     @Override
    - *     public DynamicMBean {@link #getDynamicMBeanFor
    - *                                getDynamicMBeanFor}(ObjectName name)
    - *             throws InstanceNotFoundException {
    - *         if (objectName.equals(name))
    - *             return mbean;
    - *         else
    - *             throw new InstanceNotFoundException(name);
    - *     }
    - * }
    - * 
    - * - *

    Using this class, you could make an {@code MBeanServer} that contains - * a {@link javax.management.timer.Timer Timer} MBean like this:

    - * - *
    - *     Timer timer = new Timer();
    - *     DynamicMBean mbean = new {@link javax.management.StandardMBean
    - *                                     StandardMBean}(timer, TimerMBean.class);
    - *     ObjectName name = new ObjectName("com.example:type=Timer");
    - *     MBeanServer timerMBS = new SingletonMBeanServer(name, mbean);
    - * 
    - * - *

    When {@code getDynamicMBeanFor} always returns the same object for the - * same name, as here, notifications work in the expected way: if the object - * is a {@link NotificationEmitter} then listeners can be added using - * {@link MBeanServer#addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) MBeanServer.addNotificationListener}. If - * {@code getDynamicMBeanFor} does not always return the same object for the - * same name, more work is needed to make notifications work, as described - * below.

    - * - *

    Namespaces containing Virtual MBeans

    - * - *

    Virtual MBeans are MBeans that do not exist as Java objects, - * except transiently while they are being accessed. This is useful when - * there might be very many of them, or when keeping track of their creation - * and deletion might be expensive or hard. For example, you might have one - * MBean per system process. With an ordinary {@code MBeanServer}, you would - * have to list the system processes in order to create an MBean object for - * each one, and you would have to track the arrival and departure of system - * processes in order to create or delete the corresponding MBeans. With - * Virtual MBeans, you only need the MBean for a given process at the exact - * point where it is referenced with a call such as - * {@link MBeanServer#getAttribute MBeanServer.getAttribute}.

    - * - *

    Here is an example of an {@code MBeanServer} implementation that has - * one MBean for every system property. The system property {@code "java.home"} - * is represented by the MBean called {@code - * com.example:type=Property,name="java.home"}, with an attribute called - * {@code Value} that is the value of the property.

    - * - *
    - * public interface PropertyMBean {
    - *     public String getValue();
    - * }
    - *
    - * public class PropsMBS extends MBeanServerSupport {
    - *     public static class PropertyImpl implements PropertyMBean {
    - *         private final String name;
    - *
    - *         public PropertyImpl(String name) {
    - *             this.name = name;
    - *         }
    - *
    - *         public String getValue() {
    - *             return System.getProperty(name);
    - *         }
    - *     }
    - *
    - *     @Override
    - *     public DynamicMBean {@link #getDynamicMBeanFor
    - *                                getDynamicMBeanFor}(ObjectName name)
    - *             throws InstanceNotFoundException {
    - *
    - *         // Check that the name is a legal one for a Property MBean
    - *         ObjectName namePattern = ObjectName.valueOf(
    - *                     "com.example:type=Property,name=\"*\"");
    - *         if (!namePattern.apply(name))
    - *             throw new InstanceNotFoundException(name);
    - *
    - *         // Extract the name of the property that the MBean corresponds to
    - *         String propName = ObjectName.unquote(name.getKeyProperty("name"));
    - *         if (System.getProperty(propName) == null)
    - *             throw new InstanceNotFoundException(name);
    - *
    - *         // Construct and return a transient MBean object
    - *         PropertyMBean propMBean = new PropertyImpl(propName);
    - *         return new StandardMBean(propMBean, PropertyMBean.class, false);
    - *     }
    - *
    - *     @Override
    - *     protected {@code Set} {@link #getNames getNames}() {
    - *         {@code Set names = new TreeSet();}
    - *         Properties props = System.getProperties();
    - *         for (String propName : props.stringPropertyNames()) {
    - *             ObjectName objectName = ObjectName.valueOf(
    - *                     "com.example:type=Property,name=" +
    - *                     ObjectName.quote(propName));
    - *             names.add(objectName);
    - *         }
    - *         return names;
    - *     }
    - * }
    - * 
    - * - *

    Because the {@code getDynamicMBeanFor} method - * returns a different object every time it is called, the default handling - * of notifications will not work, as explained below. - * In this case it does not matter, because the object returned by {@code - * getDynamicMBeanFor} is not a {@code NotificationEmitter}, so {@link - * MBeanServer#addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) MBeanServer.addNotificationListener} will - * always fail. But if we wanted to extend {@code PropsMBS} so that the MBean - * for property {@code "foo"} emitted a notification every time that property - * changed, we would need to do it as shown below. (Because there is no API to - * be informed when a property changes, this code assumes that some other code - * calls the {@code propertyChanged} method every time a property changes.)

    - * - *
    - * public class PropsMBS {
    - *     ...as above...
    - *
    - *     private final {@link VirtualEventManager} vem = new VirtualEventManager();
    - *
    - *     @Override
    - *     public NotificationEmitter {@link #getNotificationEmitterFor
    - *                                       getNotificationEmitterFor}(
    - *             ObjectName name) throws InstanceNotFoundException {
    - *         getDynamicMBeanFor(name);  // check that the name is valid
    - *         return vem.{@link VirtualEventManager#getNotificationEmitterFor
    - *                           getNotificationEmitterFor}(name);
    - *     }
    - *
    - *     public void propertyChanged(String name, String newValue) {
    - *         ObjectName objectName = ObjectName.valueOf(
    - *                 "com.example:type=Property,name=" + ObjectName.quote(name));
    - *         Notification n = new Notification(
    - *                 "com.example.property.changed", objectName, 0L,
    - *                 "Property " + name + " changed");
    - *         n.setUserData(newValue);
    - *         vem.{@link VirtualEventManager#publish publish}(objectName, n);
    - *     }
    - * }
    - * 
    - * - *

    MBean creation and deletion

    - * - *

    MBean creation through {@code MBeanServer.createMBean} is disabled - * by default. Subclasses which need to support MBean creation - * through {@code createMBean} need to implement a single method {@link - * #createMBean(String, ObjectName, ObjectName, Object[], String[], - * boolean)}.

    - * - *

    Similarly MBean registration and unregistration through {@code - * registerMBean} and {@code unregisterMBean} are disabled by default. - * Subclasses which need to support MBean registration and - * unregistration will need to implement {@link #registerMBean registerMBean} - * and {@link #unregisterMBean unregisterMBean}.

    - * - *

    Notifications

    - * - *

    By default {@link MBeanServer#addNotificationListener(ObjectName, - * NotificationListener, NotificationFilter, Object) addNotificationListener} - * is accepted for an MBean {@code name} if {@link #getDynamicMBeanFor - * getDynamicMBeanFor}(name) returns an object that is a - * {@link NotificationEmitter}. That is appropriate if - * {@code getDynamicMBeanFor}(name) always returns the - * same object for the same {@code name}. But with - * Virtual MBeans, every call to {@code getDynamicMBeanFor} returns a new object, - * which is discarded as soon as the MBean request has finished. - * So a listener added to that object would be immediately forgotten.

    - * - *

    The simplest way for a subclass that defines Virtual MBeans - * to support notifications is to create a private {@link VirtualEventManager} - * and override the method {@link - * #getNotificationEmitterFor getNotificationEmitterFor} as follows:

    - * - *
    - *     private final VirtualEventManager vem = new VirtualEventManager();
    - *
    - *     @Override
    - *     public NotificationEmitter getNotificationEmitterFor(
    - *             ObjectName name) throws InstanceNotFoundException {
    - *         // Check that the name is a valid Virtual MBean.
    - *         // This is the easiest way to do that, but not always the
    - *         // most efficient:
    - *         getDynamicMBeanFor(name);
    - *
    - *         // Return an object that supports add/removeNotificationListener
    - *         // through the VirtualEventManager.
    - *         return vem.getNotificationEmitterFor(name);
    - *     }
    - * 
    - * - *

    A notification {@code n} can then be sent from the Virtual MBean - * called {@code name} by calling {@link VirtualEventManager#publish - * vem.publish}(name, n). See the example - * above.

    - * - * @since 1.7 - */ -public abstract class MBeanServerSupport implements MBeanServer { - - /** - * A logger for this class. - */ - private static final Logger LOG = - JmxProperties.NAMESPACE_LOGGER; - - /** - *

    Make a new {@code MBeanServerSupport} instance.

    - */ - protected MBeanServerSupport() { - } - - /** - *

    Returns a dynamically created handle that makes it possible to - * access the named MBean for the duration of a method call.

    - * - *

    An easy way to create such a {@link DynamicMBean} handle is, for - * instance, to create a temporary MXBean instance and to wrap it in - * an instance of - * {@link javax.management.StandardMBean}. - * This handle should remain valid for the duration of the call - * but can then be discarded.

    - * @param name the name of the MBean for which a request was received. - * @return a {@link DynamicMBean} handle that can be used to invoke - * operations on the named MBean. - * @throws InstanceNotFoundException if no such MBean is supposed - * to exist. - */ - public abstract DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException; - - /** - *

    Subclasses should implement this method to return - * the names of all MBeans handled by this object instance.

    - * - *

    The object returned by getNames() should be safely {@linkplain - * Set#iterator iterable} even in the presence of other threads that may - * cause the set of names to change. Typically this means one of the - * following:

    - * - *
      - *
    • the returned set of names is always the same; or - *
    • the returned set of names is an object such as a {@link - * java.util.concurrent.CopyOnWriteArraySet CopyOnWriteArraySet} that is - * safely iterable even if the set is changed by other threads; or - *
    • a new Set is constructed every time this method is called. - *
    - * - * @return the names of all MBeans handled by this object. - */ - protected abstract Set getNames(); - - /** - *

    List names matching the given pattern. - * The default implementation of this method calls {@link #getNames()} - * and returns the subset of those names matching {@code pattern}.

    - * - * @param pattern an ObjectName pattern - * @return the list of MBean names that match the given pattern. - */ - protected Set getMatchingNames(ObjectName pattern) { - return Util.filterMatchingNames(pattern, getNames()); - } - - /** - *

    Returns a {@link NotificationEmitter} which can be used to - * subscribe or unsubscribe for notifications with the named - * mbean.

    - * - *

    The default implementation of this method calls {@link - * #getDynamicMBeanFor getDynamicMBeanFor(name)} and returns that object - * if it is a {@code NotificationEmitter}, otherwise null. See above for further discussion of notification - * handling.

    - * - * @param name The name of the MBean whose notifications are being - * subscribed, or unsuscribed. - * - * @return A {@link NotificationEmitter} that can be used to subscribe or - * unsubscribe for notifications emitted by the named MBean, or {@code - * null} if the MBean does not emit notifications and should not be - * considered as a {@code NotificationEmitter}. - * - * @throws InstanceNotFoundException if {@code name} is not the name of - * an MBean in this {@code MBeanServer}. - */ - public NotificationEmitter getNotificationEmitterFor(ObjectName name) - throws InstanceNotFoundException { - DynamicMBean mbean = getDynamicMBeanFor(name); - if (mbean instanceof NotificationEmitter) - return (NotificationEmitter) mbean; - else - return null; - } - - private NotificationEmitter getNonNullNotificationEmitterFor( - ObjectName name) - throws InstanceNotFoundException { - NotificationEmitter emitter = getNotificationEmitterFor(name); - if (emitter == null) { - IllegalArgumentException iae = new IllegalArgumentException( - "Not a NotificationEmitter: " + name); - throw new RuntimeOperationsException(iae); - } - return emitter; - } - - /** - *

    Creates a new MBean in the MBean name space. - * This operation is not supported in this base class implementation.

    - * The default implementation of this method always throws an {@link - * UnsupportedOperationException} - * wrapped in a {@link RuntimeOperationsException}.

    - * - *

    Subclasses may redefine this method to provide an implementation. - * All the various flavors of {@code MBeanServer.createMBean} methods - * will eventually call this method. A subclass that wishes to - * support MBean creation through {@code createMBean} thus only - * needs to provide an implementation for this one method.

    - * - *

    A subclass implementation of this method should respect the contract - * of the various {@code createMBean} methods in the {@link MBeanServer} - * interface, in particular as regards exception wrapping.

    - * - * @param className The class name of the MBean to be instantiated. - * @param name The object name of the MBean. May be null. - * @param params An array containing the parameters of the - * constructor to be invoked. - * @param signature An array containing the signature of the - * constructor to be invoked. - * @param loaderName The object name of the class loader to be used. - * @param useCLR This parameter is {@code true} when this method - * is called from one of the {@code MBeanServer.createMBean} methods - * whose signature does not include the {@code ObjectName} of an - * MBean class loader to use for loading the MBean class. - * - * @return An ObjectInstance, containing the - * ObjectName and the Java class name of the newly - * instantiated MBean. If the contained ObjectName - * is n, the contained Java class name is - * {@link javax.management.MBeanServer#getMBeanInfo - * getMBeanInfo(n)}.getClassName(). - * - * @exception ReflectionException Wraps a - * java.lang.ClassNotFoundException or a - * java.lang.Exception that occurred when trying to - * invoke the MBean's constructor. - * @exception InstanceAlreadyExistsException The MBean is already - * under the control of the MBean server. - * @exception MBeanRegistrationException The - * preRegister (MBeanRegistration - * interface) method of the MBean has thrown an exception. The - * MBean will not be registered. - * @exception RuntimeMBeanException If the MBean's constructor or its - * {@code preRegister} or {@code postRegister} method threw - * a {@code RuntimeException}. If the postRegister - * (MBeanRegistration interface) method of the MBean throws a - * RuntimeException, the createMBean method will - * throw a RuntimeMBeanException, although the MBean creation - * and registration succeeded. In such a case, the MBean will be actually - * registered even though the createMBean method - * threw an exception. Note that RuntimeMBeanException can - * also be thrown by preRegister, in which case the MBean - * will not be registered. - * @exception MBeanException The constructor of the MBean has - * thrown an exception - * @exception NotCompliantMBeanException This class is not a JMX - * compliant MBean - * @exception InstanceNotFoundException The specified class loader - * is not registered in the MBean server. - * @exception RuntimeOperationsException Wraps either: - *
      - *
    • a java.lang.IllegalArgumentException: The className - * passed in parameter is null, the ObjectName passed in - * parameter contains a pattern or no ObjectName is specified - * for the MBean; or
    • - *
    • an {@code UnsupportedOperationException} if creating MBeans is not - * supported by this {@code MBeanServer} implementation. - *
    - */ - public ObjectInstance createMBean(String className, - ObjectName name, ObjectName loaderName, Object[] params, - String[] signature, boolean useCLR) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - throw newUnsupportedException("createMBean"); - } - - - /** - *

    Attempts to determine whether the named MBean should be - * considered as an instance of a given class. The default implementation - * of this method calls {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} - * to get an MBean object. Then its behaviour is the same as the standard - * {@link MBeanServer#isInstanceOf MBeanServer.isInstanceOf} method.

    - * - * {@inheritDoc} - */ - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - - final DynamicMBean instance = nonNullMBeanFor(name); - - try { - final String mbeanClassName = instance.getMBeanInfo().getClassName(); - - if (mbeanClassName.equals(className)) - return true; - - final Object resource; - final ClassLoader cl; - if (instance instanceof DynamicWrapperMBean) { - DynamicWrapperMBean d = (DynamicWrapperMBean) instance; - resource = d.getWrappedObject(); - cl = d.getWrappedClassLoader(); - } else { - resource = instance; - cl = instance.getClass().getClassLoader(); - } - - final Class classNameClass = Class.forName(className, false, cl); - - if (classNameClass.isInstance(resource)) - return true; - - if (classNameClass == NotificationBroadcaster.class || - classNameClass == NotificationEmitter.class) { - try { - getNotificationEmitterFor(name); - return true; - } catch (Exception x) { - LOG.finest("MBean " + name + - " is not a notification emitter. Ignoring: "+x); - return false; - } - } - - final Class resourceClass = Class.forName(mbeanClassName, false, cl); - return classNameClass.isAssignableFrom(resourceClass); - } catch (Exception x) { - /* Could be SecurityException or ClassNotFoundException */ - LOG.logp(Level.FINEST, - MBeanServerSupport.class.getName(), - "isInstanceOf", "Exception calling isInstanceOf", x); - return false; - } - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method returns the string - * "DefaultDomain".

    - */ - public String getDefaultDomain() { - return "DefaultDomain"; - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method returns - * {@link #getNames()}.size().

    - */ - public Integer getMBeanCount() { - return getNames().size(); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method first calls {@link #getNames - * getNames()} to get a list of all MBean names, - * and from this set of names, derives the set of domains which contain - * MBeans.

    - */ - public String[] getDomains() { - final Set names = getNames(); - final Set res = new TreeSet(); - for (ObjectName n : names) { - if (n == null) continue; // not allowed but you never know. - res.add(n.getDomain()); - } - return res.toArray(new String[res.size()]); - } - - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link - * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle - * to the named MBean, - * and then call {@link DynamicMBean#getAttribute getAttribute} - * on that {@link DynamicMBean} handle.

    - * - * @throws RuntimeOperationsException {@inheritDoc} - */ - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - final DynamicMBean mbean = nonNullMBeanFor(name); - return mbean.getAttribute(attribute); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} - * to obtain a handle to the named MBean, - * and then call {@link DynamicMBean#setAttribute setAttribute} - * on that {@link DynamicMBean} handle.

    - * - * @throws RuntimeOperationsException {@inheritDoc} - */ - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - final DynamicMBean mbean = nonNullMBeanFor(name); - mbean.setAttribute(attribute); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a - * handle to the named MBean, - * and then call {@link DynamicMBean#getAttributes getAttributes} - * on that {@link DynamicMBean} handle.

    - * - * @throws RuntimeOperationsException {@inheritDoc} - */ - public AttributeList getAttributes(ObjectName name, - String[] attributes) throws InstanceNotFoundException, - ReflectionException { - final DynamicMBean mbean = nonNullMBeanFor(name); - return mbean.getAttributes(attributes); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a - * handle to the named MBean, - * and then call {@link DynamicMBean#setAttributes setAttributes} - * on that {@link DynamicMBean} handle.

    - * - * @throws RuntimeOperationsException {@inheritDoc} - */ - public AttributeList setAttributes(ObjectName name, AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - final DynamicMBean mbean = nonNullMBeanFor(name); - return mbean.setAttributes(attributes); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a - * handle to the named MBean, - * and then call {@link DynamicMBean#invoke invoke} - * on that {@link DynamicMBean} handle.

    - */ - public Object invoke(ObjectName name, String operationName, - Object[] params, String[] signature) - throws InstanceNotFoundException, MBeanException, - ReflectionException { - final DynamicMBean mbean = nonNullMBeanFor(name); - return mbean.invoke(operationName, params, signature); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a - * handle to the named MBean, - * and then call {@link DynamicMBean#getMBeanInfo getMBeanInfo} - * on that {@link DynamicMBean} handle.

    - */ - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - final DynamicMBean mbean = nonNullMBeanFor(name); - return mbean.getMBeanInfo(); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will call - * {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}.{@link DynamicMBean#getMBeanInfo getMBeanInfo()}.{@link MBeanInfo#getClassName getClassName()} to get the - * class name to combine with {@code name} to produce a new - * {@code ObjectInstance}.

    - */ - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - final DynamicMBean mbean = nonNullMBeanFor(name); - final String className = mbean.getMBeanInfo().getClassName(); - return new ObjectInstance(name, className); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first call {@link - * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle to the - * named MBean. If {@code getDynamicMBeanFor} returns an object, {@code - * isRegistered} will return true. If {@code getDynamicMBeanFor} returns - * null or throws {@link InstanceNotFoundException}, {@code isRegistered} - * will return false.

    - * - * @throws RuntimeOperationsException {@inheritDoc} - */ - public boolean isRegistered(ObjectName name) { - try { - final DynamicMBean mbean = getDynamicMBeanFor(name); - return mbean!=null; - } catch (InstanceNotFoundException x) { - if (LOG.isLoggable(Level.FINEST)) - LOG.finest("MBean "+name+" is not registered: "+x); - return false; - } - } - - - /** - * {@inheritDoc} - * - *

    The default implementation of this method will first - * call {@link #queryNames queryNames} - * to get a list of all matching MBeans, and then, for each returned name, - * call {@link #getObjectInstance getObjectInstance(name)}.

    - */ - public Set queryMBeans(ObjectName pattern, QueryExp query) { - final Set names = queryNames(pattern, query); - if (names.isEmpty()) return Collections.emptySet(); - final Set mbeans = new HashSet(); - for (ObjectName name : names) { - try { - mbeans.add(getObjectInstance(name)); - } catch (SecurityException x) { // DLS: OK - continue; - } catch (InstanceNotFoundException x) { // DLS: OK - continue; - } - } - return mbeans; - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method calls {@link #getMatchingNames - * getMatchingNames(pattern)} to obtain a list of MBeans matching - * the given name pattern. If the {@code query} parameter is null, - * this will be the result. Otherwise, it will evaluate the - * {@code query} parameter for each of the returned names, exactly - * as an {@code MBeanServer} would. This might result in - * {@link #getDynamicMBeanFor getDynamicMBeanFor} being called - * several times for each returned name.

    - */ - public Set queryNames(ObjectName pattern, QueryExp query) { - try { - final Set res = getMatchingNames(pattern); - return filterListOfObjectNames(res, query); - } catch (Exception x) { - LOG.fine("Unexpected exception raised in queryNames: "+x); - LOG.log(Level.FINEST, "Unexpected exception raised in queryNames", x); - } - // We reach here only when an exception was raised. - // - return Collections.emptySet(); - } - - private final static boolean apply(final QueryExp query, - final ObjectName on, - final MBeanServer srv) { - boolean res = false; - MBeanServer oldServer = QueryEval.getMBeanServer(); - query.setMBeanServer(srv); - try { - res = query.apply(on); - } catch (Exception e) { - LOG.finest("QueryExp.apply threw exception, returning false." + - " Cause: "+e); - res = false; - } finally { - /* - * query.setMBeanServer is probably - * QueryEval.setMBeanServer so put back the old - * value. Since that method uses a ThreadLocal - * variable, this code is only needed for the - * unusual case where the user creates a custom - * QueryExp that calls a nested query on another - * MBeanServer. - */ - query.setMBeanServer(oldServer); - } - return res; - } - - /** - * Filters a {@code Set} according to a pattern and a query. - * This might be quite inefficient for virtual name spaces. - */ - Set - filterListOfObjectNames(Set list, - QueryExp query) { - if (list.isEmpty() || query == null) - return list; - - // create a new result set - final Set result = new HashSet(); - - for (ObjectName on : list) { - // if on doesn't match query exclude it. - if (apply(query, on, this)) - result.add(on); - } - return result; - } - - - // Don't use {@inheritDoc}, because we don't want to say that the - // MBeanServer replaces a reference to the MBean by its ObjectName. - /** - *

    Adds a listener to a registered MBean. A notification emitted by - * the MBean will be forwarded to the listener.

    - * - *

    This implementation calls - * {@link #getNotificationEmitterFor getNotificationEmitterFor} - * and invokes {@code addNotificationListener} on the - * {@link NotificationEmitter} it returns. - * - * @see #getDynamicMBeanFor getDynamicMBeanFor - * @see #getNotificationEmitterFor getNotificationEmitterFor - */ - public void addNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) throws InstanceNotFoundException { - final NotificationEmitter emitter = - getNonNullNotificationEmitterFor(name); - emitter.addNotificationListener(listener, filter, handback); - } - - /** - * {@inheritDoc} - * - *

    This implementation calls - * {@link #getNotificationEmitterFor getNotificationEmitterFor} - * and invokes {@code removeNotificationListener} on the - * {@link NotificationEmitter} it returns. - * @see #getDynamicMBeanFor getDynamicMBeanFor - * @see #getNotificationEmitterFor getNotificationEmitterFor - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - final NotificationEmitter emitter = - getNonNullNotificationEmitterFor(name); - emitter.removeNotificationListener(listener); - } - - /** - * {@inheritDoc} - * - *

    This implementation calls - * {@link #getNotificationEmitterFor getNotificationEmitterFor} - * and invokes {@code removeNotificationListener} on the - * {@link NotificationEmitter} it returns. - * @see #getDynamicMBeanFor getDynamicMBeanFor - * @see #getNotificationEmitterFor getNotificationEmitterFor - */ - public void removeNotificationListener(ObjectName name, - NotificationListener listener, NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - NotificationEmitter emitter = - getNonNullNotificationEmitterFor(name); - emitter.removeNotificationListener(listener); - } - - - /** - *

    Adds a listener to a registered MBean.

    - * - *

    The default implementation of this method first calls - * {@link #getDynamicMBeanFor getDynamicMBeanFor(listenerName)}. - * If that successfully returns an object, call it {@code - * mbean}, then (a) if {@code mbean} is an instance of {@link - * NotificationListener} then this method calls {@link - * #addNotificationListener(ObjectName, NotificationListener, - * NotificationFilter, Object) addNotificationListener(name, mbean, filter, - * handback)}, otherwise (b) this method throws an exception as specified - * for this case.

    - * - *

    This default implementation is not appropriate for Virtual MBeans, - * although that only matters if the object returned by {@code - * getDynamicMBeanFor} can be an instance of - * {@code NotificationListener}.

    - * - * @throws RuntimeOperationsException {@inheritDoc} - */ - public void addNotificationListener(ObjectName name, ObjectName listenerName, - NotificationFilter filter, Object handback) - throws InstanceNotFoundException { - NotificationListener listener = getListenerMBean(listenerName); - addNotificationListener(name, listener, filter, handback); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public void removeNotificationListener(ObjectName name, - ObjectName listenerName) - throws InstanceNotFoundException, ListenerNotFoundException { - NotificationListener listener = getListenerMBean(listenerName); - removeNotificationListener(name, listener); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public void removeNotificationListener(ObjectName name, - ObjectName listenerName, NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - NotificationListener listener = getListenerMBean(listenerName); - removeNotificationListener(name, listener, filter, handback); - } - - private NotificationListener getListenerMBean(ObjectName listenerName) - throws InstanceNotFoundException { - Object mbean = getDynamicMBeanFor(listenerName); - if (mbean instanceof NotificationListener) - return (NotificationListener) mbean; - else { - throw newIllegalArgumentException( - "MBean is not a NotificationListener: " + listenerName); - } - } - - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link InstanceNotFoundException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @return the default implementation of this method never returns. - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - final UnsupportedOperationException failed = - new UnsupportedOperationException("getClassLoader"); - final InstanceNotFoundException x = - new InstanceNotFoundException(String.valueOf(loaderName)); - x.initCause(failed); - throw x; - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method calls - * {@link #getDynamicMBeanFor getDynamicMBeanFor(mbeanName)} and applies - * the logic just described to the result.

    - */ - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - final DynamicMBean mbean = nonNullMBeanFor(mbeanName); - if (mbean instanceof DynamicWrapperMBean) - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader(); - else - return mbean.getClass().getClassLoader(); - } - - /** - * {@inheritDoc} - * - *

    The default implementation of this method returns a - * {@link ClassLoaderRepository} containing exactly one loader, - * the {@linkplain Thread#getContextClassLoader() context class loader} - * for the current thread. - * Subclasses can override this method to return a different - * {@code ClassLoaderRepository}.

    - */ - public ClassLoaderRepository getClassLoaderRepository() { - // We return a new ClassLoaderRepository each time this - // method is called. This is by design, because the - // SingletonClassLoaderRepository is a very small object and - // getClassLoaderRepository() will not be called very often - // (the connector server calls it once) - in the context of - // MBeanServerSupport there's a very good chance that this method will - // *never* be called. - ClassLoader ccl = Thread.currentThread().getContextClassLoader(); - return Util.getSingleClassLoaderRepository(ccl); - } - - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { - throw newUnsupportedException("registerMBean"); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}. - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - throw newUnsupportedException("unregisterMBean"); - } - - /** - * Calls {@link #createMBean(String, ObjectName, - * ObjectName, Object[], String[], boolean) - * createMBean(className, name, null, params, signature, true)}; - */ - public final ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - try { - return createMBean(className, name, null, params, signature, true); - } catch (InstanceNotFoundException ex) { - // should not happen! - throw new MBeanException(ex, "Unexpected exception: " + ex); - } - } - - /** - * Calls {@link #createMBean(String, ObjectName, - * ObjectName, Object[], String[], boolean) - * createMBean(className,name, loaderName, params, signature, false)}; - */ - public final ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - return createMBean(className, name, loaderName, params, signature, false); - } - - /** - * Calls {@link #createMBean(String, ObjectName, - * ObjectName, Object[], String[], boolean) - * createMBean(className, name, null, null, null, true)}; - */ - public final ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - try { - return createMBean(className, name, null, null, null, true); - } catch (InstanceNotFoundException ex) { - // should not happen! - throw new MBeanException(ex, "Unexpected exception: " + ex); - } - } - - /** - * Calls {@link #createMBean(String, ObjectName, - * ObjectName, Object[], String[], boolean) - * createMBean(className, name, loaderName, null, null, false)}; - */ - public final ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - return createMBean(className, name, loaderName, null, null, false); - } - - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public Object instantiate(String className) - throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public Object instantiate(String className, Object[] params, - String[] signature) throws ReflectionException, MBeanException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - public Object instantiate(String className, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - throw new UnsupportedOperationException("Not applicable."); - } - - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - throw new UnsupportedOperationException("Not applicable."); - } - - /** - * {@inheritDoc} - * - *

    This operation is not supported in this base class implementation. - * The default implementation of this method always throws - * {@link RuntimeOperationsException} wrapping - * {@link UnsupportedOperationException}.

    - * - * @throws javax.management.RuntimeOperationsException wrapping - * {@link UnsupportedOperationException} - */ - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, byte[] data) - throws InstanceNotFoundException, OperationsException, - ReflectionException { - throw new UnsupportedOperationException("Not applicable."); - } - - - // Calls getDynamicMBeanFor, and throws an InstanceNotFoundException - // if the returned mbean is null. - // The DynamicMBean returned by this method is thus guaranteed to be - // non null. - // - private DynamicMBean nonNullMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (name == null) - throw newIllegalArgumentException("Null ObjectName"); - if (name.getDomain().equals("")) { - String defaultDomain = getDefaultDomain(); - try { - name = name.withDomain(getDefaultDomain()); - } catch (Exception e) { - throw newIllegalArgumentException( - "Illegal default domain: " + defaultDomain); - } - } - final DynamicMBean mbean = getDynamicMBeanFor(name); - if (mbean!=null) return mbean; - throw new InstanceNotFoundException(String.valueOf(name)); - } - - static RuntimeException newUnsupportedException(String operation) { - return new RuntimeOperationsException( - new UnsupportedOperationException( - operation+": Not supported in this namespace")); - } - - static RuntimeException newIllegalArgumentException(String msg) { - return new RuntimeOperationsException( - new IllegalArgumentException(msg)); - } - -} diff --git a/src/share/classes/javax/management/namespace/VirtualEventManager.java b/src/share/classes/javax/management/namespace/VirtualEventManager.java deleted file mode 100644 index 336f37565..000000000 --- a/src/share/classes/javax/management/namespace/VirtualEventManager.java +++ /dev/null @@ -1,378 +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 javax.management.namespace; - -import com.sun.jmx.remote.util.ClassLogger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventConsumer; - -/** - *

    This class maintains a list of subscribers for ObjectName patterns and - * allows a notification to be sent to all subscribers for a given ObjectName. - * It is typically used in conjunction with {@link MBeanServerSupport} - * to implement a namespace with Virtual MBeans that can emit notifications. - * The {@code VirtualEventManager} keeps track of the listeners that have been - * added to each Virtual MBean. When an event occurs that should trigger a - * notification from a Virtual MBean, the {@link #publish publish} method can - * be used to send it to the appropriate listeners.

    - * @since 1.7 - */ -public class VirtualEventManager implements EventConsumer { - /** - *

    Create a new {@code VirtualEventManager}.

    - */ - public VirtualEventManager() { - } - - public void subscribe( - ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) { - - if (logger.traceOn()) - logger.trace("subscribe", "" + name); - - if (name == null) - throw new IllegalArgumentException("Null MBean name"); - - if (listener == null) - throw new IllegalArgumentException("Null listener"); - - Map> map = - name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap; - - final ListenerInfo li = new ListenerInfo(listener, filter, handback); - List list; - - synchronized (map) { - list = map.get(name); - if (list == null) { - list = new ArrayList(); - map.put(name, list); - } - list.add(li); - } - } - - public void unsubscribe( - ObjectName name, NotificationListener listener) - throws ListenerNotFoundException { - - if (logger.traceOn()) - logger.trace("unsubscribe2", "" + name); - - if (name == null) - throw new IllegalArgumentException("Null MBean name"); - - if (listener == null) - throw new ListenerNotFoundException(); - - Map> map = - name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap; - - final ListenerInfo li = new ListenerInfo(listener, null, null); - List list; - synchronized (map) { - list = map.get(name); - if (list == null || !list.remove(li)) - throw new ListenerNotFoundException(); - - if (list.isEmpty()) - map.remove(name); - } - } - - /** - *

    Unsubscribes a listener which is listening to an MBean or a set of - * MBeans represented by an {@code ObjectName} pattern.

    - * - *

    The listener to be removed must have been added by the {@link - * #subscribe subscribe} method with the given {@code name}, {@code filter}, - * and {@code handback}. If the {@code - * name} is a pattern, then the {@code subscribe} must have used the same - * pattern. If the same listener has been subscribed more than once to the - * {@code name} with the same filter and handback, only one listener is - * removed.

    - * - * @param name The name of the MBean or an {@code ObjectName} pattern - * representing a set of MBeans to which the listener was subscribed. - * @param listener A listener that was previously subscribed to the - * MBean(s). - * - * @throws ListenerNotFoundException The given {@code listener} was not - * subscribed to the given {@code name}. - * - * @see #subscribe - */ - public void unsubscribe( - ObjectName name, NotificationListener listener, - NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - - if (logger.traceOn()) - logger.trace("unsubscribe4", "" + name); - - if (name == null) - throw new IllegalArgumentException("Null MBean name"); - - if (listener == null) - throw new ListenerNotFoundException(); - - Map> map = - name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap; - - List list; - synchronized (map) { - list = map.get(name); - boolean removed = false; - for (Iterator it = list.iterator(); it.hasNext(); ) { - ListenerInfo li = it.next(); - if (li.equals(listener, filter, handback)) { - it.remove(); - removed = true; - break; - } - } - if (!removed) - throw new ListenerNotFoundException(); - - if (list.isEmpty()) - map.remove(name); - } - } - - /** - *

    Sends a notification to the subscribers for a given MBean.

    - * - *

    For each listener subscribed with an {@code ObjectName} that either - * is equal to {@code emitterName} or is a pattern that matches {@code - * emitterName}, if the associated filter accepts the notification then it - * is forwarded to the listener.

    - * - * @param emitterName The name of the MBean emitting the notification. - * @param n The notification being sent by the MBean called - * {@code emitterName}. - * - * @throws IllegalArgumentException If the emitterName of the - * notification is null or is an {@code ObjectName} pattern. - */ - public void publish(ObjectName emitterName, Notification n) { - if (logger.traceOn()) - logger.trace("publish", "" + emitterName); - - if (n == null) - throw new IllegalArgumentException("Null notification"); - - if (emitterName == null) { - throw new IllegalArgumentException( - "Null emitter name"); - } else if (emitterName.isPattern()) { - throw new IllegalArgumentException( - "The emitter must not be an ObjectName pattern"); - } - - final List listeners = new ArrayList(); - - // If there are listeners for this exact name, add them. - synchronized (exactSubscriptionMap) { - List exactListeners = - exactSubscriptionMap.get(emitterName); - if (exactListeners != null) - listeners.addAll(exactListeners); - } - - // Loop over subscription patterns, and add all listeners for each - // one that matches the emitterName name. - synchronized (patternSubscriptionMap) { - for (ObjectName on : patternSubscriptionMap.keySet()) { - if (on.apply(emitterName)) - listeners.addAll(patternSubscriptionMap.get(on)); - } - } - - // Send the notification to all the listeners we found. - sendNotif(listeners, n); - } - - /** - *

    Returns a {@link NotificationEmitter} object which can be used to - * subscribe or unsubscribe for notifications with the named - * mbean. The returned object implements {@link - * NotificationEmitter#addNotificationListener - * addNotificationListener(listener, filter, handback)} as - * {@link #subscribe this.subscribe(name, listener, filter, handback)} - * and the two {@code removeNotificationListener} methods from {@link - * NotificationEmitter} as the corresponding {@code unsubscribe} methods - * from this class.

    - * - * @param name The name of the MBean whose notifications are being - * subscribed, or unsuscribed. - * - * @return A {@link NotificationEmitter} - * that can be used to subscribe or unsubscribe for - * notifications emitted by the named MBean, or {@code null} if - * the MBean does not emit notifications and should not - * be considered as a {@code NotificationBroadcaster}. This class - * never returns null but a subclass is allowed to. - * - * @throws InstanceNotFoundException if {@code name} does not exist. - * This implementation never throws {@code InstanceNotFoundException} but - * a subclass is allowed to override this method to do so. - */ - public NotificationEmitter - getNotificationEmitterFor(final ObjectName name) - throws InstanceNotFoundException { - final NotificationEmitter emitter = new NotificationEmitter() { - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws IllegalArgumentException { - subscribe(name, listener, filter, handback); - } - - public void removeNotificationListener( - NotificationListener listener) - throws ListenerNotFoundException { - unsubscribe(name, listener); - } - - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - throws ListenerNotFoundException { - unsubscribe(name, listener, filter, handback); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - // Never called. - return null; - } - }; - return emitter; - } - - // --------------------------------- - // private stuff - // --------------------------------- - - private static class ListenerInfo { - public final NotificationListener listener; - public final NotificationFilter filter; - public final Object handback; - - public ListenerInfo(NotificationListener listener, - NotificationFilter filter, - Object handback) { - - if (listener == null) { - throw new IllegalArgumentException("Null listener."); - } - - this.listener = listener; - this.filter = filter; - this.handback = handback; - } - - /* Two ListenerInfo instances are equal if they have the same - * NotificationListener. This means that we can use List.remove - * to implement the two-argument removeNotificationListener. - */ - @Override - public boolean equals(Object o) { - if (o == this) { - return true; - } - - if (!(o instanceof ListenerInfo)) { - return false; - } - - return listener.equals(((ListenerInfo)o).listener); - } - - /* Method that compares all four fields, appropriate for the - * four-argument removeNotificationListener. - */ - boolean equals( - NotificationListener listener, - NotificationFilter filter, - Object handback) { - return (this.listener == listener && same(this.filter, filter) - && same(this.handback, handback)); - } - - private static boolean same(Object x, Object y) { - if (x == y) - return true; - if (x == null) - return false; - return x.equals(y); - } - - @Override - public int hashCode() { - return listener.hashCode(); - } - } - - private static void sendNotif(List listeners, Notification n) { - for (ListenerInfo li : listeners) { - if (li.filter == null || - li.filter.isNotificationEnabled(n)) { - try { - li.listener.handleNotification(n, li.handback); - } catch (Exception e) { - logger.trace("sendNotif", "handleNotification", e); - } - } - } - } - - // --------------------------------- - // private variables - // --------------------------------- - - private final Map> exactSubscriptionMap = - new HashMap>(); - private final Map> patternSubscriptionMap = - new HashMap>(); - - // trace issue - private static final ClassLogger logger = - new ClassLogger("javax.management.event", "EventManager"); -} diff --git a/src/share/classes/javax/management/namespace/package-info.java b/src/share/classes/javax/management/namespace/package-info.java deleted file mode 100644 index 5c014286d..000000000 --- a/src/share/classes/javax/management/namespace/package-info.java +++ /dev/null @@ -1,629 +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. - */ - -/** - *

    The javax.management.namespace package makes it possible - * to federate MBeanServers into a hierarchical name space.

    - * - *

    What Is a Name Space?

    - *

    - * A name space is like an {@link javax.management.MBeanServer} within - * an {@code MBeanServer}. Just as a file system folder can contain - * another file system folder, an {@code MBeanServer} can contain another - * {@code MBeanServer}. Similarly, just as a remote folder on a remote - * disk can be mounted on a parent folder on a local disk, a remote name - * space in a remote {@code MBeanServer} can be mounted on a name - * space in a local parent {@code MBeanServer}. - *

    - *

    - * The javax.management.namespace API thus makes it possible to - * create a hierarchy of MBean servers federated in a hierarchical name - * space inside a single {@code MBeanServer}. - *

    - *

    How To Create a Name Space?

    - *

    - * To create a name space, you only need to register a - * {@link javax.management.namespace.JMXNamespace} MBean in - * an MBean server. We have seen that a namespace is like - * an {@code MBeanServer} within an {@code MBeanServer}, and - * therefore, it is possible to create a namespace that shows the - * content of another {@code MBeanServer}. The simplest case is - * when that {@code MBeanServer} is another {@code MBeanServer} - * created by the {@link javax.management.MBeanServerFactory} as - * shown in the extract below: - *

    - *
    - *  final MBeanServer server = ....;
    - *  final String namespace = "foo";
    - *  final ObjectName namespaceName = {@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName
    - *        JMXNamespaces.getNamespaceObjectName(namespace)};
    - *  server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
    - *                      namespaceName);
    - *  
    - *

    - * To navigate in namespaces and view their content, the easiest way is - * to use an instance of {@link javax.management.namespace.JMXNamespaceView}. For instance, given - * the {@code server} above, in which we created a namespace {@code "foo"}, - * it is possible to create a {@code JMXNamespaceView} that will make it - * possible to navigate easily in the namespaces and sub-namespaces of that - * server: - *

    - *
    - *  // create a namespace view for 'server'
    - *  final JMXNamespaceView view = new JMXNamespaceView(server);
    - *
    - *  // list all top level namespaces in 'server'
    - *  System.out.println("List of namespaces: " + Arrays.toString({@link javax.management.namespace.JMXNamespaceView#list() view.list()}));
    - *
    - *  // go down into namespace 'foo': provides a namespace view of 'foo' and its
    - *  // sub namespaces...
    - *  final JMXNamespaceView foo = {@link javax.management.namespace.JMXNamespaceView#down view.down("foo")};
    - *
    - *  // list all MBeans contained in namespace 'foo'
    - *  System.out.println({@link javax.management.namespace.JMXNamespaceView#where() foo.where()} + " contains: " +
    - *         {@link javax.management.namespace.JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
    - *  
    - *

    - * It is also possible to create more complex namespaces, such as namespaces - * that point to MBean servers located in remote JVMs. - *

    - *

    - * For instance, to mount the MBeanServer accessible - * at service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi - * in a name space {@code "foo"} inside the {@linkplain - * java.lang.management.ManagementFactory#getPlatformMBeanServer platform - * MBeanServer} you would write the following piece of code: - *

    - *
    - *      final JMXServiceURL sourceURL =
    - *         new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi");
    - *      final MBeanServer platform = ManagementFactory.getPlatformMBeanServer();
    - *      final Map<String,Object> options = Collections.emptyMap();
    - *      final JMXRemoteNamespace mbean = {@link
    - *            javax.management.namespace.JMXRemoteNamespace JMXRemoteNamespace}.
    - *         {@link javax.management.namespace.JMXRemoteNamespace#newJMXRemoteNamespace newJMXRemoteNamespace(sourceURL, options)};
    - *      final ObjectName name = {@link javax.management.namespace.JMXNamespaces JMXNamespaces}.{@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName(String) getNamespaceObjectName("foo")};
    - *      final ObjectInstance ref = platform.registerMBean(mbean,name);
    - *      platform.invoke(ref.getObjectName(),"connect",null,null);
    - *  
    - * - *

    What Does a Name Space Look Like?

    - * - *

    - * We have seen that {@link javax.management.namespace.JMXNamespaceView} class - * provides an easy way to navigate within namespaces. It is however also - * possible to interact with namespaces directly from the top level - * {@code MBeanServer} in which they have been created. - * From the outside, a name space only appears as a special MBean in - * the MBean server. There's nothing much you can do with this MBean - * directly. - *

    - *

    - * For instance, let's assume you have registered a {@link - * javax.management.namespace.JMXRemoteNamespaceMBean - * JMXRemoteNamespaceMBean} to manage the name space {@code "foo"}. - *
    If you query for - * platform.queryNames("*//:*",null), then you will see - * one MBean named {@code "foo//:type=JMXNamespace"}. - *
    This is the {@link javax.management.namespace.JMXNamespace} - * MBean which is in charge of handling the namespace {@code "foo"}. - *

    - *

    - * In fact, name space handler MBeans are instances of - * the class {@link javax.management.namespace.JMXNamespace} - or - * instances of a subclass of that class. - * They have a special {@link javax.management.ObjectName} defined by - * {@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName - * JMXNamespaces.getNamespaceObjectName}.
    - * {@link javax.management.namespace.JMXNamespace} instances are able - * to return an {@link - * javax.management.namespace.JMXNamespace#getSourceServer MBeanServer} - * which corresponds to the MBeanServer within (= the name space itself). - *

    - *

    - * So how does it work? How can you see the MBeans contained in the new - * name space? - *

    - *

    In order to address scalability issues, MBeans registered in - * namespaces (such as our namespace {@code "foo"} above) can not be - * seen with {@code mbeanServer.queryNames("*:*",null)}. To see the MBeans - * contained in a namespace, you can use one of these methods: - *

    - *
      - *
    1. - * You can use the {@link javax.management.namespace.JMXNamespaceView} - * class shown above, - *
    2. - *
    3. - * or you can directly look for MBeans - * whose names match - * {@code "foo//*:*"}, - *
    4. - *
    5. - * or you can narrow down to the namespace - * and obtain an MBeanServer - * proxy that corresponds to an MBeanServer view of that namespace. - * The JMXNamespaces class provides a static method that - * allows you to narrow down to a name space, by calling - * {@link javax.management.namespace.JMXNamespaces#narrowToNamespace(MBeanServer,String) - * JMXNamespaces.narrowToNamespace}. - *
    6. - *
    - * - *

    Using Name Space Prefixes

    - *

    - * As we have explained above, MBeans contained in name - * spaces are not returned by {@code server.queryNames(null,null)} - or - * server.queryNames({@link javax.management.ObjectName#WILDCARD ObjectName.WILDCARD},null). - *
    - * However, these MBeans can still be accessed from the top level - * {@code MBeanServer} interface, without using any API specific to the - * version 2.0 of the JMX API, simply by using object names with - * name space prefixes: - *
    To list MBeans contained in a namespace {@code "foo"} you can - * query for MBeans whose names match {@code "foo//*:*"}, as shown - * earlier in this document: - *

    - *         server.queryNames(new ObjectName("foo//*:*", null);
    - *         // or equivalently:
    - *         server.queryNames(JMXNamespaces.getWildcardFor("foo"), null);
    - *      
    - * This will return a list of MBean names whose domain name starts - * with {@code foo//}. - *

    - * Using these names, you can invoke any operation on the corresponding - * MBeans. For instance, to get the {@link javax.management.MBeanInfo - * MBeanInfo} of an MBean - * contained in name space {@code "foo"} (assuming - * the name of the MBean within its name space is domain:type=Thing, - * then simply call: - *

    - *         server.getMBeanInfo(new ObjectName("foo//domain:type=Thing"));
    - *      
    - * An easier way to access MBeans contained in a name space is to - * cd inside the name space, as shown in the following paragraph. - *

    - * Although ObjectName patterns where the characters - * * and ? appear in the namespace path are - * legal, they are not valid in the {@code name} parameter of the - * MBean Server {@link - * javax.management.MBeanServer#queryNames queryNames} and {@link - * javax.management.MBeanServer#queryMBeans queryMBeans} methods.
    - * When invoking queryNames or queryMBeans, - * only ObjectNames of the form:
    - * [namespace-without-pattern//]*[pattern-without-namespace]:key-properties-with-or-without-pattern - * are valid.
    - * In other words: in the case of {@link - * javax.management.MBeanServer#queryNames queryNames} and {@link - * javax.management.MBeanServer#queryMBeans queryMBeans}, if a - * namespace path is present, it must not contain any pattern. - *

    - * There is no such restriction for the {@code query} parameter of these - * methods. However, it must be noted that the {@code query} parameter - * will be evaluated in the context of the namespace where the MBeans - * selected by the pattern specified in {@code name} are located. - * This means that if {@code query} parameter is an ObjectName pattern that - * contains a namespace path, no MBean name will match and the result of - * the query will be empty.
    - * In other words:

    - *
    • {@code queryNames("foo//bar//?a?:*","b?z:type=Monitor,*")} will select - * all MBeans in namespace foo//bar whose names match both - * ?a?:* and b?z:type=Monitor,*, but
    • - *
    • {@code queryNames("foo//bar//?a?:*","foo//bar//b?z:type=Monitor,*")} - * will select nothing because no name matching ?a?:* will - * also match foo//bar//b?z:type=Monitor,*. - *
    • - *
    - * - *

    Narrowing Down Into a Name Spaces

    - *

    - * As we have seen, name spaces are like MBean servers within MBean servers. - * Therefore, it is possible to view a name space just as if it were - * an other MBean server. This is similar to opening a sub - * folder from a parent folder.
    - * This operation is illustrated in the code extract below: - *

    - *          final MBeanServer foo =
    - *                JMXNamespaces.narrowToNamespace(platform, "foo");
    - *          final MBeanInfo info =
    - *                foo.getMBeanInfo(new ObjectName("domain:type=Thing"));
    - *      
    - * The {@code MBeanServer} returned by {@link - * javax.management.namespace.JMXNamespaces#narrowToNamespace(MBeanServer,String) - * JMXNamespaces.narrowToNamespace} is an {@code MBeanServer} view that - * narrows down into a given namespace. The MBeans contained inside that - * namespace can now be accessed by their regular local name.
    - * The MBean server obtained by narrowing down - * to name space {@code "foo"} behaves just like a regular MBean server. - * However, it may sometimes throw an {@link - * java.lang.UnsupportedOperationException UnsupportedOperationException} - * wrapped in a {@link javax.management.RuntimeOperationsException - * RuntimeOperationsException} if you try to call an operation which is not - * supported by the underlying name space handler. - *
    For instance, {@link javax.management.MBeanServer#registerMBean - * registerMBean} is not supported for name spaces mounted from remote - * MBean servers. - *

    - *

    - * Note: If you have a deep hierarchy of namespaces, and if you - * are switching from one namespace to another in the course of your - * application, it might be more convenient to use a - * {@link javax.management.namespace.JMXNamespaceView} - * in order to navigate in your namespaces. - *

    - * - *

    Different Types of Name Spaces

    - *

    - * This API lets you create several types of name spaces: - *

      - *
    • - * You can use the {@link - * javax.management.namespace.JMXRemoteNamespace - * JMXRemoteNamespace} to create - * remote name spaces, mounted from - * a remote sub {@code MBeanServer} source, as shown - * earlier in this document. - *
    • - *
    • - * You can also use {@link - * javax.management.namespace.JMXNamespace - * JMXNamespace} to create - * local name spaces, - * by providing a direct reference to another {@code MBeanServer} - * instance living in the same JVM. - *
    • - *
    • - * Finally, you can create - * name spaces containing virtual MBeans, - * by subclassing the {@link - * javax.management.namespace.MBeanServerSupport - * MBeanServerSupport}, and passing an instance of - * your own subclass to a {@link - * javax.management.namespace.JMXNamespace JMXNamespace}. - *
    • - *
    • - * If none of these classes suit your needs, you can also provide - * your own subclass of {@link - * javax.management.namespace.JMXNamespace - * JMXNamespace}. This is however discouraged. - *
    • - *
    - *

    - * - *

    Name Spaces And Special Operations

    - *

    - * MBean Naming considerations aside, Name Spaces are transparent for - * most {@code MBeanServer} operations. There are however a few - * exceptions: - *

    - *
      - *
    • - *

      MBeanServer only operations - these are the operations which are - * supported by {@link javax.management.MBeanServer MBeanServer} but - * are not present in {@link - * javax.management.MBeanServerConnection - * MBeanServerConnection}. Since a name space can be a local view of - * a remote {@code MBeanServer}, accessible only through an - * {@code MBeanServerConnection}, these - * kinds of operations are not always supported.

      - *
        - *
      • - *

        registerMBean:

        - *

        The {@link javax.management.MBeanServer#registerMBean - * registerMBean} - * operation is not supported by most name spaces. A call - * to - *

        - *   MBeanServer server = ....;
        - *   ThingMBean mbean = new Thing(...);
        - *   ObjectName name = new ObjectName("foo//domain:type=Thing");
        - *   server.registerMBean(mbean, name);
        - *                          
        - * will usually fail, unless the name space - * {@code "foo"} is a local name - * space. In the case where you attempt to cross - * multiple name spaces, then all name spaces in the - * path must support the {@code registerMBean} operation - * in order for it to succeed.
        - * To create an MBean inside a name space, it is - * usually safer to use {@code createMBean} - - * although some special - * considerations can also apply. - *

        - *

        - *
      • - *
      • - *

        getClassLoader:

        - *

        Similarly to registerMBean, - * and for the same reasons, {@link - * javax.management.MBeanServer#getClassLoader - * getClassLoader} will usually fail, unless the - * class loader is an MBean registered in a - * local name space.
        - *

        - *
      • - *
      • - *

        getClassLoaderFor:

        - *

        The implementation of {@link - * javax.management.MBeanServer#getClassLoaderFor - * getClassLoaderFor} also depends on which - * type of name space - * handler is used across the namespace path. - *

        - *

        - * A local name space will usually - * be able to implement this method just as a real - * {@code MBeanServer} would. A - * remote name space will usually - * return the default class loader configured on the - * internal {@link javax.management.remote.JMXConnector - * JMXConnector} used to connect to the remote server. - * When a {@link - * javax.management.namespace.JMXRemoteNamespace - * JMXRemoteNamespace} is used to connect to a - * remote server that contains MBeans which export - * custom types, the {@link - * javax.management.namespace.JMXRemoteNamespace - * JMXRemoteNamespace} must thus be configured with - * an options map such that the underlying connector - * can obtain a default class loader able - * to handle those types. - *

        - *

        - * Other types of name spaces - * may implement this method - * as best as they can. - *

        - *
      • - *
      - *
    • - *
    • - *

      MBean creation

      - *

      MBean creation through {@link - * javax.management.MBeanServerConnection#createMBean - * createMBean} might not be supported by all - * name spaces: local name spaces and - * remote name spaces will usually - * support it, but virtual name - * spaces and custom name - * spaces might not. - *

      - *

      - * In that case, they will throw an {@link - * java.lang.UnsupportedOperationException - * UnsupportedOperationException} usually wrapped into an {@link - * javax.management.MBeanRegistrationException}. - *

      - *
    • - *
    • - *

      Notifications

      - *

      Some namespaces might not support JMX Notifications. In that - * case, a call to add or remove notification listener for an - * MBean contained in that name space will raise a - * {@link javax.management.RuntimeOperationsException - * RuntimeOperationsException} wrapping an {@link - * java.lang.UnsupportedOperationException - * UnsupportedOperationException} exception. - *

      - *
    • - *
    - * - *

    Crossing Several Name Spaces

    - *

    - * Just as folders can contain other folders, name spaces can contain - * other name spaces. For instance, if an {@code MBeanServer} S1 - * containing a name space {@code "bar"} is mounted in another - * {@code MBeanServer} S2 with name space {@code "foo"}, then - * an MBean M1 named {@code "domain:type=Thing"} in namespace - * {@code "bar"} will appear as {@code "foo//bar//domain:type=Thing"} in - * {@code MBeanServer} S2. - *

    - *

    - * When accessing the MBean M1 from server S2, the - * method call will traverse in a cascade {@code MBeanServer} S2, - * then the name space handler for name space {@code "foo"}, then - * {@code MBeanServer} S1, before coming to the name space - * handler for name space {@code "bar"}. Any operation invoked - * on the MBean from a "top-level" name space will therefore need to - * traverse all the name spaces along the name space path until - * it eventually reaches the named MBean. This means that an operation - * like registerMBean for instance, - * can only succeed if all the name spaces along the path support it. - *

    - *

    - * Narrowing to a nested name space works just the same as narrowing - * to a top level name space: - *

    - *          final MBeanServer S2 = .... ;
    - *          final MBeanServer bar =
    - *                JMXNamespaces.narrowToNamespace(S2, "foo//bar");
    - *          final MBeanInfo info =
    - *                foo.getMBeanInfo(new ObjectName("domain:type=Thing"));
    - *      
    - *

    - * - *

    Name Spaces And Operation Results

    - *

    - * Operation results, as well as attribute values returned by an MBean - * contained in a name space must be interpreted in the context of that - * name space.
    - * In other words, if an MBean in name space "foo" has an attribute of - * type {@code ObjectName}, then it must be assumed that the - * {@code ObjectName} returned by that MBean is relative to - * name space "foo".
    - * The same rule aplies for MBean names that can be returned by - * operations invoked on such an MBean. If one of the MBean operations - * return, say, a {@code Set} then those MBean names must - * also be assumed to be relative to name space "foo".
    - *

    - *

    - * In the usual case, a JMX client will first - * narrow to a name space before invoking - * any operation on the MBeans it contains. In that case the names - * returned by the MBean invoked can be directly fed back to the - * narrowed connection. - *
    - * If however, the JMX client directly invoked the MBean from a higher - * name space, without having narrowed to that name space first, then - * the names that might be returned by that MBean will not be directly - * usable - the JMX client will need to either - * narrow to the name space before using the - * returned names, or convert the names to the higher level name space - * context. - *
    - * The {@link javax.management.namespace.JMXNamespaces JMXNamespaces} - * class provides methods that can be used to perform that conversion. - *

    - * - *

    Name Spaces And Notifications

    - *

    - * As already explained, name spaces are very - * similar to {@code MBeanServer}s. It is thus possible to get - * {@link javax.management.MBeanServerNotification MBeanServerNotifications} - * when MBeans are added or removed within a name space, by registering - * with the {@link javax.management.MBeanServerDelegate - * MBeanServerDelegate} MBean of the corresponding name space.
    - * However, it must be noted that the notifications emitted by a - * name space must be interpreted in the context of that name space. - * For instance, if an MBean {@code "domain:type=Thing"} contained in - * namespace "foo//bar" emits a notification, the source of the - * notification will be {@code "domain:type=Thing"}, not - * {@code "foo//bar//domain:type=Thing"}.
    - * It is therefore recommended to keep track of the name space - * information when registering a listener with an MBean contained in - * a name space, especially if the same listener is used to receive - * notifications from different name spaces. An easy solution is to - * use the handback, as illustrated in the code below. - *

    - *            final MBeanServer server = ...;
    - *            final NotificationListener listener = new NotificationListener() {
    - *                public void handleNotification(Notification n, Object handback) {
    - *                    if (!(n instanceof MBeanServerNotification)) {
    - *                        System.err.println("Error: expected MBeanServerNotification");
    - *                        return;
    - *                    }
    - *                    final MBeanServerNotification mbsn =
    - *                            (MBeanServerNotification) n;
    - *
    - *                    // We will pass the namespace path in the handback.
    - *                    //
    - *                    // The received notification must be interpreted in
    - *                    // the context of its source - therefore
    - *                    // mbsn.getMBeanName() does not include the name space
    - *                    // path...
    - *                    //
    - *                    final String namespace = (String) handback;
    - *                    System.out.println("Received " + mbsn.getType() +
    - *                            " for MBean " + mbsn.getMBeanName() +
    - *                            " from name space " + namespace);
    - *                }
    - *            };
    - *            server.addNotificationListener(JMXNamespaces.insertPath("foo//bar",
    - *                    MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//bar");
    - *            server.addNotificationListener(JMXNamespaces.insertPath("foo//joe",
    - *                    MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//joe");
    - *          
    - *

    - *

    - * JMX Connectors may require some configuration in order to be able - * to forward notifications from MBeans located in name spaces. - * The RMI JMX Connector Server - * in the Java SE 7 platform is configured by default to internally - * use the new {@linkplain javax.management.event event service} on - * the server side. - * When the connector server is configured in this way, JMX clients - * which use the old JMX Notifications mechanism (such as clients - * running on prior versions of the JDK) will be able to - * to receive notifications from MBeans located in sub name spaces. - * This is because the connector server will transparently delegate - * their subscriptions to the underlying {@linkplain - * javax.management.event event service}. In summary: - *

      - *
    • - * On the server side: When exporting an {@code MBeanServer} - * through a JMX Connector, you will need to make sure that the - * connector server uses the new {@linkplain javax.management.event - * event service} in order to register for notifications. If the - * connector server doesn't use the event service, only clients - * which explicitly use the new {@linkplain javax.management.event - * event service} will be able to register for notifications - * with MBeans located in sub name spaces. - *
    • - *
    • - * On the client side: if the JMX Connector server (on the remote - * server side) was configured to internally use the new - * {@linkplain javax.management.event - * event service}, then clients can continue to use the old - * {@code MBeanServerConnection} add / remove notification - * listener methods transparently. Otherwise, only clients which - * explicitly use the new {@linkplain javax.management.event - * event service} will be able to receive notifications from - * MBeans contained in sub name spaces. - *
    • - *
    - *

    - *

    - * These configuration issues apply at each node in the name space path, - * whenever the name space points to a remote server. The - * {@link javax.management.namespace.JMXRemoteNamespace - * JMXRemoteNamespace} can be configured in such a way that it will - * explicitly use an {@link javax.management.event.EventClient EventClient} - * when forwarding subscription to the remote side. Note that this can be - * unnecessary (and a waste of resources) if the underlying JMXConnector - * returned by the JMXConnectorFactory (client side) already uses the - * {@linkplain javax.management.event event service} to register for - * notifications with the server side. - *

    - * - *

    Name Spaces And Access Control

    - *

    - * Access to MBeans exposed through JMX namespaces is controlled by - * {@linkplain javax.management.namespace.JMXNamespacePermission - * jmx namespace permissions}. These permissions are checked by the - * MBeanServer in which the {@link - * javax.management.namespace.JMXNamespace JMXNamespace} MBean is registered. - * This is described in - * details in the {@link - * javax.management.namespace.JMXNamespace JMXNamespace} class. - *

    - *

    - * To implement a "firewall-like" access control in a JMX agent you - * can also place an {@link - * javax.management.remote.MBeanServerForwarder} in the JMX Connector - * Server which exposes the top-level MBeanServer of your application. - * This {@code MBeanServerForwarder} will be able to perform - * authorization checks for all MBeans, including those located in - * sub name spaces. - *

    - *

    - * For a tighter access control we recommend using a {@link - * java.lang.SecurityManager security manager}. - *

    - * @since 1.7 - *

    - **/ - -package javax.management.namespace; - diff --git a/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java b/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java index 2262c2a5e..67341c41a 100644 --- a/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java +++ b/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java @@ -26,6 +26,8 @@ package javax.management.openmbean; import com.sun.jmx.mbeanserver.MXBeanLookup; +import com.sun.jmx.mbeanserver.MXBeanMapping; +import com.sun.jmx.mbeanserver.MXBeanMappingFactory; import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; @@ -115,12 +117,7 @@ public class CompositeDataInvocationHandler implements InvocationHandler { is null. */ public CompositeDataInvocationHandler(CompositeData compositeData) { - this(compositeData, MXBeanMappingFactory.DEFAULT); - } - - public CompositeDataInvocationHandler(CompositeData compositeData, - MXBeanMappingFactory mappingFactory) { - this(compositeData, mappingFactory, null); + this(compositeData, null); } /** @@ -139,13 +136,11 @@ public class CompositeDataInvocationHandler implements InvocationHandler { is null. */ CompositeDataInvocationHandler(CompositeData compositeData, - MXBeanMappingFactory mappingFactory, MXBeanLookup lookup) { if (compositeData == null) throw new IllegalArgumentException("compositeData"); this.compositeData = compositeData; this.lookup = lookup; - this.mappingFactory = mappingFactory; } /** @@ -204,7 +199,7 @@ public class CompositeDataInvocationHandler implements InvocationHandler { } } MXBeanMapping mapping = - mappingFactory.mappingForType(method.getGenericReturnType(), + MXBeanMappingFactory.DEFAULT.mappingForType(method.getGenericReturnType(), MXBeanMappingFactory.DEFAULT); return mapping.fromOpenValue(openValue); } @@ -250,5 +245,4 @@ public class CompositeDataInvocationHandler implements InvocationHandler { private final CompositeData compositeData; private final MXBeanLookup lookup; - private final MXBeanMappingFactory mappingFactory; } diff --git a/src/share/classes/javax/management/openmbean/CompositeDataSupport.java b/src/share/classes/javax/management/openmbean/CompositeDataSupport.java index 9a2f307fd..87a89860e 100644 --- a/src/share/classes/javax/management/openmbean/CompositeDataSupport.java +++ b/src/share/classes/javax/management/openmbean/CompositeDataSupport.java @@ -92,16 +92,16 @@ public class CompositeDataSupport * @param itemNames itemNames must list, in any order, all the * item names defined in compositeType; the order in which the * names are listed, is used to match values in itemValues[]; must - * not be null. + * not be null or empty. * * @param itemValues the values of the items, listed in the same order as * their respective names in itemNames; each item value can be * null, but if it is non-null it must be a valid value for the open type * defined in compositeType for the corresponding item; must be of - * the same size as itemNames; must not be null. + * the same size as itemNames; must not be null or empty. * * @throws IllegalArgumentException compositeType is null, or - * itemNames[] or itemValues[] is null, or one + * itemNames[] or itemValues[] is null or empty, or one * of the elements in itemNames[] is a null or empty string, or * itemNames[] and itemValues[] are not of the same size. * @@ -124,6 +124,8 @@ public class CompositeDataSupport if (itemNames == null || itemValues == null) throw new IllegalArgumentException("Null itemNames or itemValues"); + if (itemNames.length == 0 || itemValues.length == 0) + throw new IllegalArgumentException("Empty itemNames or itemValues"); if (itemNames.length != itemValues.length) { throw new IllegalArgumentException( "Different lengths: itemNames[" + itemNames.length + @@ -154,10 +156,10 @@ public class CompositeDataSupport * must not be null. * @param items the mappings of all the item names to their values; * items must contain all the item names defined in compositeType; - * must not be null. + * must not be null or empty. * * @throws IllegalArgumentException compositeType is null, or - * items is null, or one of the keys in items is a null + * items is null or empty, or one of the keys in items is a null * or empty string. * @throws OpenDataException items' size differs from the * number of items defined in compositeType, or one of the @@ -167,8 +169,6 @@ public class CompositeDataSupport * compositeType. * @throws ArrayStoreException one or more keys in items is not of * the class java.lang.String. - * - * @see #toMap */ public CompositeDataSupport(CompositeType compositeType, Map items) @@ -177,13 +177,13 @@ public class CompositeDataSupport } private static SortedMap makeMap(Map items) { - if (items == null) - throw new IllegalArgumentException("Null items map"); - if (items.containsKey(null) || items.containsKey("")) - throw new IllegalArgumentException("Null or empty item name"); + if (items == null || items.isEmpty()) + throw new IllegalArgumentException("Null or empty items map"); SortedMap map = new TreeMap(); for (Object key : items.keySet()) { + if (key == null || key.equals("")) + throw new IllegalArgumentException("Null or empty item name"); if (!(key instanceof String)) { throw new ArrayStoreException("Item name is not string: " + key); // This can happen because of erasure. The particular @@ -328,54 +328,6 @@ public class CompositeDataSupport return Collections.unmodifiableCollection(contents.values()); } - /** - *

    Returns a Map representing the contents of the given CompositeData. - * Each item in the CompositeData is represented by an entry in the map, - * where the name and value of the item are the key and value of the entry. - * The returned value is modifiable but modifications to it have no effect - * on the original CompositeData.

    - * - *

    For example, if you have a CompositeData {@code cd1} and you want - * to produce another CompositeData {@code cd2} which is the same except - * that the value of its {@code id} item has been changed to 253, you - * could write:

    - * - *
    -     * CompositeData cd1 = ...;
    -     * {@code Map} map = CompositeDataSupport.toMap(cd1);
    -     * assert(map.get("id") instanceof Integer);
    -     * map.put("id", 253);
    -     * CompositeData cd2 = {@link #CompositeDataSupport(CompositeType, Map)
    -     * new CompositeDataSupport}(cd1.getCompositeType(), map);
    -     * 
    - * - *

    Logically, this method would be a method in the {@link CompositeData} - * interface, but cannot be for compatibility reasons.

    - * - * @param cd the CompositeData to convert to a Map. - * - * @return a Map that is a copy of the contents of {@code cd}. - * - * @throws IllegalArgumentException if {@code cd} is null. - * - * @see #CompositeDataSupport(CompositeType, Map) - */ - public static Map toMap(CompositeData cd) { - if (cd == null) - throw new IllegalArgumentException("Null argument"); - - // If we really wanted, we could check whether cd is a - // CompositeDataSupport and return a copy of cd.contents if so, - // but I don't think that would be substantially faster. - Map map = new LinkedHashMap(); - CompositeType ct = cd.getCompositeType(); - for (String key : ct.keySet()) { - Object value = cd.get(key); - map.put(key, value); - } - return map; - } - /** * Compares the specified obj parameter with this * CompositeDataSupport instance for equality. diff --git a/src/share/classes/javax/management/openmbean/CompositeType.java b/src/share/classes/javax/management/openmbean/CompositeType.java index 28c3fd72b..4bee36584 100644 --- a/src/share/classes/javax/management/openmbean/CompositeType.java +++ b/src/share/classes/javax/management/openmbean/CompositeType.java @@ -89,7 +89,7 @@ public class CompositeType extends OpenType { *
      * @param itemNames The names of the items contained in the * composite data values described by this CompositeType instance; - * cannot be null; no element can be null or an empty string. + * cannot be null and should contain at least one element; no element can be a null or empty string. * Note that the order in which the item names are given is not important to differentiate a * CompositeType instance from another; * the item names are internally stored sorted in ascending alphanumeric order. @@ -125,7 +125,7 @@ public class CompositeType extends OpenType { // super(CompositeData.class.getName(), typeName, description, false); - // Check the 3 arrays are not null and that there is no null element or empty string in them + // Check the 3 arrays are not null or empty (ie length==0) and that there is no null element or empty string in them // checkForNullElement(itemNames, "itemNames"); checkForNullElement(itemDescriptions, "itemDescriptions"); @@ -159,8 +159,8 @@ public class CompositeType extends OpenType { } private static void checkForNullElement(Object[] arg, String argName) { - if (arg == null) { - throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null."); + if ( (arg == null) || (arg.length == 0) ) { + throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null or empty."); } for (int i=0; iThe {@link MXBeanMapping} class to be used to map the - * annotated type. This class must have a public constructor with - * a single argument of type {@link java.lang.reflect.Type}. The - * constructor will be called with the annotated type as an - * argument. See the {@code MXBeanMapping} documentation - * for an example.

    - * - *

    If the {@code MXBeanMapping} cannot in fact handle that - * type, the constructor should throw an {@link - * OpenDataException}. If the constructor throws this or any other - * exception then an MXBean in which the annotated type appears is - * invalid, and registering it in the MBean Server will produce a - * {@link NotCompliantMBeanException}. - */ - public Class value(); -} diff --git a/src/share/classes/javax/management/openmbean/MXBeanMappingFactoryClass.java b/src/share/classes/javax/management/openmbean/MXBeanMappingFactoryClass.java deleted file mode 100644 index e707ef81e..000000000 --- a/src/share/classes/javax/management/openmbean/MXBeanMappingFactoryClass.java +++ /dev/null @@ -1,72 +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 javax.management.openmbean; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - *

    Specifies the MXBean mapping factory to be used for Java types - * in an MXBean interface, or in all MXBean interfaces in a package.

    - * - *

    Applying a mapping factory to all Java types in an MXBean interface - * looks like this:

    - * - *
    - * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
    - * public interface SomethingMXBean {
    - *     public MyLinkedList getSomething();
    - * }
    - * 
    - * - *

    Applying a mapping factory to all Java types in all MXBean interfaces - * in a package, say {@code com.example.mxbeans}, looks like this. In the - * package source directory, create a file called {@code package-info.java} - * with these contents:

    - * - *
    - * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
    - * package com.example.mxbeans;
    - * 
    - * - * @see MXBeanMappingFactory - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.TYPE, ElementType.PACKAGE}) -@Documented @Inherited -public @interface MXBeanMappingFactoryClass { - /** - *

    The {@link MXBeanMappingFactory} class to be used to map - * types in the annotated interface or package. This class must - * have a public constructor with no arguments. See the {@code - * MXBeanMappingFactory} documentation for an example.

    - */ - public Class value(); -} diff --git a/src/share/classes/javax/management/openmbean/OpenType.java b/src/share/classes/javax/management/openmbean/OpenType.java index b6d40d008..f88b1a2d2 100644 --- a/src/share/classes/javax/management/openmbean/OpenType.java +++ b/src/share/classes/javax/management/openmbean/OpenType.java @@ -219,7 +219,7 @@ public abstract class OpenType implements Serializable { }); } - static String validClassName(String className) throws OpenDataException { + private static String validClassName(String className) throws OpenDataException { className = valid("className", className); // Check if className describes an array class, and determines its elements' class name. diff --git a/src/share/classes/javax/management/package.html b/src/share/classes/javax/management/package.html index 372c30efd..9c8ce40a1 100644 --- a/src/share/classes/javax/management/package.html +++ b/src/share/classes/javax/management/package.html @@ -128,42 +128,6 @@ have any questions. class.

    -

    Defining Standard MBeans with annotations

    - -

    As an alternative to creating an interface such as - ConfigurationMBean and a class that implements it, - you can write just the class, and use annotations to pick out the - public methods that will make up the management interface. For - example, the following class has the same management interface - as a Configuration class that implements the - ConfigurationMBean interface above.

    - -
    -    {@link javax.management.MBean @MBean}
    -    public class Configuration {
    -        {@link javax.management.ManagedAttribute @ManagedAttribute}
    -        public int getCacheSize() {...}
    -        @ManagedAttribute
    -        public void setCacheSize(int size) {...}
    -
    -        @ManagedAttribute
    -        public long getLastChangedTime() {...}
    -
    -        {@link javax.management.ManagedOperation @ManagedOperation}
    -        public void save() {...}
    -        ...
    -    }
    -        
    - -

    This approach simplifies development, but it does have two - potential drawbacks. First, if you run the Javadoc tool on - this class, the documentation of the management interface may - be mixed in with the documentation of non-management methods - in the class. Second, you cannot make a proxy - as described below if you do not have an - interface like ConfigurationMBean.

    - -

    MXBeans

    An MXBean is a variant of Standard MBean where complex @@ -173,11 +137,6 @@ have any questions. classes in your MBean interface. They are described in detail in the specification for {@link javax.management.MXBean MXBean}.

    -

    You can define MXBeans using annotations as described - in the previous section, but - using the @MXBean annotation instead of - @MBean.

    -

    Dynamic MBeans

    @@ -305,7 +264,7 @@ have any questions. perform the query.

    -

    MBean lifecycle and resource injection

    +

    MBean lifecycle

    An MBean can implement the {@link javax.management.MBeanRegistration MBeanRegistration} interface in order to be told when it is registered @@ -315,11 +274,6 @@ have any questions. object and to get its ObjectName within the MBean Server.

    -

    If the only reason to implement MBeanRegistration is to - discover the MBeanServer and ObjectName, resource injection may be - more convenient.

    -

    Notifications

    @@ -329,26 +283,16 @@ have any questions. type string that can distinguish it from other notifications of the same class.

    -

    If an MBean is to emit notifications, it must do one of two things.

    - -
      -
    • It can implement the interface {@link - javax.management.NotificationEmitter NotificationEmitter} (or - its parent {@link javax.management.NotificationBroadcaster - NotificationBroadcaster}), usually by subclassing - {@link javax.management.NotificationBroadcasterSupport - NotificationBroadcasterSupport} or delegating to an instance of - that class.
    • -
    • It can use resource - injection to obtain a {@link javax.management.SendNotification - SendNotification} object that it can use to send - notifications.
    • -
    - -

    The two classes below illustrate these two techniques:

    +

    An MBean that will emit notifications must implement the + {@link javax.management.NotificationBroadcaster + NotificationBroadcaster} or {@link + javax.management.NotificationEmitter NotificationEmitter} + interface. Usually, it does this by subclassing + {@link javax.management.NotificationBroadcasterSupport + NotificationBroadcasterSupport} or delegating to an instance of + that class. Here is an example:

    -    // Implementing NotificationEmitter (via NotificationBroadcasterSupport)
         public class Configuration extends NotificationBroadcasterSupport
                 implements ConfigurationMBean {
             ...
    @@ -358,17 +302,6 @@ have any questions.
                 sendNotification}(n);
             }
         }
    -
    -    // Getting a SendNotification through resource injection
    -    public class Configuration implements ConfigurationMBean {
    -        @Resource
    -        private volatile SendNotification sender;
    -        ...
    -        private void updated() {
    -            Notification n = new Notification(...);
    -            sender.sendNotification(n);
    -        }
    -    }
             
    @@ -410,88 +343,51 @@ have any questions.

    Interoperability between versions of the JMX specification

    -

    When a client connects to a server using the JMX Remote - API, it is possible that they do not have the same version - of the JMX specification. The version of the JMX - specification described here is version 2.0. Previous - versions were 1.0, 1.1, 1.2, and 1.4. (There was no 1.3.) - The standard JMX Remote API is defined to work with version - 1.2 onwards, so in standards-based deployment the only - interoperability questions that arise concern version 1.2 - onwards.

    - -

    Every version of the JMX specification continues to - implement the features of previous versions. So when the - client is running an earlier version than the server, there - should not be any interoperability concerns. The only - exception is the unlikely one where a pre-2.0 client used - the string {@code //} in the domain part of an {@link - javax.management.ObjectName ObjectName}.

    - -

    When the client is running a later version than the server, - certain newer features may not be available, as detailed in - the next sections. The method {@link - javax.management.JMX#getSpecificationVersion - JMX.getSpecificationVersion} can be used to determine the - server version to check if required features are - available.

    - -

    If the remote MBean Server is 1.4

    - -
      - -
    • You cannot use {@link - javax.management.QueryNotificationFilter - QueryNotificationFilter} in {@link - javax.management.MBeanServerConnection#addNotificationListener - addNotificationListener} since this class did not exist - in 1.4.

      - -
    • In an attribute in a query, you cannot access values - inside complex types using dot syntax, for example - {@link javax.management.Query#attr Query.attr}{@code - ("HeapMemoryUsage.used")}.

      - -
    • The packages {@link javax.management.event} and - {@link javax.management.namespace} did not exist in 1.4, - so you cannot remotely create instances of the MBeans - they define.

      - -
    • Even if the remote MBean Server is 2.0, you cannot in - general suppose that {@link - javax.management.event.EventClient EventClient} or - {@link javax.management.ClientContext ClientContext} - will work there without first checking. If the remote - MBean Server is 1.4 then those checks will return false. - An attempt to use these features without checking will - fail in the same way as for a remote 2.0 that is not - configured to support them.

      -
    - -

    If the remote MBean Server is 1.2

    - -

    In addition to the above,

    +

    When a client connects to a server using the JMX Remote + API, it is possible that they do not have the same version + of the JMX specification. The version of the JMX + specification described here is version 1.4. Previous + versions were 1.0, 1.1, and 1.2. (There was no 1.3.) + The standard JMX Remote API is defined to work with version + 1.2 onwards, so in standards-based deployment the only + interoperability questions that arise concern version 1.2 + onwards.

    + +

    Every version of the JMX specification continues to + implement the features of previous versions. So when the + client is running an earlier version than the server, there + should not be any interoperability concerns.

    + +

    When the client is running a later version than the server, + certain newer features may not be available, as detailed in + the next sections. The client can determine the server's + version by examining the {@link + javax.management.MBeanServerDelegateMBean#getSpecificationVersion + SpecificationVersion} attribute of the {@code + MBeanServerDelegate}.

    + +

    If the remote MBean Server is 1.2

      -
    • You cannot use wildcards in a key property of an - {@link javax.management.ObjectName ObjectName}, for - example {@code domain:type=Foo,name=*}. Wildcards that - match whole properties are still allowed, for example - {@code *:*} or {@code *:type=Foo,*}.

      +
    • You cannot use wildcards in a key property of an + {@link javax.management.ObjectName ObjectName}, for + example {@code domain:type=Foo,name=*}. Wildcards that + match whole properties are still allowed, for example + {@code *:*} or {@code *:type=Foo,*}.

      -
    • You cannot use {@link - javax.management.Query#isInstanceOf Query.isInstanceOf} - in a query.

      +
    • You cannot use {@link + javax.management.Query#isInstanceOf Query.isInstanceOf} + in a query.

      -
    • You cannot use dot syntax such as {@code - HeapMemoryUsage.used} in the {@linkplain - javax.management.monitor.Monitor#setObservedAttribute - observed attribute} of a monitor, as described in the - documentation for the {@link javax.management.monitor} - package.

      +
    • You cannot use dot syntax such as {@code + HeapMemoryUsage.used} in the {@linkplain + javax.management.monitor.Monitor#setObservedAttribute + observed attribute} of a monitor, as described in the + documentation for the {@link javax.management.monitor} + package.

      -
    +

    @see diff --git a/src/share/classes/javax/management/remote/IdentityMBeanServerForwarder.java b/src/share/classes/javax/management/remote/IdentityMBeanServerForwarder.java deleted file mode 100644 index 0b1e996d7..000000000 --- a/src/share/classes/javax/management/remote/IdentityMBeanServerForwarder.java +++ /dev/null @@ -1,303 +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 javax.management.remote; - -import java.io.ObjectInputStream; -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.OperationsException; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.loading.ClassLoaderRepository; - -/** - * An {@link MBeanServerForwarder} that forwards all {@link MBeanServer} - * operations unchanged to the next {@code MBeanServer} in the chain. - * This class is typically subclassed to override some but not all methods. - */ -public class IdentityMBeanServerForwarder implements MBeanServerForwarder { - - private MBeanServer next; - - /** - *

    Construct a forwarder that has no next {@code MBeanServer}. - * The resulting object will be unusable until {@link #setMBeanServer - * setMBeanServer} is called to establish the next item in the chain.

    - */ - public IdentityMBeanServerForwarder() { - } - - /** - *

    Construct a forwarder that forwards to the given {@code MBeanServer}. - * It is not an error for {@code next} to be null, but the resulting object - * will be unusable until {@link #setMBeanServer setMBeanServer} is called - * to establish the next item in the chain.

    - */ - public IdentityMBeanServerForwarder(MBeanServer next) { - this.next = next; - } - - public synchronized MBeanServer getMBeanServer() { - return next; - } - - public synchronized void setMBeanServer(MBeanServer mbs) { - next = mbs; - } - - private synchronized MBeanServer next() { - return next; - } - - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, MBeanRegistrationException { - next().unregisterMBean(name); - } - - public AttributeList setAttributes(ObjectName name, - AttributeList attributes) - throws InstanceNotFoundException, ReflectionException { - return next().setAttributes(name, attributes); - } - - public void setAttribute(ObjectName name, Attribute attribute) - throws InstanceNotFoundException, AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - next().setAttribute(name, attribute); - } - - public void removeNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - next().removeNotificationListener(name, listener, filter, handback); - } - - public void removeNotificationListener(ObjectName name, - NotificationListener listener) - throws InstanceNotFoundException, ListenerNotFoundException { - next().removeNotificationListener(name, listener); - } - - public void removeNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException, ListenerNotFoundException { - next().removeNotificationListener(name, listener, filter, handback); - } - - public void removeNotificationListener(ObjectName name, ObjectName listener) - throws InstanceNotFoundException, ListenerNotFoundException { - next().removeNotificationListener(name, listener); - } - - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, MBeanRegistrationException, - NotCompliantMBeanException { - return next().registerMBean(object, name); - } - - public Set queryNames(ObjectName name, QueryExp query) { - return next().queryNames(name, query); - } - - public Set queryMBeans(ObjectName name, QueryExp query) { - return next().queryMBeans(name, query); - } - - public boolean isRegistered(ObjectName name) { - return next().isRegistered(name); - } - - public boolean isInstanceOf(ObjectName name, String className) - throws InstanceNotFoundException { - return next().isInstanceOf(name, className); - } - - public Object invoke(ObjectName name, String operationName, Object[] params, - String[] signature) - throws InstanceNotFoundException, MBeanException, - ReflectionException { - return next().invoke(name, operationName, params, signature); - } - - public Object instantiate(String className, ObjectName loaderName, - Object[] params, String[] signature) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - return next().instantiate(className, loaderName, params, signature); - } - - public Object instantiate(String className, Object[] params, - String[] signature) - throws ReflectionException, MBeanException { - return next().instantiate(className, params, signature); - } - - public Object instantiate(String className, ObjectName loaderName) - throws ReflectionException, MBeanException, - InstanceNotFoundException { - return next().instantiate(className, loaderName); - } - - public Object instantiate(String className) - throws ReflectionException, MBeanException { - return next().instantiate(className); - } - - public ObjectInstance getObjectInstance(ObjectName name) - throws InstanceNotFoundException { - return next().getObjectInstance(name); - } - - public MBeanInfo getMBeanInfo(ObjectName name) - throws InstanceNotFoundException, IntrospectionException, - ReflectionException { - return next().getMBeanInfo(name); - } - - public Integer getMBeanCount() { - return next().getMBeanCount(); - } - - public String[] getDomains() { - return next().getDomains(); - } - - public String getDefaultDomain() { - return next().getDefaultDomain(); - } - - public ClassLoaderRepository getClassLoaderRepository() { - return next().getClassLoaderRepository(); - } - - public ClassLoader getClassLoaderFor(ObjectName mbeanName) - throws InstanceNotFoundException { - return next().getClassLoaderFor(mbeanName); - } - - public ClassLoader getClassLoader(ObjectName loaderName) - throws InstanceNotFoundException { - return next().getClassLoader(loaderName); - } - - public AttributeList getAttributes(ObjectName name, String[] attributes) - throws InstanceNotFoundException, ReflectionException { - return next().getAttributes(name, attributes); - } - - public Object getAttribute(ObjectName name, String attribute) - throws MBeanException, AttributeNotFoundException, - InstanceNotFoundException, ReflectionException { - return next().getAttribute(name, attribute); - } - - @Deprecated - public ObjectInputStream deserialize(String className, - ObjectName loaderName, - byte[] data) - throws InstanceNotFoundException, OperationsException, - ReflectionException { - return next().deserialize(className, loaderName, data); - } - - @Deprecated - public ObjectInputStream deserialize(String className, byte[] data) - throws OperationsException, ReflectionException { - return next().deserialize(className, data); - } - - @Deprecated - public ObjectInputStream deserialize(ObjectName name, byte[] data) - throws InstanceNotFoundException, OperationsException { - return next().deserialize(name, data); - } - - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName, Object[] params, - String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - return next().createMBean(className, name, loaderName, params, signature); - } - - public ObjectInstance createMBean(String className, ObjectName name, - Object[] params, String[] signature) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - return next().createMBean(className, name, params, signature); - } - - public ObjectInstance createMBean(String className, ObjectName name, - ObjectName loaderName) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - return next().createMBean(className, name, loaderName); - } - - public ObjectInstance createMBean(String className, ObjectName name) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException { - return next().createMBean(className, name); - } - - public void addNotificationListener(ObjectName name, ObjectName listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - next().addNotificationListener(name, listener, filter, handback); - } - - public void addNotificationListener(ObjectName name, - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws InstanceNotFoundException { - next().addNotificationListener(name, listener, filter, handback); - } -} diff --git a/src/share/classes/javax/management/remote/JMXConnector.java b/src/share/classes/javax/management/remote/JMXConnector.java index 1909a5afd..9ac3aa043 100644 --- a/src/share/classes/javax/management/remote/JMXConnector.java +++ b/src/share/classes/javax/management/remote/JMXConnector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-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 @@ -57,26 +57,6 @@ public interface JMXConnector extends Closeable { public static final String CREDENTIALS = "jmx.remote.credentials"; - /** - *

    Name of the attribute that specifies whether to use the - * {@linkplain javax.management.event Event Service} to handle - * notifications for this connector. The value associated with - * this attribute, if any, is a String, which must be equal, - * ignoring case, to {@code "true"} or {@code "false"}.

    - * - *

    Not all connectors will understand this attribute, but the - * standard {@linkplain javax.management.remote.rmi.RMIConnector - * RMI Connector} does.

    - * - *

    If this attribute is not present, then the system property of the - * same name ({@value}) is consulted. If that is not set - * either, then the Event Service is not used.

    - * - * @since 1.7 - */ - public static final String USE_EVENT_SERVICE = - "jmx.remote.use.event.service"; - /** *

    Establishes the connection to the connector server. This * method is equivalent to {@link #connect(Map) diff --git a/src/share/classes/javax/management/remote/JMXConnectorServer.java b/src/share/classes/javax/management/remote/JMXConnectorServer.java index 056114cfc..1f7cc81b5 100644 --- a/src/share/classes/javax/management/remote/JMXConnectorServer.java +++ b/src/share/classes/javax/management/remote/JMXConnectorServer.java @@ -26,22 +26,17 @@ package javax.management.remote; -import com.sun.jmx.remote.util.EnvHelp; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.NoSuchElementException; -import javax.management.ClientContext; -import javax.management.MBeanInfo; // for javadoc import javax.management.MBeanNotificationInfo; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.ObjectName; -import javax.management.event.EventClientDelegate; /** *

    Superclass of every connector server. A connector server is @@ -80,98 +75,6 @@ public abstract class JMXConnectorServer public static final String AUTHENTICATOR = "jmx.remote.authenticator"; - /** - *

    Name of the attribute that specifies whether this connector - * server can delegate notification handling to the - * {@linkplain javax.management.event Event Service}. - * The value associated with - * this attribute, if any, is a String, which must be equal, - * ignoring case, to {@code "true"} or {@code "false"}.

    - * - *

    Not all connector servers will understand this attribute, but the - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer - * RMI Connector Server} does.

    - * - *

    If this attribute is not present, then the system property of the - * same name ({@value}) is consulted. If that is not set - * either, then the Event Service is used if the connector server - * supports it.

    - * - * @since 1.7 - */ - public static final String DELEGATE_TO_EVENT_SERVICE = - "jmx.remote.delegate.event.service"; - - /** - *

    Name of the attribute that specifies whether this connector - * server allows clients to communicate a context with each request. - * The value associated with this attribute, if any, must be a string - * that is equal to {@code "true"} or {@code "false"}, ignoring case. - * If it is {@code "true"}, then the connector server will simulate - * a namespace {@code jmx.context//}, as described in - * {@link ClientContext#newContextForwarder}. This namespace is needed - * for {@link ClientContext#withContext ClientContext.withContext} to - * function correctly.

    - * - *

    Not all connector servers will understand this attribute, but the - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer - * RMI Connector Server} does. For a connector server that understands - * this attribute, the default value is {@code "true"}.

    - * - * @since 1.7 - */ - public static final String CONTEXT_FORWARDER = - "jmx.remote.context.forwarder"; - - /** - *

    Name of the attribute that specifies whether this connector server - * localizes the descriptions in the {@link MBeanInfo} object returned by - * {@link MBeanServer#getMBeanInfo MBeanServer.getMBeanInfo}, based on the - * locale communicated by the client.

    - * - *

    The value associated with this attribute, if any, must be a string - * that is equal to {@code "true"} or {@code "false"}, ignoring case. - * If it is {@code "true"}, then the connector server will localize - * {@code MBeanInfo} descriptions as specified in {@link - * ClientContext#newLocalizeMBeanInfoForwarder}.

    - * - *

    Not all connector servers will understand this attribute, but the - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer - * RMI Connector Server} does. For a connector server that understands - * this attribute, the default value is {@code "false"}.

    - * - *

    Because localization requires the client to be able to communicate - * its locale, it does not make sense to specify this attribute as - * {@code "true"} if {@link #CONTEXT_FORWARDER} is not also {@code "true"}. - * For a connector server that understands these attributes, specifying - * this inconsistent combination will result in an {@link - * IllegalArgumentException}.

    - * - * @since 1.7 - */ - public static final String LOCALIZE_MBEAN_INFO_FORWARDER = - "jmx.remote.localize.mbean.info"; - - /** - *

    Name of the attribute that specifies whether this connector - * server simulates the existence of the {@link EventClientDelegate} - * MBean. The value associated with this attribute, if any, must - * be a string that is equal to {@code "true"} or {@code "false"}, - * ignoring case. If it is {@code "true"}, then the connector server - * will simulate an EventClientDelegate MBean, as described in {@link - * EventClientDelegate#newForwarder}. This MBean is needed for {@link - * javax.management.event.EventClient EventClient} to function correctly.

    - * - *

    Not all connector servers will understand this attribute, but the - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer - * RMI Connector Server} does. For a connector server that understands - * this attribute, the default value is {@code "true"}.

    - * - * @since 1.7 - */ - public static final String EVENT_CLIENT_DELEGATE_FORWARDER = - "jmx.remote.event.client.delegate.forwarder"; - /** *

    Constructs a connector server that will be registered as an * MBean in the MBean server it is attached to. This constructor @@ -194,322 +97,27 @@ public abstract class JMXConnectorServer * to an MBean server by being registered in it. */ public JMXConnectorServer(MBeanServer mbeanServer) { - insertUserMBeanServer(mbeanServer); + this.mbeanServer = mbeanServer; } /** *

    Returns the MBean server that this connector server is - * attached to, or the first in a chain of user-added - * {@link MBeanServerForwarder}s, if any.

    + * attached to.

    * * @return the MBean server that this connector server is attached * to, or null if it is not yet attached to an MBean server. - * - * @see #setMBeanServerForwarder - * @see #getSystemMBeanServerForwarder */ public synchronized MBeanServer getMBeanServer() { - return userMBeanServer; + return mbeanServer; } - public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf) { - if (mbsf == null) - throw new IllegalArgumentException("Invalid null argument: mbsf"); - - if (userMBeanServer != null) - mbsf.setMBeanServer(userMBeanServer); - insertUserMBeanServer(mbsf); - } - - /** - *

    Remove a forwarder from the chain of forwarders. The forwarder can - * be in the system chain or the user chain. On successful return from - * this method, the first occurrence in the chain of an object that is - * {@linkplain Object#equals equal} to {@code mbsf} will have been - * removed.

    - * - * @param mbsf the forwarder to remove - * - * @throws NoSuchElementException if there is no occurrence of {@code mbsf} - * in the chain. - * @throws IllegalArgumentException if {@code mbsf} is null or is the - * {@linkplain #getSystemMBeanServerForwarder() system forwarder}. - * - * @since 1.7 - */ - public synchronized void removeMBeanServerForwarder(MBeanServerForwarder mbsf) { + public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf) + { if (mbsf == null) throw new IllegalArgumentException("Invalid null argument: mbsf"); - if (systemMBeanServerForwarder.equals(mbsf)) - throw new IllegalArgumentException("Cannot remove system forwarder"); - - MBeanServerForwarder prev = systemMBeanServerForwarder; - MBeanServer curr; - while (true) { - curr = prev.getMBeanServer(); - if (mbsf.equals(curr)) - break; - if (curr instanceof MBeanServerForwarder) - prev = (MBeanServerForwarder) curr; - else - throw new NoSuchElementException("MBeanServerForwarder not in chain"); - } - MBeanServer next = mbsf.getMBeanServer(); - prev.setMBeanServer(next); - if (userMBeanServer == mbsf) - userMBeanServer = next; - } - - /* - * Set userMBeanServer to mbs and arrange for the end of the chain of - * system MBeanServerForwarders to point to it. See the comment before - * the systemMBeanServer and userMBeanServer field declarations. - */ - private void insertUserMBeanServer(MBeanServer mbs) { - MBeanServerForwarder lastSystemMBSF = systemMBeanServerForwarder; - while (true) { - MBeanServer mbsi = lastSystemMBSF.getMBeanServer(); - if (mbsi == userMBeanServer) - break; - lastSystemMBSF = (MBeanServerForwarder) mbsi; - } - userMBeanServer = mbs; - lastSystemMBSF.setMBeanServer(mbs); - } - /** - *

    Returns the first item in the chain of system and then user - * forwarders. There is a chain of {@link MBeanServerForwarder}s between - * a {@code JMXConnectorServer} and its {@code MBeanServer}. This chain - * consists of two sub-chains: first the system chain and then - * the user chain. Incoming requests are given to the first - * forwarder in the system chain. Each forwarder can handle a request - * itself, or more usually forward it to the next forwarder, perhaps with - * some extra behavior such as logging or security checking before or after - * the forwarding. The last forwarder in the system chain is followed by - * the first forwarder in the user chain.

    - * - *

    The object returned by this method is the first forwarder in the - * system chain. For a given {@code JMXConnectorServer}, this method - * always returns the same object, which simply forwards every request - * to the next object in the chain.

    - * - *

    Not all connector servers support a system chain of forwarders, - * although the standard {@linkplain - * javax.management.remote.rmi.RMIConnectorServer RMI connector - * server} does. For those that do not, this method will throw {@code - * UnsupportedOperationException}. All - * connector servers do support a user chain of forwarders.

    - * - *

    The system chain is usually defined by a - * connector server based on the environment Map; see {@link - * JMXConnectorServerFactory#newJMXConnectorServer - * JMXConnectorServerFactory.newJMXConnectorServer}. Allowing - * the connector server to define its forwarders in this way - * ensures that they are in the correct order - some forwarders - * need to be inserted before others for correct behavior. It is - * possible to modify the system chain, for example using {@code - * connectorServer.getSystemMBeanServerForwarder().setMBeanServer(mbsf)} or - * {@link #removeMBeanServerForwarder removeMBeanServerForwarder}, but in - * that case the system chain is no longer guaranteed to be correct.

    - * - *

    The user chain is defined by calling {@link - * #setMBeanServerForwarder setMBeanServerForwarder} to insert forwarders - * at the head of the user chain.

    - * - *

    This code illustrates how the chains can be traversed:

    - * - *
    -     * JMXConnectorServer cs;
    -     * System.out.println("system chain:");
    -     * MBeanServer mbs = cs.getSystemMBeanServerForwarder();
    -     * while (true) {
    -     *     if (mbs == cs.getMBeanServer())
    -     *         System.out.println("user chain:");
    -     *     if (!(mbs instanceof MBeanServerForwarder))
    -     *         break;
    -     *     MBeanServerForwarder mbsf = (MBeanServerForwarder) mbs;
    -     *     System.out.println("--forwarder: " + mbsf);
    -     *     mbs = mbsf.getMBeanServer();
    -     * }
    -     * System.out.println("--MBean Server");
    -     * 
    - * - *

    Note for connector server implementors

    - * - *

    Existing connector server implementations can be updated to support - * a system chain of forwarders as follows:

    - * - *
      - *
    • Override the {@link #supportsSystemMBeanServerForwarder()} - * method so that it returns true.

      - * - *
    • Call {@link #installStandardForwarders} from the constructor of - * the connector server.

      - * - *
    • Direct incoming requests to the result of {@link - * #getSystemMBeanServerForwarder()} instead of the result of {@link - * #getMBeanServer()}.

      - *
    - * - * @return the first item in the system chain of forwarders. - * - * @throws UnsupportedOperationException if {@link - * #supportsSystemMBeanServerForwarder} returns false. - * - * @see #supportsSystemMBeanServerForwarder - * @see #setMBeanServerForwarder - * - * @since 1.7 - */ - public MBeanServerForwarder getSystemMBeanServerForwarder() { - if (!supportsSystemMBeanServerForwarder()) { - throw new UnsupportedOperationException( - "System MBeanServerForwarder not supported by this " + - "connector server"); - } - return systemMBeanServerForwarder; - } - - /** - *

    Returns true if this connector server supports a system chain of - * {@link MBeanServerForwarder}s. The default implementation of this - * method returns false. Connector servers that do support the system - * chain must override this method to return true. - * - * @return true if this connector server supports the system chain of - * forwarders. - * - * @since 1.7 - */ - public boolean supportsSystemMBeanServerForwarder() { - return false; - } - - /** - * Closes a client connection. If the connection is successfully closed, - * the method {@link #connectionClosed} is called to notify interested parties. - *

    Not all connector servers support this method. For those that do, it - * should be possible to cause a new client connection to fail before it - * can be used, by calling this method from within a - * {@link javax.management.NotificationListener} - * when it receives a {@link JMXConnectionNotification#OPENED} notification. - * This allows the owner of a connector server to deny certain connections, - * typically based on the information in the connection id. - *

    The implementation of this method in {@code JMXConnectorServer} throws - * {@code UnsupportedOperationException}. Subclasses can override this - * method to support closing a specified client connection. - * - * @param connectionId the id of the client connection to be closed. - * @throws IllegalStateException if the server is not started or is closed. - * @throws IllegalArgumentException if {@code connectionId} is null or is - * not the id of any open connection. - * @throws java.io.IOException if an I/O error appears when closing the - * connection. - * - * @since 1.7 - */ - public void closeConnection(String connectionId) - throws IOException { - throw new UnsupportedOperationException(); - } - - /** - *

    Install {@link MBeanServerForwarder}s in the system chain - * based on the attributes in the given {@code Map}. A connector - * server that {@linkplain #supportsSystemMBeanServerForwarder supports} - * a system chain of {@code MBeanServerForwarder}s can call this method - * to add forwarders to that chain based on the contents of {@code env}. - * In order:

    - * - *
      - * - *
    • If {@link #EVENT_CLIENT_DELEGATE_FORWARDER} is absent, or is - * present with the value {@code "true"}, then a forwarder - * equivalent to {@link EventClientDelegate#newForwarder - * EventClientDelegate.newForwarder}{@code (sysMBSF.getMBeanServer(), - * sysMBSF)} is inserted at the start of the system chain, - * where {@code sysMBSF} is the object returned by {@link - * #getSystemMBeanServerForwarder()}.
    • - * - *
    • If {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is present with the - * value {@code "true"}, then a forwarder equivalent to - * {@link ClientContext#newLocalizeMBeanInfoForwarder - * ClientContext.newLocalizeMBeanInfoForwarder}{@code - * (sysMBSF.getMBeanServer())} is inserted at the start of the system - * chain.
    • - * - *
    • If {@link #CONTEXT_FORWARDER} is absent, or is present with - * the value {@code "true"}, then a forwarder equivalent to - * {@link ClientContext#newContextForwarder - * ClientContext.newContextForwarder}{@code (sysMSBF.getMBeanServer(), - * sysMBSF)} is inserted at the tart of the system chain.
    • - * - *
    - * - *

    For {@code EVENT_CLIENT_DELEGATE_FORWARDER} and {@code - * CONTEXT_FORWARDER}, if the attribute is absent from the {@code - * Map} and a system property of the same name is defined, then - * the value of the system property is used as if it were in the - * {@code Map}. - * - *

    Since each forwarder is inserted at the start of the chain, - * the final order of the forwarders is the reverse of the order - * above. This is important, because the {@code - * LOCALIZE_MBEAN_INFO_FORWARDER} can only work if the {@code - * CONTEXT_FORWARDER} has already installed the remote client's locale - * in the {@linkplain ClientContext#getContext context} of the current - * thread.

    - * - *

    Attributes in {@code env} that are not listed above are ignored - * by this method.

    - * - * @throws UnsupportedOperationException if {@link - * #supportsSystemMBeanServerForwarder} is false. - * - * @throws IllegalArgumentException if the relevant attributes in {@code env} are - * inconsistent, for example if {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is - * {@code "true"} but {@link #CONTEXT_FORWARDER} is {@code "false"}; or - * if one of the attributes has an illegal value. - * - * @since 1.7 - */ - protected void installStandardForwarders(Map env) { - MBeanServerForwarder sysMBSF = getSystemMBeanServerForwarder(); - - // Remember that forwarders must be added in reverse order! - - boolean ecd = EnvHelp.computeBooleanFromString( - env, EVENT_CLIENT_DELEGATE_FORWARDER, false, true); - boolean localize = EnvHelp.computeBooleanFromString( - env, LOCALIZE_MBEAN_INFO_FORWARDER, false, false); - boolean context = EnvHelp.computeBooleanFromString( - env, CONTEXT_FORWARDER, false, true); - - if (localize && !context) { - throw new IllegalArgumentException( - "Inconsistent environment parameters: " + - LOCALIZE_MBEAN_INFO_FORWARDER + "=\"true\" requires " + - CONTEXT_FORWARDER + "=\"true\""); - } - - if (ecd) { - MBeanServerForwarder mbsf = EventClientDelegate.newForwarder( - sysMBSF.getMBeanServer(), sysMBSF); - sysMBSF.setMBeanServer(mbsf); - } - - if (localize) { - MBeanServerForwarder mbsf = ClientContext.newLocalizeMBeanInfoForwarder( - sysMBSF.getMBeanServer()); - sysMBSF.setMBeanServer(mbsf); - } - - if (context) { - MBeanServerForwarder mbsf = ClientContext.newContextForwarder( - sysMBSF.getMBeanServer(), sysMBSF); - sysMBSF.setMBeanServer(mbsf); - } + if (mbeanServer != null) mbsf.setMBeanServer(mbeanServer); + mbeanServer = mbsf; } public String[] getConnectionIds() { @@ -753,8 +361,8 @@ public abstract class JMXConnectorServer ObjectName name) { if (mbs == null || name == null) throw new NullPointerException("Null MBeanServer or ObjectName"); - if (userMBeanServer == null) { - insertUserMBeanServer(mbs); + if (mbeanServer == null) { + mbeanServer = mbs; myName = name; } return name; @@ -788,53 +396,10 @@ public abstract class JMXConnectorServer myName = null; } - /* - * Fields describing the chains of forwarders (MBeanServerForwarders). - * In the general case, the forwarders look something like this: - * - * userMBeanServer - * | - * v - * systemMBeanServerForwarder -> mbsf2 -> mbsf3 -> mbsf4 -> mbsf5 -> mbs - * - * Here, each mbsfi is an MBeanServerForwarder, and the arrows - * illustrate its getMBeanServer() method. The last MBeanServerForwarder - * can point to an MBeanServer that is not instanceof MBeanServerForwarder, - * here mbs. - * - * The system chain is never empty because it always has at least - * systemMBeanServerForwarder. Initially, the user chain can be empty if - * this JMXConnectorServer was constructed without an MBeanServer. In - * this case, userMBS will be null. If there is initially an MBeanServer, - * userMBS will point to it. - * - * Whenever userMBS is changed, the system chain must be updated. Before - * the update, the last forwarder in the system chain points to the old - * value of userMBS (possibly null). It must be updated to point to - * the new value. The invariant is that starting from systemMBSF and - * repeatedly calling MBSF.getMBeanServer() you will end up at userMBS. - * The implication is that you will not see any MBeanServer object on the - * way that is not also an MBeanServerForwarder. - * - * The method insertUserMBeanServer contains the logic to change userMBS - * and adjust the system chain appropriately. - * - * If userMBS is null and this JMXConnectorServer is registered in an - * MBeanServer, then userMBS becomes that MBeanServer, and the system - * chain must be updated as just described. - * - * When systemMBSF is updated, there is no effect on userMBS. The system - * chain may contain forwarders even though the user chain is empty - * (there is no MBeanServer). In that case an attempt to forward an - * incoming request through the chain will fall off the end and fail with a - * NullPointerException. Usually a connector server will refuse to start() - * if it is not attached to an MBS, so this situation should not arise. + /** + * The MBeanServer used by this server to execute a client request. */ - - private MBeanServer userMBeanServer; - - private final MBeanServerForwarder systemMBeanServerForwarder = - new IdentityMBeanServerForwarder(); + private MBeanServer mbeanServer = null; /** * The name used to registered this server in an MBeanServer. @@ -842,7 +407,7 @@ public abstract class JMXConnectorServer */ private ObjectName myName; - private List connectionIds = new ArrayList(); + private final List connectionIds = new ArrayList(); private static final int[] sequenceNumberLock = new int[0]; private static long sequenceNumber; diff --git a/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java b/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java index b784b87e4..9600a539e 100644 --- a/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java +++ b/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java @@ -130,18 +130,12 @@ public interface JMXConnectorServerMBean { * MBeanServer.

    * * - *

    A connector server may support two chains of forwarders, - * a system chain and a user chain. See {@link - * JMXConnectorServer#getSystemMBeanServerForwarder} for details.

    - * * @param mbsf the new MBeanServerForwarder. * * @exception IllegalArgumentException if the call to {@link * MBeanServerForwarder#setMBeanServer mbsf.setMBeanServer} fails * with IllegalArgumentException. This includes the * case where mbsf is null. - * - * @see JMXConnectorServer#getSystemMBeanServerForwarder */ public void setMBeanServerForwarder(MBeanServerForwarder mbsf); diff --git a/src/share/classes/javax/management/remote/JMXServiceURL.java b/src/share/classes/javax/management/remote/JMXServiceURL.java index 06b3b92f9..82049042a 100644 --- a/src/share/classes/javax/management/remote/JMXServiceURL.java +++ b/src/share/classes/javax/management/remote/JMXServiceURL.java @@ -36,8 +36,6 @@ import java.net.MalformedURLException; import java.net.UnknownHostException; import java.util.BitSet; import java.util.StringTokenizer; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.InvalidKeyException; /** *

    The address of a JMX API connector server. Instances of this class @@ -338,50 +336,6 @@ public class JMXServiceURL implements Serializable { validate(); } - /** - *

    Construct a {@code JMXServiceURL} instance from the given - * {@code CompositeData}. The presence of this method means that - * {@code JMXServiceURL} is - * reconstructible in MXBeans.

    - * - *

    (The effect of this method could have been obtained more simply - * with a @{@link java.beans.ConstructorProperties ConstructorProperties} - * annotation on the four-parameter {@linkplain #JMXServiceURL( - * String, String, int, String) constructor}, but that would have meant - * that this API could not be implemented on versions of the Java platform - * that predated the introduction of that annotation.)

    - * - * @param cd a {@code CompositeData} object that must contain items called - * {@code protocol}, {@code host}, and {@code URLPath} of type {@code String} - * and {@code port} of type {@code Integer}. Such an object will be produced - * by the MXBean framework when mapping a {@code JMXServiceURL} - * instance to an Open Data value. - * - * @return a {@code JMXServiceURL} constructed with the protocol, host, - * port, and URL path extracted from the given {@code CompositeData}. - * - * @throws MalformedURLException if the given {@code CompositeData} does - * not contain all the required items with the required types or if the - * resultant URL is syntactically incorrect. - */ - public static JMXServiceURL from(CompositeData cd) - throws MalformedURLException { - try { - String proto = (String) cd.get("protocol"); - String host = (String) cd.get("host"); - int port = (Integer) cd.get("port"); - String urlPath = (String) cd.get("URLPath"); - return new JMXServiceURL(proto, host, port, urlPath); - } catch (RuntimeException e) { - // Could be InvalidKeyException if the item is missing, - // or ClassCastException if it is present but with the wrong type. - MalformedURLException x = new MalformedURLException(e.getMessage()); - x.initCause(e); - throw x; - } - } - private void validate() throws MalformedURLException { // Check protocol diff --git a/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java b/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java index acac5ec8f..e0f60821b 100644 --- a/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java +++ b/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java @@ -25,12 +25,10 @@ package javax.management.remote.rmi; -import com.sun.jmx.mbeanserver.Util; import static com.sun.jmx.mbeanserver.Util.cast; import com.sun.jmx.remote.internal.ServerCommunicatorAdmin; import com.sun.jmx.remote.internal.ServerNotifForwarder; import com.sun.jmx.remote.security.JMXSubjectDomainCombiner; -import com.sun.jmx.remote.security.NotificationAccessController; import com.sun.jmx.remote.security.SubjectDelegator; import com.sun.jmx.remote.util.ClassLoaderWithRepository; import com.sun.jmx.remote.util.ClassLogger; @@ -38,7 +36,6 @@ import com.sun.jmx.remote.util.EnvHelp; import com.sun.jmx.remote.util.OrderClassLoaders; import java.io.IOException; -import java.lang.reflect.UndeclaredThrowableException; import java.rmi.MarshalledObject; import java.rmi.UnmarshalException; import java.rmi.server.Unreferenced; @@ -59,25 +56,18 @@ import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; -import javax.management.JMX; 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.Notification; import javax.management.NotificationFilter; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.QueryExp; import javax.management.ReflectionException; import javax.management.RuntimeOperationsException; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.EventClientNotFoundException; -import javax.management.event.FetchingEventForwarder; -import javax.management.namespace.JMXNamespaces; import javax.management.remote.JMXServerErrorException; import javax.management.remote.NotificationResult; import javax.management.remote.TargetedNotification; @@ -168,6 +158,17 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { this.env = env; } + private synchronized ServerNotifForwarder getServerNotifFwd() { + // Lazily created when first use. Mainly when + // addNotificationListener is first called. + if (serverNotifForwarder == null) + serverNotifForwarder = + new ServerNotifForwarder(mbeanServer, + env, + rmiServer.getNotifBuffer(), + connectionId); + return serverNotifForwarder; + } public String getConnectionId() throws IOException { // We should call reqIncomming() here... shouldn't we? @@ -178,7 +179,6 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { final boolean debug = logger.debugOn(); final String idstr = (debug?"["+this.toString()+"]":null); - final SubscriptionManager mgr; synchronized (this) { if (terminated) { if (debug) logger.debug("close",idstr + " already terminated."); @@ -193,12 +193,11 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { serverCommunicatorAdmin.terminate(); } - mgr = subscriptionManager; - subscriptionManager = null; + if (serverNotifForwarder != null) { + serverNotifForwarder.terminate(); + } } - if (mgr != null) mgr.terminate(); - rmiServer.clientClosed(this); if (debug) logger.debug("close",idstr + " closed."); @@ -997,7 +996,8 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { // remove all registered listeners for (int j=0; j action = - new PrivilegedExceptionAction() { - public NotificationResult run() throws IOException { - return doFetchNotifs(csn, t, mn); + PrivilegedAction action = + new PrivilegedAction() { + public NotificationResult run() { + return getServerNotifFwd().fetchNotifs(csn, t, mn); } }; - try { - if (acc == null) - return action.run(); - else - return AccessController.doPrivileged(action, acc); - } catch (IOException x) { - throw x; - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - // should not happen - throw new UndeclaredThrowableException(x); - } - + if (acc == null) + return action.run(); + else + return AccessController.doPrivileged(action, acc); } finally { serverCommunicatorAdmin.rspOutgoing(); } } - /** - * This is an abstraction class that let us use the legacy - * ServerNotifForwarder and the new EventClientDelegateMBean - * indifferently. - **/ - private static interface SubscriptionManager { - public void removeNotificationListener(ObjectName name, Integer id) - throws InstanceNotFoundException, ListenerNotFoundException, IOException; - public void removeNotificationListener(ObjectName name, Integer[] ids) - throws Exception; - public NotificationResult fetchNotifications(long csn, long timeout, int maxcount) - throws IOException; - public Integer addNotificationListener(ObjectName name, NotificationFilter filter) - throws InstanceNotFoundException, IOException; - public void terminate() - throws IOException; - } - - /** - * A SubscriptionManager that uses a ServerNotifForwarder. - **/ - private static class LegacySubscriptionManager implements SubscriptionManager { - private final ServerNotifForwarder forwarder; - LegacySubscriptionManager(ServerNotifForwarder forwarder) { - this.forwarder = forwarder; - } - - public void removeNotificationListener(ObjectName name, Integer id) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - if (!JMXNamespaces.getContainingNamespace(name).equals("")) { - logger.debug("removeNotificationListener", - "This connector server is not configured to support " + - "forwarding of notification subscriptions to name spaces"); - throw new RuntimeOperationsException( - new UnsupportedOperationException( - "removeNotificationListener on name space MBeans. ")); - } - forwarder.removeNotificationListener(name,id); - } - - public void removeNotificationListener(ObjectName name, Integer[] ids) - throws Exception { - if (!JMXNamespaces.getContainingNamespace(name).equals("")) { - logger.debug("removeNotificationListener", - "This connector server is not configured to support " + - "forwarding of notification subscriptions to name spaces"); - throw new RuntimeOperationsException( - new UnsupportedOperationException( - "removeNotificationListener on name space MBeans. ")); - } - forwarder.removeNotificationListener(name,ids); - } - - public NotificationResult fetchNotifications(long csn, long timeout, int maxcount) { - return forwarder.fetchNotifs(csn,timeout,maxcount); - } - - public Integer addNotificationListener(ObjectName name, - NotificationFilter filter) - throws InstanceNotFoundException, IOException { - if (!JMXNamespaces.getContainingNamespace(name).equals("")) { - logger.debug("addNotificationListener", - "This connector server is not configured to support " + - "forwarding of notification subscriptions to name spaces"); - throw new RuntimeOperationsException( - new UnsupportedOperationException( - "addNotificationListener on name space MBeans. ")); - } - return forwarder.addNotificationListener(name,filter); - } - - public void terminate() { - forwarder.terminate(); - } - } - - /** - * A SubscriptionManager that uses an EventClientDelegateMBean. - **/ - private static class EventSubscriptionManager - implements SubscriptionManager { - private final MBeanServer mbeanServer; - private final EventClientDelegateMBean delegate; - private final NotificationAccessController notifAC; - private final boolean checkNotificationEmission; - private final String clientId; - private final String connectionId; - private volatile String mbeanServerName; - - EventSubscriptionManager( - MBeanServer mbeanServer, - EventClientDelegateMBean delegate, - Map env, - String clientId, - String connectionId) { - this.mbeanServer = mbeanServer; - this.delegate = delegate; - this.notifAC = EnvHelp.getNotificationAccessController(env); - this.checkNotificationEmission = - EnvHelp.computeBooleanFromString( - env, "jmx.remote.x.check.notification.emission", false); - this.clientId = clientId; - this.connectionId = connectionId; - } - - private String mbeanServerName() { - if (mbeanServerName != null) return mbeanServerName; - else return (mbeanServerName = getMBeanServerName(mbeanServer)); - } - - @SuppressWarnings("serial") // no serialVersionUID - private class AccessControlFilter implements NotificationFilter { - private final NotificationFilter wrapped; - private final ObjectName name; - - AccessControlFilter(ObjectName name, NotificationFilter wrapped) { - this.name = name; - this.wrapped = wrapped; - } - - public boolean isNotificationEnabled(Notification notification) { - try { - if (checkNotificationEmission) { - ServerNotifForwarder.checkMBeanPermission( - mbeanServerName(), mbeanServer, name, - "addNotificationListener"); - } - notifAC.fetchNotification( - connectionId, name, notification, getSubject()); - return (wrapped == null) ? true : - wrapped.isNotificationEnabled(notification); - } catch (InstanceNotFoundException e) { - return false; - } catch (SecurityException e) { - return false; - } - } - - } - - public Integer addNotificationListener( - ObjectName name, NotificationFilter filter) - throws InstanceNotFoundException, IOException { - if (notifAC != null) { - notifAC.addNotificationListener(connectionId, name, getSubject()); - filter = new AccessControlFilter(name, filter); - } - try { - return delegate.addListener(clientId,name,filter); - } catch (EventClientNotFoundException x) { - throw new IOException("Unknown clientId: "+clientId,x); - } - } - - public void removeNotificationListener(ObjectName name, Integer id) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - if (notifAC != null) - notifAC.removeNotificationListener(connectionId, name, getSubject()); - try { - delegate.removeListenerOrSubscriber(clientId, id); - } catch (EventClientNotFoundException x) { - throw new IOException("Unknown clientId: "+clientId,x); - } - } - - public void removeNotificationListener(ObjectName name, Integer[] ids) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - if (notifAC != null) - notifAC.removeNotificationListener(connectionId, name, getSubject()); - try { - for (Integer id : ids) - delegate.removeListenerOrSubscriber(clientId, id); - } catch (EventClientNotFoundException x) { - throw new IOException("Unknown clientId: "+clientId,x); - } - } - - public NotificationResult fetchNotifications(long csn, long timeout, - int maxcount) - throws IOException { - try { - // For some reason the delegate doesn't accept a negative - // sequence number. However legacy clients will always call - // fetchNotifications with a negative sequence number, when - // they call it for the first time. - // In that case, we will use 0 instead. - // - return delegate.fetchNotifications( - clientId, Math.max(csn, 0), maxcount, timeout); - } catch (EventClientNotFoundException x) { - throw new IOException("Unknown clientId: "+clientId,x); - } - } - - public void terminate() - throws IOException { - try { - delegate.removeClient(clientId); - } catch (EventClientNotFoundException x) { - throw new IOException("Unknown clientId: "+clientId,x); - } - } - - private static Subject getSubject() { - return Subject.getSubject(AccessController.getContext()); - } - } - - /** - * Creates a SubscriptionManager that uses either the legacy notifications - * mechanism (ServerNotifForwarder) or the new event service - * (EventClientDelegateMBean) depending on which option was passed in - * the connector's map. - **/ - private SubscriptionManager createSubscriptionManager() - throws IOException { - if (EnvHelp.delegateToEventService(env) && - mbeanServer.isRegistered(EventClientDelegate.OBJECT_NAME)) { - final EventClientDelegateMBean mbean = - JMX.newMBeanProxy(mbeanServer, - EventClientDelegate.OBJECT_NAME, - EventClientDelegateMBean.class); - String clientId; - try { - clientId = - mbean.addClient( - FetchingEventForwarder.class.getName(), - new Object[] {EnvHelp.getNotifBufferSize(env)}, - new String[] {int.class.getName()}); - } catch (Exception e) { - if (e instanceof IOException) - throw (IOException) e; - else - throw new IOException(e); - } - - // we're going to call remove client... - try { - mbean.lease(clientId, Long.MAX_VALUE); - } catch (EventClientNotFoundException x) { - throw new IOException("Unknown clientId: "+clientId,x); - } - return new EventSubscriptionManager(mbeanServer, mbean, env, - clientId, connectionId); - } else { - final ServerNotifForwarder serverNotifForwarder = - new ServerNotifForwarder(mbeanServer, - env, - rmiServer.getNotifBuffer(), - connectionId); - return new LegacySubscriptionManager(serverNotifForwarder); - } - } - - /** - * Lazy creation of a SubscriptionManager. - **/ - private synchronized SubscriptionManager getSubscriptionManager() - throws IOException { - // Lazily created when first use. Mainly when - // addNotificationListener is first called. - - if (subscriptionManager == null) { - subscriptionManager = createSubscriptionManager(); - } - return subscriptionManager; - } - - // calls SubscriptionManager. - private void doRemoveListener(ObjectName name, Integer id) - throws InstanceNotFoundException, ListenerNotFoundException, - IOException { - getSubscriptionManager().removeNotificationListener(name,id); - } - - // calls SubscriptionManager. - private void doRemoveListener(ObjectName name, Integer[] ids) - throws Exception { - getSubscriptionManager().removeNotificationListener(name,ids); - } - - // calls SubscriptionManager. - private NotificationResult doFetchNotifs(long csn, long timeout, int maxcount) - throws IOException { - return getSubscriptionManager().fetchNotifications(csn, timeout, maxcount); - } - - // calls SubscriptionManager. - private Integer doAddListener(ObjectName name, NotificationFilter filter) - throws InstanceNotFoundException, IOException { - return getSubscriptionManager().addNotificationListener(name,filter); - } - - /** *

    Returns a string representation of this object. In general, * the toString method returns a string that @@ -1787,8 +1479,9 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { return null; case ADD_NOTIFICATION_LISTENERS: - return doAddListener((ObjectName)params[0], - (NotificationFilter)params[1]); + return getServerNotifFwd().addNotificationListener( + (ObjectName)params[0], + (NotificationFilter)params[1]); case ADD_NOTIFICATION_LISTENER_OBJECTNAME: mbeanServer.addNotificationListener((ObjectName)params[0], @@ -1798,7 +1491,9 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { return null; case REMOVE_NOTIFICATION_LISTENER: - doRemoveListener((ObjectName)params[0],(Integer[])params[1]); + getServerNotifFwd().removeNotificationListener( + (ObjectName)params[0], + (Integer[])params[1]); return null; case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME: @@ -1909,15 +1604,6 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { return e; } - private static String getMBeanServerName(final MBeanServer server) { - final PrivilegedAction action = new PrivilegedAction() { - public String run() { - return Util.getMBeanServerSecurityName(server); - } - }; - return AccessController.doPrivileged(action); - } - private static final Object[] NO_OBJECTS = new Object[0]; private static final String[] NO_STRINGS = new String[0]; @@ -2033,7 +1719,7 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced { // SERVER NOTIFICATION //-------------------- - private SubscriptionManager subscriptionManager; + private ServerNotifForwarder serverNotifForwarder; private Map env; // TRACES & DEBUG diff --git a/src/share/classes/javax/management/remote/rmi/RMIConnector.java b/src/share/classes/javax/management/remote/rmi/RMIConnector.java index 5f1b8ac71..4b865166b 100644 --- a/src/share/classes/javax/management/remote/rmi/RMIConnector.java +++ b/src/share/classes/javax/management/remote/rmi/RMIConnector.java @@ -25,9 +25,6 @@ package javax.management.remote.rmi; -import com.sun.jmx.event.DaemonThreadFactory; -import com.sun.jmx.event.EventConnection; -import com.sun.jmx.mbeanserver.PerThreadGroupPool; import com.sun.jmx.mbeanserver.Util; import com.sun.jmx.remote.internal.ClientCommunicatorAdmin; import com.sun.jmx.remote.internal.ClientListenerInfo; @@ -72,11 +69,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.WeakHashMap; -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; @@ -84,7 +76,6 @@ import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; -import javax.management.JMX; import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; @@ -102,8 +93,6 @@ import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.QueryExp; import javax.management.ReflectionException; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegateMBean; import javax.management.remote.JMXConnectionNotification; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; @@ -224,6 +213,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable * * @return a String representation of this object. **/ + @Override public String toString() { final StringBuilder b = new StringBuilder(this.getClass().getName()); b.append(":"); @@ -330,8 +320,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable // connectionId = getConnectionId(); - eventServiceEnabled = EnvHelp.eventServiceEnabled(env); - Notification connectedNotif = new JMXConnectionNotification(JMXConnectionNotification.OPENED, this, @@ -341,8 +329,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable null); sendNotification(connectedNotif); - // whether or not event service - if (tracing) logger.trace("connect",idstr + " done..."); } catch (IOException e) { if (tracing) @@ -400,38 +386,10 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable } rmbsc = new RemoteMBeanServerConnection(delegationSubject); - if (eventServiceEnabled) { - EventClientDelegateMBean ecd = JMX.newMBeanProxy( - rmbsc, EventClientDelegateMBean.OBJECT_NAME, - EventClientDelegateMBean.class); - EventClient ec = new EventClient(ecd, null, defaultExecutor(), null, - EventClient.DEFAULT_REQUESTED_LEASE_TIME); - - rmbsc = EventConnection.Factory.make(rmbsc, ec); - ec.addEventClientListener( - lostNotifListener, null, null); - } rmbscMap.put(delegationSubject, rmbsc); return rmbsc; } - private static Executor defaultExecutor() { - PerThreadGroupPool.Create create = - new PerThreadGroupPool.Create() { - public ThreadPoolExecutor createThreadPool(ThreadGroup group) { - ThreadFactory daemonThreadFactory = new DaemonThreadFactory( - "JMX RMIConnector listener dispatch %d"); - ThreadPoolExecutor executor = new ThreadPoolExecutor( - 1, 10, 1, TimeUnit.SECONDS, - new LinkedBlockingQueue(), - daemonThreadFactory); - executor.allowCoreThreadTimeOut(true); - return executor; - } - }; - return listenerDispatchThreadPool.getThreadPoolExecutor(create); - } - public void addConnectionNotificationListener(NotificationListener listener, NotificationFilter filter, @@ -511,17 +469,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable communicatorAdmin.terminate(); } - // close all EventClient - for (MBeanServerConnection rmbsc : rmbscMap.values()) { - if (rmbsc instanceof EventConnection) { - try { - ((EventConnection)rmbsc).getEventClient().close(); - } catch (Exception e) { - // OK - } - } - } - if (rmiNotifClient != null) { try { rmiNotifClient.terminate(); @@ -660,8 +607,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable private class RemoteMBeanServerConnection implements MBeanServerConnection { private Subject delegationSubject; - public EventClient eventClient = null; - public RemoteMBeanServerConnection() { this(null); } @@ -1504,6 +1449,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable super(period); } + @Override public void gotIOException(IOException ioe) throws IOException { if (ioe instanceof NoSuchObjectException) { // need to restart @@ -1865,26 +1811,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable terminated = false; connectionBroadcaster = new NotificationBroadcasterSupport(); - - lostNotifListener = - new NotificationListener() { - public void handleNotification(Notification n, Object hb) { - if (n != null && EventClient.NOTIFS_LOST.equals(n.getType())) { - Long lost = (Long)n.getUserData(); - final String msg = - "May have lost up to " + lost + - " notification" + (lost.longValue() == 1 ? "" : "s"); - sendNotification(new JMXConnectionNotification( - JMXConnectionNotification.NOTIFS_LOST, - RMIConnector.this, - connectionId, - clientNotifCounter++, - msg, - lost)); - - } - } - }; } //-------------------------------------------------------------------- @@ -2609,11 +2535,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable private transient ClientCommunicatorAdmin communicatorAdmin; - private boolean eventServiceEnabled; -// private transient EventRelay eventRelay; - - private transient NotificationListener lostNotifListener; - /** * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to * connect unconnected stubs. @@ -2632,7 +2553,4 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable private static String strings(final String[] strs) { return objects(strs); } - - private static final PerThreadGroupPool listenerDispatchThreadPool = - PerThreadGroupPool.make(); } diff --git a/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java b/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java index 7acc02adb..9e4efdd18 100644 --- a/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java +++ b/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java @@ -230,8 +230,6 @@ public class RMIConnectorServer extends JMXConnectorServer { this.address = url; this.rmiServerImpl = rmiServerImpl; - - installStandardForwarders(this.attributes); } /** @@ -383,7 +381,7 @@ public class RMIConnectorServer extends JMXConnectorServer { try { if (tracing) logger.trace("start", "setting default class loader"); defaultClassLoader = EnvHelp.resolveServerClassLoader( - attributes, getSystemMBeanServerForwarder()); + attributes, getMBeanServer()); } catch (InstanceNotFoundException infc) { IllegalArgumentException x = new IllegalArgumentException("ClassLoader not found: "+infc); @@ -398,7 +396,7 @@ public class RMIConnectorServer extends JMXConnectorServer { else rmiServer = newServer(); - rmiServer.setMBeanServer(getSystemMBeanServerForwarder()); + rmiServer.setMBeanServer(getMBeanServer()); rmiServer.setDefaultClassLoader(defaultClassLoader); rmiServer.setRMIConnectorServer(this); rmiServer.export(); @@ -592,34 +590,12 @@ public class RMIConnectorServer extends JMXConnectorServer { return Collections.unmodifiableMap(map); } - /** - * {@inheritDoc} - * @return true, since this connector server does support a system chain - * of forwarders. - */ - @Override - public boolean supportsSystemMBeanServerForwarder() { - return true; - } - - /** - * {@inheritDoc} - *

    The {@code RMIConnectorServer} class does support closing a specified - * client connection. - * @throws IllegalStateException if the server is not started or is closed. - * @throws IllegalArgumentException if {@code connectionId} is null or is - * not the id of any open connection. - * @since 1.7 - */ @Override - public void closeConnection(String connectionId) - throws IOException { - if (isActive()) { - rmiServerImpl.closeConnection(connectionId); - } else { - throw new IllegalStateException( - "The server is not started or is closed."); - } + public synchronized + void setMBeanServerForwarder(MBeanServerForwarder mbsf) { + super.setMBeanServerForwarder(mbsf); + if (rmiServerImpl != null) + rmiServerImpl.setMBeanServer(getMBeanServer()); } /* We repeat the definitions of connection{Opened,Closed,Failed} diff --git a/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java b/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java index e7e5ffeb4..94c6eed61 100644 --- a/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java +++ b/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java @@ -270,52 +270,6 @@ public abstract class RMIServerImpl implements Closeable, RMIServer { return client; } - /** - * Closes a client connection. - * @param connectionId the id of the client connection to be closed. - * @throws IllegalArgumentException if {@code connectionId} is null or is - * not the id of any open connection. - * @throws java.io.IOException if an I/O error appears when closing the - * connection. - * - * @since 1.7 - */ - public void closeConnection(String connectionId) - throws IOException { - final boolean debug = logger.debugOn(); - - if (debug) logger.trace("closeConnection","cconnectionId="+connectionId); - - if (connectionId == null) - throw new IllegalArgumentException("Null connectionId."); - - RMIConnection client = null; - synchronized (clientList) { - dropDeadReferences(); - for (Iterator> it = clientList.iterator(); - it.hasNext(); ) { - client = it.next().get(); - if (client != null && connectionId.equals(client.getConnectionId())) { - it.remove(); - break; - } - } - } - - if (client == null) { - throw new IllegalArgumentException("Unknown id: "+connectionId); - } - - if (debug) logger.trace("closeConnection", "closing client connection."); - closeClient(client); - - if (debug) logger.trace("closeConnection", "sending notif"); - connServer.connectionClosed(connectionId, - "Client connection closed", null); - - if (debug) logger.trace("closeConnection","done"); - } - /** *

    Creates a new client connection. This method is called by * the public method {@link #newClient(Object)}.

    diff --git a/src/share/classes/sun/management/ClassLoadingImpl.java b/src/share/classes/sun/management/ClassLoadingImpl.java index 9eda58380..2f4b6ed07 100644 --- a/src/share/classes/sun/management/ClassLoadingImpl.java +++ b/src/share/classes/sun/management/ClassLoadingImpl.java @@ -71,6 +71,6 @@ class ClassLoadingImpl implements ClassLoadingMXBean { native static void setVerboseClass(boolean value); public ObjectName getObjectName() { - return ObjectName.valueOf(ManagementFactory.CLASS_LOADING_MXBEAN_NAME); + return Util.newObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME); } } diff --git a/src/share/classes/sun/management/CompilationImpl.java b/src/share/classes/sun/management/CompilationImpl.java index 9c13e67eb..d69d9cc64 100644 --- a/src/share/classes/sun/management/CompilationImpl.java +++ b/src/share/classes/sun/management/CompilationImpl.java @@ -70,7 +70,7 @@ class CompilationImpl implements CompilationMXBean { } public ObjectName getObjectName() { - return ObjectName.valueOf(ManagementFactory.COMPILATION_MXBEAN_NAME); + return Util.newObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME); } diff --git a/src/share/classes/sun/management/HotSpotDiagnostic.java b/src/share/classes/sun/management/HotSpotDiagnostic.java index d33337fcf..cedfe5ae2 100644 --- a/src/share/classes/sun/management/HotSpotDiagnostic.java +++ b/src/share/classes/sun/management/HotSpotDiagnostic.java @@ -25,9 +25,9 @@ package sun.management; -import java.util.*; import java.io.IOException; -import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import javax.management.ObjectName; import com.sun.management.HotSpotDiagnosticMXBean; @@ -117,6 +117,6 @@ public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean { } public ObjectName getObjectName() { - return ObjectName.valueOf("com.sun.management:type=HotSpotDiagnostic"); + return Util.newObjectName("com.sun.management:type=HotSpotDiagnostic"); } } diff --git a/src/share/classes/sun/management/HotspotInternal.java b/src/share/classes/sun/management/HotspotInternal.java index 88f9a8268..7006699a4 100644 --- a/src/share/classes/sun/management/HotspotInternal.java +++ b/src/share/classes/sun/management/HotspotInternal.java @@ -41,7 +41,7 @@ public class HotspotInternal private final static String HOTSPOT_INTERNAL_MBEAN_NAME = "sun.management:type=HotspotInternal"; - private static ObjectName objName = ObjectName.valueOf(HOTSPOT_INTERNAL_MBEAN_NAME); + private static ObjectName objName = Util.newObjectName(HOTSPOT_INTERNAL_MBEAN_NAME); private MBeanServer server = null; /** diff --git a/src/share/classes/sun/management/ManagementFactoryHelper.java b/src/share/classes/sun/management/ManagementFactoryHelper.java index 06c2439ab..d91dd8dd1 100644 --- a/src/share/classes/sun/management/ManagementFactoryHelper.java +++ b/src/share/classes/sun/management/ManagementFactoryHelper.java @@ -160,7 +160,7 @@ public class ManagementFactoryHelper { if (result == null) { synchronized (this) { if (objname == null) { - result = ObjectName.valueOf(BUFFER_POOL_MXBEAN_NAME + + result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME + ",name=" + pool.getName()); objname = result; } @@ -257,7 +257,7 @@ public class ManagementFactoryHelper { */ private static void addMBean(MBeanServer mbs, Object mbean, String mbeanName) { try { - final ObjectName objName = ObjectName.valueOf(mbeanName); + final ObjectName objName = Util.newObjectName(mbeanName); // inner class requires these fields to be final final MBeanServer mbs0 = mbs; @@ -317,7 +317,7 @@ public class ManagementFactoryHelper { private static void unregisterMBean(MBeanServer mbs, String mbeanName) { try { - final ObjectName objName = ObjectName.valueOf(mbeanName); + final ObjectName objName = Util.newObjectName(mbeanName); // inner class requires these fields to be final final MBeanServer mbs0 = mbs; diff --git a/src/share/classes/sun/management/MemoryImpl.java b/src/share/classes/sun/management/MemoryImpl.java index aa56186ae..7e53f5a97 100644 --- a/src/share/classes/sun/management/MemoryImpl.java +++ b/src/share/classes/sun/management/MemoryImpl.java @@ -34,15 +34,7 @@ import java.lang.management.MemoryPoolMXBean; import javax.management.ObjectName; import javax.management.MBeanNotificationInfo; import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ListenerNotFoundException; import javax.management.openmbean.CompositeData; -import java.util.List; -import java.util.ArrayList; -import java.util.ListIterator; -import java.util.Collections; /** * Implementation class for the memory subsystem. @@ -177,7 +169,7 @@ class MemoryImpl extends NotificationEmitterSupport } public ObjectName getObjectName() { - return ObjectName.valueOf(ManagementFactory.MEMORY_MXBEAN_NAME); + return Util.newObjectName(ManagementFactory.MEMORY_MXBEAN_NAME); } } diff --git a/src/share/classes/sun/management/OperatingSystemImpl.java b/src/share/classes/sun/management/OperatingSystemImpl.java index 18f28e09b..d91aaa866 100644 --- a/src/share/classes/sun/management/OperatingSystemImpl.java +++ b/src/share/classes/sun/management/OperatingSystemImpl.java @@ -74,7 +74,7 @@ public class OperatingSystemImpl implements OperatingSystemMXBean { } } public ObjectName getObjectName() { - return ObjectName.valueOf(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME); + return Util.newObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME); } } diff --git a/src/share/classes/sun/management/RuntimeImpl.java b/src/share/classes/sun/management/RuntimeImpl.java index 55bcbdc85..d698916b0 100644 --- a/src/share/classes/sun/management/RuntimeImpl.java +++ b/src/share/classes/sun/management/RuntimeImpl.java @@ -33,12 +33,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Properties; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.OpenDataException; import javax.management.ObjectName; /** @@ -149,7 +143,7 @@ class RuntimeImpl implements RuntimeMXBean { } public ObjectName getObjectName() { - return ObjectName.valueOf(ManagementFactory.RUNTIME_MXBEAN_NAME); + return Util.newObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME); } } diff --git a/src/share/classes/sun/management/ThreadImpl.java b/src/share/classes/sun/management/ThreadImpl.java index 6604c72b7..b7be6a765 100644 --- a/src/share/classes/sun/management/ThreadImpl.java +++ b/src/share/classes/sun/management/ThreadImpl.java @@ -29,10 +29,6 @@ import java.lang.management.ThreadMXBean; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; -import java.lang.management.LockInfo; -import java.lang.management.MonitorInfo; -import java.util.Map; -import java.util.HashMap; import javax.management.ObjectName; @@ -415,7 +411,7 @@ class ThreadImpl implements ThreadMXBean { private static native void resetContentionTimes0(long tid); public ObjectName getObjectName() { - return ObjectName.valueOf(ManagementFactory.THREAD_MXBEAN_NAME); + return Util.newObjectName(ManagementFactory.THREAD_MXBEAN_NAME); } } diff --git a/src/share/classes/sun/management/Util.java b/src/share/classes/sun/management/Util.java index 1da808300..53f879ce8 100644 --- a/src/share/classes/sun/management/Util.java +++ b/src/share/classes/sun/management/Util.java @@ -25,26 +25,34 @@ package sun.management; -import java.lang.management.*; +import java.lang.management.ManagementPermission; import java.util.List; -import java.security.Permission; import javax.management.ObjectName; import javax.management.MalformedObjectNameException; -import static java.lang.management.ManagementFactory.*; -class Util { +public class Util { + private Util() {} // there are no instances of this class + static RuntimeException newException(Exception e) { throw new RuntimeException(e); } private static final String[] EMPTY_STRING_ARRAY = new String[0]; static String[] toStringArray(List list) { - return (String[]) list.toArray(EMPTY_STRING_ARRAY); + return list.toArray(EMPTY_STRING_ARRAY); } public static ObjectName newObjectName(String domainAndType, String name) { - return ObjectName.valueOf(domainAndType + ",name=" + name); + return newObjectName(domainAndType + ",name=" + name); + } + + public static ObjectName newObjectName(String name) { + try { + return ObjectName.getInstance(name); + } catch (MalformedObjectNameException e) { + throw new IllegalArgumentException(e); + } } private static ManagementPermission monitorPermission = diff --git a/test/javax/management/Introspector/AnnotatedMBeanTest.java b/test/javax/management/Introspector/AnnotatedMBeanTest.java deleted file mode 100644 index 382a1219c..000000000 --- a/test/javax/management/Introspector/AnnotatedMBeanTest.java +++ /dev/null @@ -1,337 +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. - * - * 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. - */ - -/* - * @test %M% %I% - * @bug 6323980 - * @summary Test MBeans defined with @MBean - * @author Eamonn McManus - * @run main/othervm -ea AnnotatedMBeanTest - */ - -import java.io.File; -import java.io.PrintWriter; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import javax.management.Attribute; -import javax.management.Descriptor; -import javax.management.DescriptorKey; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.MXBean; -import javax.management.MalformedObjectNameException; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; -import javax.management.MBean; -import javax.management.ObjectName; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeType; - -public class AnnotatedMBeanTest { - private static MBeanServer mbs; - private static final ObjectName objectName; - static { - try { - objectName = new ObjectName("test:type=Test"); - } catch (MalformedObjectNameException e) { - throw new RuntimeException(e); - } - } - - public static void main(String[] args) throws Exception { - if (!AnnotatedMBeanTest.class.desiredAssertionStatus()) - throw new Exception("Test must be run with -ea"); - - File policyFile = File.createTempFile("jmxperms", ".policy"); - policyFile.deleteOnExit(); - PrintWriter pw = new PrintWriter(policyFile); - pw.println("grant {"); - pw.println(" permission javax.management.MBeanPermission \"*\", \"*\";"); - pw.println(" permission javax.management.MBeanServerPermission \"*\";"); - pw.println(" permission javax.management.MBeanTrustPermission \"*\";"); - pw.println("};"); - pw.close(); - - System.setProperty("java.security.policy", policyFile.getAbsolutePath()); - System.setSecurityManager(new SecurityManager()); - - String failure = null; - - for (Method m : AnnotatedMBeanTest.class.getDeclaredMethods()) { - if (Modifier.isStatic(m.getModifiers()) && - m.getName().startsWith("test") && - m.getParameterTypes().length == 0) { - mbs = MBeanServerFactory.newMBeanServer(); - try { - m.invoke(null); - System.out.println(m.getName() + " OK"); - } catch (InvocationTargetException ite) { - System.out.println(m.getName() + " got exception:"); - Throwable t = ite.getCause(); - t.printStackTrace(System.out); - failure = m.getName() + ": " + t.toString(); - } - } - } - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - public static class Stats { - private final int used; - private final int size; - private final boolean interesting; - - public Stats(int used, int size, boolean interesting) { - this.used = used; - this.size = size; - this.interesting = interesting; - } - - public int getUsed() { - return used; - } - - public int getSize() { - return size; - } - - public boolean isInteresting() { - return interesting; - } - } - - @Retention(RetentionPolicy.RUNTIME) - public static @interface Units { - @DescriptorKey("units") - String value(); - } - - @MBean - public static class Cache { - private int used = 23; - private int size = 99; - - @ManagedAttribute - @Units("bytes") - public int getUsed() { - return used; - } - - @ManagedAttribute - public int getSize() { - return size; - } - - @ManagedAttribute - public void setSize(int x) { - this.size = x; - } - - @ManagedAttribute - public boolean isInteresting() { - return false; - } - - @ManagedAttribute - public Stats getStats() { - return new Stats(used, size, false); - } - - @ManagedOperation - public int dropOldest(int n) { - return 55; - } - - private void irrelevantMethod() {} - private int getIrrelevant() {return 0;} - public int getIrrelevant2() {return 0;} - - public int otherIrrelevantMethod() {return 5;} - } - - public static class SubCache extends Cache { - // SubCache does not have the @MBean annotation - // but its parent does. It doesn't add any @ManagedAttribute or - // @ManagedOperation methods, so its management interface - // should be the same. - private void irrelevantMethod2() {} - public int otherIrrelevantMethod3() {return 0;} - - public int getX() {return 0;} - public void setX(int x) {} - } - - @MXBean - public static class CacheMX { - private int used = 23; - private int size = 99; - - @ManagedAttribute - @Units("bytes") - public int getUsed() { - return used; - } - - @ManagedAttribute - public int getSize() { - return size; - } - - @ManagedAttribute - public void setSize(int x) { - this.size = x; - } - - @ManagedAttribute - public boolean isInteresting() { - return false; - } - - @ManagedAttribute - public Stats getStats() { - return new Stats(used, size, false); - } - - @ManagedOperation - public int dropOldest(int n) { - return 55; - } - - private void irrelevantMethod() {} - private int getIrrelevant() {return 0;} - public int getIrrelevant2() {return 0;} - - public int otherIrrelevantMethod() {return 5;} - } - - public static class SubCacheMX extends CacheMX { - private void irrelevantMethod2() {} - public int otherIrrelevantMethod3() {return 0;} - - public int getX() {return 0;} - public void setX(int x) {} - } - - private static void testSimpleManagedResource() throws Exception { - testResource(new Cache(), false); - } - - private static void testSubclassManagedResource() throws Exception { - testResource(new SubCache(), false); - } - - private static void testMXBeanResource() throws Exception { - testResource(new CacheMX(), true); - } - - private static void testSubclassMXBeanResource() throws Exception { - testResource(new SubCacheMX(), true); - } - - private static void testResource(Object resource, boolean mx) throws Exception { - mbs.registerMBean(resource, objectName); - - MBeanInfo mbi = mbs.getMBeanInfo(objectName); - assert mbi.getDescriptor().getFieldValue("mxbean").equals(Boolean.toString(mx)); - - MBeanAttributeInfo[] mbais = mbi.getAttributes(); - - assert mbais.length == 4: mbais.length; - - for (MBeanAttributeInfo mbai : mbais) { - String name = mbai.getName(); - if (name.equals("Used")) { - assert mbai.isReadable(); - assert !mbai.isWritable(); - assert !mbai.isIs(); - assert mbai.getType().equals("int"); - assert "bytes".equals(mbai.getDescriptor().getFieldValue("units")); - } else if (name.equals("Size")) { - assert mbai.isReadable(); - assert mbai.isWritable(); - assert !mbai.isIs(); - assert mbai.getType().equals("int"); - } else if (name.equals("Interesting")) { - assert mbai.isReadable(); - assert !mbai.isWritable(); - assert mbai.isIs(); - assert mbai.getType().equals("boolean"); - } else if (name.equals("Stats")) { - assert mbai.isReadable(); - assert !mbai.isWritable(); - assert !mbai.isIs(); - Descriptor d = mbai.getDescriptor(); - if (mx) { - assert mbai.getType().equals(CompositeData.class.getName()); - assert d.getFieldValue("originalType").equals(Stats.class.getName()); - CompositeType ct = (CompositeType) d.getFieldValue("openType"); - Set names = new HashSet( - Arrays.asList("used", "size", "interesting")); - assert ct.keySet().equals(names) : ct.keySet(); - } else { - assert mbai.getType().equals(Stats.class.getName()); - } - } else - assert false : name; - } - - MBeanOperationInfo[] mbois = mbi.getOperations(); - - assert mbois.length == 1: mbois.length; - - MBeanOperationInfo mboi = mbois[0]; - assert mboi.getName().equals("dropOldest"); - assert mboi.getReturnType().equals("int"); - MBeanParameterInfo[] mbpis = mboi.getSignature(); - assert mbpis.length == 1: mbpis.length; - assert mbpis[0].getType().equals("int"); - - assert mbs.getAttribute(objectName, "Used").equals(23); - - assert mbs.getAttribute(objectName, "Size").equals(99); - mbs.setAttribute(objectName, new Attribute("Size", 55)); - assert mbs.getAttribute(objectName, "Size").equals(55); - - assert mbs.getAttribute(objectName, "Interesting").equals(false); - - Object stats = mbs.getAttribute(objectName, "Stats"); - assert (mx ? CompositeData.class : Stats.class).isInstance(stats) : stats.getClass(); - - int ret = (Integer) mbs.invoke( - objectName, "dropOldest", new Object[] {66}, new String[] {"int"}); - assert ret == 55; - } -} diff --git a/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java b/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java deleted file mode 100644 index aa9b34b3c..000000000 --- a/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java +++ /dev/null @@ -1,442 +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. - * - * 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. - */ - -/* - * @test - * @bug 6323980 6772779 - * @summary Test @NotificationInfo annotation - * @author Eamonn McManus - * @run main/othervm -ea AnnotatedNotificationInfoTest - */ - -import java.io.Serializable; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Field; -import java.util.Arrays; -import javax.annotation.Resource; -import javax.management.AttributeChangeNotification; -import javax.management.Description; -import javax.management.Descriptor; -import javax.management.ImmutableDescriptor; -import javax.management.ListenerNotFoundException; -import javax.management.MBean; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.MXBean; -import javax.management.Notification; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationInfo; -import javax.management.NotificationInfos; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.SendNotification; - -public class AnnotatedNotificationInfoTest { - - static final Descriptor expectedDescriptor = new ImmutableDescriptor( - "foo=bar", "descriptionResourceBundleBaseName=bundle", - "descriptionResourceKey=key"); - static final MBeanNotificationInfo expected = new MBeanNotificationInfo( - new String[] {"foo", "bar"}, - AttributeChangeNotification.class.getName(), - "description", - expectedDescriptor); - - // Data for the first kind of test. This tests that MBeanNotificationInfo - // is correctly derived from @NotificationInfo. - // Every static field called mbean* is expected to be an MBean - // with a single MBeanNotificationInfo that has the same value - // in each case. - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static interface Intf1MBean {} - - public static class Intf1 - extends NotificationBroadcasterSupport implements Intf1MBean {} - - private static Object mbeanIntf1 = new Intf1(); - - @NotificationInfos( - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"})) - public static interface Intf2MBean {} - - public static class Intf2 - extends NotificationBroadcasterSupport implements Intf2MBean {} - - private static Object mbeanIntf2 = new Intf2(); - - @NotificationInfos({}) - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static interface Intf3MBean {} - - public static class Intf3 - extends NotificationBroadcasterSupport implements Intf3MBean {} - - private static Object mbeanIntf3 = new Intf3(); - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static interface ParentIntf {} - - public static interface Intf4MBean extends Serializable, ParentIntf, Cloneable {} - - public static class Intf4 - extends NotificationBroadcasterSupport implements Intf4MBean {} - - private static Object mbeanIntf4 = new Intf4(); - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static interface Intf5MXBean {} - - public static class Intf5Impl - extends NotificationBroadcasterSupport implements Intf5MXBean {} - - private static Object mbeanIntf5 = new Intf5Impl(); - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static interface Intf6MBean {} - - public static class Intf6 implements Intf6MBean { - @Resource - private volatile SendNotification send; - } - - private static Object mbeanIntf6 = new Intf6(); - - public static interface Impl1MBean {} - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static class Impl1 - extends NotificationBroadcasterSupport implements Impl1MBean {} - - private static Object mbeanImpl1 = new Impl1(); - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static class ParentImpl extends NotificationBroadcasterSupport {} - - public static interface Impl2MBean {} - - public static class Impl2 extends ParentImpl implements Impl2MBean {} - - private static Object mbeanImpl2 = new Impl2(); - - public static interface Impl3MXBean {} - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static class Impl3 - extends NotificationBroadcasterSupport implements Impl3MXBean {} - - private static Object mbeanImpl3 = new Impl3(); - - public static class Impl4 extends ParentImpl implements Impl3MXBean {} - - private static Object mbeanImpl4 = new Impl4(); - - @MBean - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static class MBean1 extends NotificationBroadcasterSupport {} - - private static Object mbeanMBean1 = new MBean1(); - - @MBean - public static class MBean2 extends ParentImpl {} - - private static Object mbeanMBean2 = new MBean2(); - - @MBean - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static class MBean3 { - @Resource - private volatile SendNotification send; - } - - private static Object mbeanMBean3 = new MBean3(); - - @MXBean - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static class MXBean1 extends NotificationBroadcasterSupport {} - - private static Object mbeanMXBean1 = new MXBean1(); - - @MXBean - public static class MXBean2 extends ParentImpl {} - - private static Object mbeanMXBean2 = new MXBean2(); - - // Test that @NotificationInfo and @NotificationInfos are ignored if - // the MBean returns a non-empty MBeanNotificationInfo[] from its - // NotificationBroadcaster.getNotifications() implementation. - - @NotificationInfo(types={"blim", "blam"}) - public static interface Explicit1MBean {} - - public static class Explicit1 - extends NotificationBroadcasterSupport implements Explicit1MBean { - public Explicit1() { - super(expected); - } - } - - private static Object mbeanExplicit1 = new Explicit1(); - - @NotificationInfos( - { - @NotificationInfo(types="blim"), @NotificationInfo(types="blam") - } - ) - public static interface Explicit2MXBean {} - - public static class Explicit2 - implements NotificationBroadcaster, Explicit2MXBean { - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) {} - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException {} - - public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[] {expected}; - } - } - - // Data for the second kind of test. This tests that @NotificationInfo is - // ignored if the MBean is not a notification source. Every static - // field called ignoredMBean* is expected to be an MBean on which - // isInstanceOf(NotificationBroadcaster.class.getName() is false, - // addNotificationListener produces an exception, and the - // MBeanNotificationInfo array is empty. - @NotificationInfo(types={"com.example.notifs.create", - "com.example.notifs.destroy"}) - public static interface CacheMBean { - public int getCachedNum(); - } - - public static class Cache implements CacheMBean { - public int getCachedNum() { - return 0; - } - } - - private static Object ignoredMBean1 = new Cache(); - - @NotificationInfos( - @NotificationInfo(types={"foo", "bar"}) - ) - public static interface Cache2MBean { - public int getCachedNum(); - } - - public static class Cache2 implements Cache2MBean { - public int getCachedNum() { - return 0; - } - } - - private static Object ignoredMBean2 = new Cache2(); - - private static final NotificationListener nullListener = - new NotificationListener() { - public void handleNotification( - Notification notification, Object handback) {} - }; - - // Test that inheriting inconsistent @NotificationInfo annotations is - // an error, but not if they are overridden by a non-empty getNotifications() - - @NotificationInfo(types={"blim"}) - public static interface Inconsistent1 {} - - @NotificationInfo(types={"blam"}) - public static interface Inconsistent2 {} - - public static interface InconsistentMBean extends Inconsistent1, Inconsistent2 {} - - public static class Inconsistent - extends NotificationBroadcasterSupport implements InconsistentMBean {} - - public static class Consistent - extends Inconsistent implements NotificationBroadcaster { - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) {} - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException {} - - public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[] {expected}; - } - } - - private static Object mbeanConsistent = new Consistent(); - - @NotificationInfo( - types = {"foo", "bar"}, - notificationClass = AttributeChangeNotification.class, - description = @Description( - value = "description", - bundleBaseName = "bundle", - key = "key"), - descriptorFields = {"foo=bar"}) - public static interface Consistent2MBean extends Inconsistent1, Inconsistent2 {} - - public static class Consistent2 - extends NotificationBroadcasterSupport implements Consistent2MBean {} - - private static Object mbeanConsistent2 = new Consistent2(); - - public static void main(String[] args) throws Exception { - if (!AnnotatedNotificationInfoTest.class.desiredAssertionStatus()) - throw new Exception("Test must be run with -ea"); - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName on = new ObjectName("a:b=c"); - - System.out.println("Testing MBeans..."); - for (Field mbeanField : - AnnotatedNotificationInfoTest.class.getDeclaredFields()) { - boolean notifier; - if (mbeanField.getName().startsWith("mbean")) - notifier = true; - else if (mbeanField.getName().startsWith("ignoredMBean")) - notifier = false; - else - continue; - System.out.println("..." + mbeanField.getName()); - Object mbean = mbeanField.get(null); - mbs.registerMBean(mbean, on); - MBeanInfo mbi = mbs.getMBeanInfo(on); - MBeanNotificationInfo[] mbnis = mbi.getNotifications(); - if (notifier) { - assert mbnis.length == 1 : mbnis.length; - assert mbnis[0].equals(expected) : mbnis[0]; - } else { - assert mbnis.length == 0 : mbnis.length; - assert !mbs.isInstanceOf(on, NotificationBroadcaster.class.getName()); - try { - mbs.addNotificationListener(on, nullListener, null, null); - assert false : "addNotificationListener works"; - } catch (Exception e) { - // OK: addNL correctly refused - } - } - mbs.unregisterMBean(on); - } - - // Test that inconsistent @NotificationInfo annotations produce an - // error. - try { - mbs.registerMBean(new Inconsistent(), on); - System.out.println(mbs.getMBeanInfo(on)); - assert false : "Inconsistent @NotificationInfo not detected"; - } catch (Exception e) { - System.out.println( - "Inconsistent @NotificationInfo correctly produced " + e); - } - } -} diff --git a/test/javax/management/Introspector/AnnotationTest.java b/test/javax/management/Introspector/AnnotationTest.java index 8bd9804a3..85b5d4525 100644 --- a/test/javax/management/Introspector/AnnotationTest.java +++ b/test/javax/management/Introspector/AnnotationTest.java @@ -32,15 +32,22 @@ * @run main AnnotationTest */ -import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; -import javax.management.*; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import javax.management.Descriptor; +import javax.management.DescriptorRead; +import javax.management.DescriptorKey; +import javax.management.ImmutableDescriptor; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; /* This test checks that annotations produce Descriptor entries as - specified in javax.management.DescriptorKey and javax.management.DescriptorField. - It does the following: + specified in javax.management.DescriptorKey. It does two things: - An annotation consisting of an int and a String, each with an appropriate @DescriptorKey annotation, is placed on every program @@ -62,10 +69,6 @@ import javax.management.*; The test checks that in each case the corresponding Descriptor appears in the appropriate place inside the MBean's MBeanInfo. - - A @DescriptorFields annotation defining two fields is placed in the - same places and again the test checks that the two fields appear - in the corresponding MBean*Info objects. - - An annotation consisting of enough other types to ensure coverage is placed on a getter. The test checks that the generated MBeanAttributeInfo contains the corresponding Descriptor. The tested @@ -111,12 +114,11 @@ public class AnnotationTest { boolean[] booleanArrayValue(); } - /* We use the annotations @Pair(x = 3, y = "foo") - and @DescriptorFields({"foo=bar", "baz="}) everywhere, and this is - the Descriptor that they should produce: */ + /* We use the annotation @Pair(x = 3, y = "foo") everywhere, and this is + the Descriptor that it should produce: */ private static Descriptor expectedDescriptor = - new ImmutableDescriptor(new String[] {"x", "y", "foo", "baz"}, - new Object[] {3, "foo", "bar", ""}); + new ImmutableDescriptor(new String[] {"x", "y"}, + new Object[] {3, "foo"}); private static Descriptor expectedFullDescriptor = new ImmutableDescriptor(new String[] { @@ -136,10 +138,8 @@ public class AnnotationTest { }); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) public static interface ThingMBean { @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) @Full(classValue=Full.class, enumValue=RetentionPolicy.RUNTIME, booleanValue=false, @@ -151,47 +151,32 @@ public class AnnotationTest { int getReadOnly(); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) void setWriteOnly(int x); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) int getReadWrite1(); void setReadWrite1(int x); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) int getReadWrite2(); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) void setReadWrite2(int x); int getReadWrite3(); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) void setReadWrite3(int x); @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - int operation(@Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - int p1, - @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - int p2); + int operation(@Pair(x = 3, y = "foo") int p1, + @Pair(x = 3, y = "foo") int p2); } public static class Thing implements ThingMBean { @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) public Thing() {} @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - public Thing( - @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - int p1) {} + public Thing(@Pair(x = 3, y = "foo") int p1) {} public int getReadOnly() {return 0;} @@ -210,20 +195,14 @@ public class AnnotationTest { } @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) public static interface ThingMXBean extends ThingMBean {} public static class ThingImpl implements ThingMXBean { @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) public ThingImpl() {} @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - public ThingImpl( - @Pair(x = 3, y = "foo") - @DescriptorFields({"foo=bar", "baz="}) - int p1) {} + public ThingImpl(@Pair(x = 3, y = "foo") int p1) {} public int getReadOnly() {return 0;} @@ -241,79 +220,6 @@ public class AnnotationTest { public int operation(int p1, int p2) {return 0;} } - @Retention(RetentionPolicy.RUNTIME) - public static @interface DefaultTest { - @DescriptorKey(value = "string1", omitIfDefault = true) - String string1() default ""; - @DescriptorKey(value = "string2", omitIfDefault = true) - String string2() default "tiddly pom"; - @DescriptorKey(value = "int", omitIfDefault = true) - int intx() default 23; - @DescriptorKey(value = "intarray1", omitIfDefault = true) - int[] intArray1() default {}; - @DescriptorKey(value = "intarray2", omitIfDefault = true) - int[] intArray2() default {1, 2}; - @DescriptorKey(value = "stringarray1", omitIfDefault = true) - String[] stringArray1() default {}; - @DescriptorKey(value = "stringarray2", omitIfDefault = true) - String[] stringArray2() default {"foo", "bar"}; - } - - @Retention(RetentionPolicy.RUNTIME) - public static @interface Expect { - String[] value() default {}; - } - - public static interface DefaultMBean { - @DefaultTest - @Expect() - public void a(); - - @DefaultTest(string1="") - @Expect() - public void b(); - - @DefaultTest(string1="nondefault") - @Expect("string1=nondefault") - public void c(); - - @DefaultTest(string2="tiddly pom") - @Expect() - public void d(); - - @DefaultTest(intx=23) - @Expect() - public void e(); - - @DefaultTest(intx=34) - @Expect("int=34") - public void f(); - - @DefaultTest(intArray1={}) - @Expect() - public void g(); - - @DefaultTest(intArray1={2,3}) - @Expect("intarray1=[2, 3]") - public void h(); - - @DefaultTest(intArray2={}) - @Expect("intarray2=[]") - public void i(); - - @DefaultTest(stringArray1={}) - @Expect() - public void j(); - - @DefaultTest(stringArray1={"foo"}) - @Expect("stringarray1=[foo]") - public void k(); - - @DefaultTest(stringArray2={}) - @Expect("stringarray2=[]") - public void l(); - } - public static void main(String[] args) throws Exception { System.out.println("Testing that annotations are correctly " + "reflected in Descriptor entries"); @@ -336,43 +242,6 @@ public class AnnotationTest { } check(mbs, on); - System.out.println(); - System.out.println("Testing that omitIfDefault works"); - DefaultMBean defaultImpl = (DefaultMBean) Proxy.newProxyInstance( - DefaultMBean.class.getClassLoader(), - new Class[] {DefaultMBean.class}, - new InvocationHandler(){ - public Object invoke(Object proxy, Method method, Object[] args) { - return null; - } - }); - DynamicMBean mbean = new StandardMBean(defaultImpl, DefaultMBean.class); - MBeanOperationInfo[] ops = mbean.getMBeanInfo().getOperations(); - for (MBeanOperationInfo op : ops) { - String name = op.getName(); - Expect expect = - DefaultMBean.class.getMethod(name).getAnnotation(Expect.class); - Descriptor opd = op.getDescriptor(); - List fields = new ArrayList(); - for (String fieldName : opd.getFieldNames()) { - Object value = opd.getFieldValue(fieldName); - String s = Arrays.deepToString(new Object[] {value}); - s = s.substring(1, s.length() - 1); - fields.add(fieldName + "=" + s); - } - Descriptor opds = new ImmutableDescriptor(fields.toArray(new String[0])); - Descriptor expd = new ImmutableDescriptor(expect.value()); - if (opds.equals(expd)) - System.out.println("OK: op " + name + ": " + opds); - else { - String failure = "Bad descriptor for op " + name + ": " + - "expected " + expd + ", got " + opds; - System.out.println("NOT OK: " + failure); - failed = failure; - } - } - System.out.println(); - if (failed == null) System.out.println("Test passed"); else diff --git a/test/javax/management/Introspector/ExceptionsDescriptorTest.java b/test/javax/management/Introspector/ExceptionsDescriptorTest.java deleted file mode 100644 index 5b931ba72..000000000 --- a/test/javax/management/Introspector/ExceptionsDescriptorTest.java +++ /dev/null @@ -1,245 +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. - * - * 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. - */ - -/* - * @test %M% %I% - * @bug 6250014 - * @summary Test that Exceptions are added to the MbeanInfo - * @author Jean-Francois Denise - * @run main/othervm ExceptionsDescriptorTest - */ -import java.lang.management.ManagementFactory; -import java.util.HashSet; -import java.util.Set; -import javax.management.Descriptor; -import javax.management.JMX; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.ObjectName; - -public class ExceptionsDescriptorTest { - - private static final ObjectName OBJECT_NAME = ObjectName.valueOf(":type=Foo"); - final static String EXCEPTION_NAME = Exception.class.getName(); - final static String ILLEGAL_ARGUMENT_EXCEPTION_NAME = - IllegalArgumentException.class.getName(); - final static Set ONE_EXCEPTION = new HashSet(); - final static Set TWO_EXCEPTION = new HashSet(); - static { - ONE_EXCEPTION.add(EXCEPTION_NAME); - TWO_EXCEPTION.add(EXCEPTION_NAME); - TWO_EXCEPTION.add(ILLEGAL_ARGUMENT_EXCEPTION_NAME); - } - public interface TestMBean { - - public void doIt(); - - public void doIt(String str) throws Exception; - - public void doIt(String str, boolean b) throws Exception, - IllegalArgumentException; - - public String getThat(); - - public void setThat(String that); - - public String getThe() throws Exception; - - public void setThe(String the); - - public String getThese(); - - public void setThese(String the) throws Exception; - - public String getIt() throws Exception; - - public void setIt(String str) throws Exception; - - public String getThis() throws Exception, IllegalArgumentException; - - public void setThose(String str) throws Exception, - IllegalArgumentException; - } - - public static class Test implements TestMBean { - - public Test() { - } - - public Test(int i) throws Exception { - } - - public Test(int i, int j) throws Exception, IllegalArgumentException { - } - - public void doIt() { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void doIt(String str) throws Exception { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void doIt(String str, boolean b) throws Exception, IllegalArgumentException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public String getThat() { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setThat(String that) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public String getThe() throws Exception { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setThe(String the) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public String getThese() { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setThese(String the) throws Exception { - throw new UnsupportedOperationException("Not supported yet."); - } - - public String getIt() throws Exception { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setIt(String str) throws Exception { - throw new UnsupportedOperationException("Not supported yet."); - } - - public String getThis() throws Exception, IllegalArgumentException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setThose(String str) throws Exception, IllegalArgumentException { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - private static void check(Descriptor d, - Set exceptionsExpectedValue, - boolean exceptionsExpected, - Set setExceptionsExpectedValue, - boolean setExceptionsExpected) throws Exception { - String[] exceptionsValues = (String[]) d.getFieldValue(JMX.EXCEPTIONS_FIELD); - String[] setExceptionsValues = (String[]) d.getFieldValue(JMX.SET_EXCEPTIONS_FIELD); - - if (exceptionsExpected && exceptionsValues == null) { - throw new Exception("exceptions is expected but null value"); - } - if (!exceptionsExpected && exceptionsValues != null) { - throw new Exception("exceptions is not expected but non null value"); - } - if (setExceptionsExpected && setExceptionsValues == null) { - throw new Exception("setExceptions is expected but null value"); - } - if (!setExceptionsExpected && setExceptionsValues != null) { - throw new Exception("setExceptions is not expected but non null value"); - } - - if (exceptionsExpected) { - checkValues(exceptionsExpectedValue, exceptionsValues); - } - if (setExceptionsExpected) { - checkValues(setExceptionsExpectedValue, setExceptionsValues); - } - } - - private static void checkValues(Set expectedValuesSet, - String[] realValues) throws Exception { - - Set realValuesSet = new HashSet(); - for (String ex : realValues) { - realValuesSet.add(ex); - } - if (!realValuesSet.equals(expectedValuesSet)) { - throw new Exception("Invalid content for exceptions. Was expecting " + - expectedValuesSet + ". Found " + realValuesSet); - } - } - - public static void main(String[] args) throws Exception { - Test t = new Test(); - ManagementFactory.getPlatformMBeanServer().registerMBean(t, OBJECT_NAME); - MBeanInfo info = ManagementFactory.getPlatformMBeanServer(). - getMBeanInfo(OBJECT_NAME); - //Constructors - for (MBeanConstructorInfo ctr : info.getConstructors()) { - if (ctr.getSignature().length == 0) { - check(ctr.getDescriptor(), null, false, null, false); - } - if (ctr.getSignature().length == 1) { - check(ctr.getDescriptor(), ONE_EXCEPTION, true, null, false); - } - if (ctr.getSignature().length == 2) { - check(ctr.getDescriptor(),TWO_EXCEPTION,true, null, false); - } - } - //Attributes - for (MBeanAttributeInfo attr : info.getAttributes()) { - if (attr.getName().equals("That")) { - check(attr.getDescriptor(), null, false, null, false); - } - if (attr.getName().equals("The")) { - check(attr.getDescriptor(), ONE_EXCEPTION,true,null, false); - } - if (attr.getName().equals("These")) { - check(attr.getDescriptor(), null, false, ONE_EXCEPTION,true); - } - if (attr.getName().equals("It")) { - check(attr.getDescriptor(), ONE_EXCEPTION,true,ONE_EXCEPTION, - true); - } - if (attr.getName().equals("This")) { - check(attr.getDescriptor(), TWO_EXCEPTION,true,null,false); - } - if (attr.getName().equals("Those")) { - check(attr.getDescriptor(), null,false,TWO_EXCEPTION,true); - } - } - //Operations - for (MBeanOperationInfo oper : info.getOperations()) { - if (oper.getSignature().length == 0) { - check(oper.getDescriptor(), null, false, null, false); - } - if (oper.getSignature().length == 1) { - check(oper.getDescriptor(), ONE_EXCEPTION, true, null, false); - } - if (oper.getSignature().length == 2) { - check(oper.getDescriptor(), TWO_EXCEPTION,true, null, false); - } - } - System.out.println("Test passed"); - } -} diff --git a/test/javax/management/Introspector/MBeanDescriptionTest.java b/test/javax/management/Introspector/MBeanDescriptionTest.java deleted file mode 100644 index 5a52b0b69..000000000 --- a/test/javax/management/Introspector/MBeanDescriptionTest.java +++ /dev/null @@ -1,830 +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. - * - * 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. - */ - -/* - * @test %M% %I% - * @bug 6323980 - * @summary Test @Description - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import javax.management.Description; -import javax.management.IntrospectionException; -import javax.management.MBean; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; -import javax.management.MBeanFeatureInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.MBeanServer; -import javax.management.MXBean; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.StandardMBean; - -public class MBeanDescriptionTest { - private static String failure; - private static final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - private static final ObjectName name; - static { - try { - name = new ObjectName("a:b=c"); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public static interface Interface { - @Description("A description") - public String getA(); - - @Description("B description") - public int getB(); - public void setB(int x); - - public boolean isC(); - @Description("C description") - public void setC(boolean x); - - @Description("D description") - public void setD(float x); - - @Description("H description") - public int getH(); - @Description("H description") - public void setH(int x); - - public String getE(); - - public int getF(); - public void setF(int x); - - public void setG(boolean x); - - @Description("opA description") - public int opA( - @Description("p1 description") - int p1, - @Description("p2 description") - int p2); - - public void opB(float x); - } - - @Description("MBean description") - public static interface TestMBean extends Interface {} - - public static class Test implements TestMBean { - @Description("0-arg constructor description") - public Test() {} - - public Test(String why) {} - - @Description("2-arg constructor description") - public Test( - @Description("p1 description") - int x, - @Description("p2 description") - String y) { - } - - public String getA() { - return null; - } - - public int getB() { - return 0; - } - - public void setB(int x) { - } - - public boolean isC() { - return false; - } - - public void setC(boolean x) { - } - - public void setD(float x) { - } - - public String getE() { - return null; - } - - public int getF() { - return 0; - } - - public void setF(int x) { - } - - public void setG(boolean x) { - } - - public int getH() { - return 0; - } - - public void setH(int x) { - } - - public int opA(int p1, int p2) { - return 0; - } - - public void opB(float x) { - } - } - - public static class TestSub extends Test { - @Description("0-arg constructor description") - public TestSub() {} - - public TestSub(String why) {} - - @Description("2-arg constructor description") - public TestSub( - @Description("p1 description") - int x, - @Description("p2 description") - String y) { - } - } - - public static class StandardSub extends StandardMBean implements TestMBean { - @Description("0-arg constructor description") - public StandardSub() { - super(TestMBean.class, false); - } - - public StandardSub(String why) { - super(TestMBean.class, false); - } - - @Description("2-arg constructor description") - public StandardSub( - @Description("p1 description") - int x, - @Description("p2 description") - String y) { - super(TestMBean.class, false); - } - - public String getA() { - return null; - } - - public int getB() { - return 0; - } - - public void setB(int x) { - } - - public boolean isC() { - return false; - } - - public void setC(boolean x) { - } - - public void setD(float x) { - } - - public String getE() { - return null; - } - - public int getF() { - return 0; - } - - public void setF(int x) { - } - - public void setG(boolean x) { - } - - public int opA(int p1, int p2) { - return 0; - } - - public void opB(float x) { - } - - public int getH() { - return 0; - } - - public void setH(int x) { - } - } - - @Description("MBean description") - public static interface TestMXBean extends Interface {} - - public static class TestMXBeanImpl implements TestMXBean { - @Description("0-arg constructor description") - public TestMXBeanImpl() {} - - public TestMXBeanImpl(String why) {} - - @Description("2-arg constructor description") - public TestMXBeanImpl( - @Description("p1 description") - int x, - @Description("p2 description") - String y) { - } - - public String getA() { - return null; - } - - public int getB() { - return 0; - } - - public void setB(int x) { - } - - public boolean isC() { - return false; - } - - public void setC(boolean x) { - } - - public void setD(float x) { - } - - public String getE() { - return null; - } - - public int getF() { - return 0; - } - - public void setF(int x) { - } - - public void setG(boolean x) { - } - - public int opA(int p1, int p2) { - return 0; - } - - public void opB(float x) { - } - - public int getH() { - return 0; - } - - public void setH(int x) { - } - } - - public static class StandardMXSub extends StandardMBean implements TestMXBean { - @Description("0-arg constructor description") - public StandardMXSub() { - super(TestMXBean.class, true); - } - - public StandardMXSub(String why) { - super(TestMXBean.class, true); - } - - @Description("2-arg constructor description") - public StandardMXSub( - @Description("p1 description") - int x, - @Description("p2 description") - String y) { - super(TestMXBean.class, true); - } - - public String getA() { - return null; - } - - public int getB() { - return 0; - } - - public void setB(int x) { - } - - public boolean isC() { - return false; - } - - public void setC(boolean x) { - } - - public void setD(float x) { - } - - public String getE() { - return null; - } - - public int getF() { - return 0; - } - - public void setF(int x) { - } - - public void setG(boolean x) { - } - - public int opA(int p1, int p2) { - return 0; - } - - public void opB(float x) { - } - - public int getH() { - return 0; - } - - public void setH(int x) { - } - } - - @MBean - @Description("MBean description") - public static class AnnotatedMBean { - @Description("0-arg constructor description") - public AnnotatedMBean() {} - - public AnnotatedMBean(String why) {} - - @Description("2-arg constructor description") - public AnnotatedMBean( - @Description("p1 description") - int x, - @Description("p2 description") - String y) {} - - @ManagedAttribute - @Description("A description") - public String getA() { - return null; - } - - @ManagedAttribute - @Description("B description") - public int getB() { - return 0; - } - - @ManagedAttribute - public void setB(int x) { - } - - @ManagedAttribute - public boolean isC() { - return false; - } - - @ManagedAttribute - @Description("C description") - public void setC(boolean x) { - } - - @ManagedAttribute - @Description("D description") - public void setD(float x) { - } - - @ManagedAttribute - public String getE() { - return null; - } - - @ManagedAttribute - public int getF() { - return 0; - } - - @ManagedAttribute - public void setF(int x) { - } - - @ManagedAttribute - public void setG(boolean x) { - } - - @ManagedAttribute - @Description("H description") - public int getH() { - return 0; - } - - @ManagedAttribute - @Description("H description") - public void setH(int x) { - } - - @ManagedOperation - @Description("opA description") - public int opA( - @Description("p1 description") int p1, - @Description("p2 description") int p2) { - return 0; - } - - @ManagedOperation - public void opB(float x) { - } - } - - @MXBean - @Description("MBean description") - public static class AnnotatedMXBean { - @Description("0-arg constructor description") - public AnnotatedMXBean() {} - - public AnnotatedMXBean(String why) {} - - @Description("2-arg constructor description") - public AnnotatedMXBean( - @Description("p1 description") - int x, - @Description("p2 description") - String y) {} - - @ManagedAttribute - @Description("A description") - public String getA() { - return null; - } - - @ManagedAttribute - @Description("B description") - public int getB() { - return 0; - } - - @ManagedAttribute - public void setB(int x) { - } - - @ManagedAttribute - public boolean isC() { - return false; - } - - @ManagedAttribute - @Description("C description") - public void setC(boolean x) { - } - - @ManagedAttribute - @Description("D description") - public void setD(float x) { - } - - @ManagedAttribute - public String getE() { - return null; - } - - @ManagedAttribute - public int getF() { - return 0; - } - - @ManagedAttribute - public void setF(int x) { - } - - @ManagedAttribute - public void setG(boolean x) { - } - - @ManagedAttribute - @Description("H description") - public int getH() { - return 0; - } - - @ManagedAttribute - @Description("H description") - public void setH(int x) { - } - - @ManagedOperation - @Description("opA description") - public int opA( - @Description("p1 description") int p1, - @Description("p2 description") int p2) { - return 0; - } - - @ManagedOperation - public void opB(float x) { - } - } - - // Negative tests follow. - - // Inconsistent descriptions - public static interface BadInterface { - @Description("foo") - public String getFoo(); - @Description("bar") - public void setFoo(String x); - } - - public static interface BadMBean extends BadInterface {} - - public static class Bad implements BadMBean { - public String getFoo() { - return null; - } - - public void setFoo(String x) { - } - } - - public static interface BadMXBean extends BadInterface {} - - public static class BadMXBeanImpl implements BadMXBean { - public String getFoo() { - return null; - } - - public void setFoo(String x) { - } - } - - private static interface Defaults { - public String defaultAttributeDescription(String name); - public String defaultOperationDescription(String name); - public String defaultParameterDescription(int index); - } - - private static class StandardDefaults implements Defaults { - public String defaultAttributeDescription(String name) { - return "Attribute exposed for management"; - } - - public String defaultOperationDescription(String name) { - return "Operation exposed for management"; - } - - public String defaultParameterDescription(int index) { - return ""; - } - } - private static final Defaults standardDefaults = new StandardDefaults(); - - private static class MXBeanDefaults implements Defaults { - public String defaultAttributeDescription(String name) { - return name; - } - - public String defaultOperationDescription(String name) { - return name; - } - - public String defaultParameterDescription(int index) { - return "p" + index; - } - } - private static final Defaults mxbeanDefaults = new MXBeanDefaults(); - - private static class TestCase { - final String name; - final Object mbean; - final Defaults defaults; - TestCase(String name, Object mbean, Defaults defaults) { - this.name = name; - this.mbean = mbean; - this.defaults = defaults; - } - } - - private static class ExceptionTest { - final String name; - final Object mbean; - ExceptionTest(String name, Object mbean) { - this.name = name; - this.mbean = mbean; - } - } - - private static final TestCase[] tests = { - new TestCase("Standard MBean", new Test(), standardDefaults), - new TestCase("Standard MBean subclass", new TestSub(), standardDefaults), - new TestCase("StandardMBean delegating", - new StandardMBean(new Test(), TestMBean.class, false), - standardDefaults), - new TestCase("StandardMBean delegating to subclass", - new StandardMBean(new TestSub(), TestMBean.class, false), - standardDefaults), - new TestCase("StandardMBean subclass", new StandardSub(), standardDefaults), - - new TestCase("MXBean", new TestMXBeanImpl(), mxbeanDefaults), - new TestCase("StandardMBean MXBean delegating", - new StandardMBean(new TestMXBeanImpl(), TestMXBean.class, true), - mxbeanDefaults), - new TestCase("StandardMBean MXBean subclass", - new StandardMXSub(), mxbeanDefaults), - - new TestCase("@MBean", new AnnotatedMBean(), standardDefaults), - new TestCase("@MXBean", new AnnotatedMXBean(), mxbeanDefaults), - new TestCase("StandardMBean @MBean delegating", - new StandardMBean(new AnnotatedMBean(), null, false), - standardDefaults), - new TestCase("StandardMBean @MXBean delegating", - new StandardMBean(new AnnotatedMXBean(), null, true), - mxbeanDefaults), - }; - - private static final ExceptionTest[] exceptionTests = { - new ExceptionTest("Standard MBean with inconsistent get/set", new Bad()), - new ExceptionTest("MXBean with inconsistent get/set", new BadMXBeanImpl()), - }; - - public static void main(String[] args) throws Exception { - System.out.println("=== Testing correct MBeans ==="); - for (TestCase test : tests) { - System.out.println("Testing " + test.name + "..."); - mbs.registerMBean(test.mbean, name); - boolean expectConstructors = - (test.mbean.getClass() != StandardMBean.class); - check(mbs.getMBeanInfo(name), test.defaults, expectConstructors); - mbs.unregisterMBean(name); - } - System.out.println(); - - System.out.println("=== Testing incorrect MBeans ==="); - for (ExceptionTest test : exceptionTests) { - System.out.println("Testing " + test.name); - try { - mbs.registerMBean(test.mbean, name); - fail("Registration succeeded but should not have"); - mbs.unregisterMBean(name); - } catch (NotCompliantMBeanException e) { - // OK - } catch (Exception e) { - fail("Registration failed with wrong exception: " + - "expected NotCompliantMBeanException, got " + - e.getClass().getName()); - } - } - System.out.println(); - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static void check( - MBeanInfo mbi, Defaults defaults, boolean expectConstructors) - throws Exception { - assertEquals("MBean description", mbi.getDescription()); - - // These attributes have descriptions - for (String attr : new String[] {"A", "B", "C", "D", "H"}) { - MBeanAttributeInfo mbai = getAttributeInfo(mbi, attr); - assertEquals(attr + " description", mbai.getDescription()); - } - - // These attributes don't have descriptions - for (String attr : new String[] {"E", "F", "G"}) { - // If we ever change the default description, we'll need to change - // this test accordingly. - MBeanAttributeInfo mbai = getAttributeInfo(mbi, attr); - assertEquals( - defaults.defaultAttributeDescription(attr), mbai.getDescription()); - } - - // This operation has a description, as do its parameters - MBeanOperationInfo opA = getOperationInfo(mbi, "opA"); - assertEquals("opA description", opA.getDescription()); - checkSignature(opA.getSignature()); - - // This operation has the default description, as does its parameter - MBeanOperationInfo opB = getOperationInfo(mbi, "opB"); - assertEquals(defaults.defaultOperationDescription("opB"), opB.getDescription()); - MBeanParameterInfo opB0 = opB.getSignature()[0]; - assertEquals(defaults.defaultParameterDescription(0), opB0.getDescription()); - - if (expectConstructors) { - // The 0-arg and 2-arg constructors have descriptions - MBeanConstructorInfo con0 = getConstructorInfo(mbi, 0); - assertEquals("0-arg constructor description", con0.getDescription()); - MBeanConstructorInfo con2 = getConstructorInfo(mbi, 2); - assertEquals("2-arg constructor description", con2.getDescription()); - checkSignature(con2.getSignature()); - - // The 1-arg constructor does not have a description. - // The default description for constructors and their - // parameters is the same for all types of MBean. - MBeanConstructorInfo con1 = getConstructorInfo(mbi, 1); - assertEquals("Public constructor of the MBean", con1.getDescription()); - assertEquals("", con1.getSignature()[0].getDescription()); - } - } - - private static void checkSignature(MBeanParameterInfo[] params) { - for (int i = 0; i < params.length; i++) { - MBeanParameterInfo mbpi = params[i]; - assertEquals("p" + (i+1) + " description", mbpi.getDescription()); - } - } - - private static MBeanAttributeInfo getAttributeInfo(MBeanInfo mbi, String attr) - throws Exception { - return getFeatureInfo(mbi.getAttributes(), attr); - } - - private static MBeanOperationInfo getOperationInfo(MBeanInfo mbi, String op) - throws Exception { - return getFeatureInfo(mbi.getOperations(), op); - } - - private static MBeanConstructorInfo getConstructorInfo(MBeanInfo mbi, int nparams) - throws Exception { - for (MBeanConstructorInfo mbci : mbi.getConstructors()) { - if (mbci.getSignature().length == nparams) - return mbci; - } - throw new Exception("Constructor not found: " + nparams); - } - - private static T getFeatureInfo( - T[] features, String name) throws Exception { - for (T feature : features) { - if (feature.getName().equals(name)) - return feature; - } - throw new Exception("Feature not found: " + name); - } - - private static void assertEquals(Object expected, Object actual) { - if (!expected.equals(actual)) - fail("Expected " + string(expected) + ", got " + string(actual)); - } - - private static String string(Object x) { - if (x instanceof String) - return quote((String) x); - else - return String.valueOf(x); - } - - private static String quote(String s) { - return '"' + s.replace("\\", "\\\\").replace("\"", "\\\"") + '"'; - } - - private static void fail(String why) { - StackTraceElement[] stack = new Throwable().getStackTrace(); - int n = 0; - for (StackTraceElement elmt : stack) { - String method = elmt.getMethodName(); - if (method.equals("fail") || method.equals("assertEquals") || - method.equals("checkSignature")) - continue; - n = elmt.getLineNumber(); - break; - } - System.out.println("FAILED: " + why + " (line " + n + ")"); - failure = why; - } -} diff --git a/test/javax/management/Introspector/ObjectNameTemplateTest.java b/test/javax/management/Introspector/ObjectNameTemplateTest.java deleted file mode 100644 index 2abcaf085..000000000 --- a/test/javax/management/Introspector/ObjectNameTemplateTest.java +++ /dev/null @@ -1,343 +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. - * - * 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. - */ - -/* - * @test %M% %I% - * @bug 6675526 - * @summary Test MBeans named with @ObjectNameTemplate - * @author Jean-Francois Denise - * @run main/othervm ObjectNameTemplateTest - */ -import java.lang.management.ManagementFactory; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.List; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.ImmutableDescriptor; -import javax.management.InvalidAttributeValueException; -import javax.management.JMX; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanServer; -import javax.management.MXBean; -import javax.management.MBean; -import javax.management.ManagedAttribute; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.ObjectNameTemplate; -import javax.management.ReflectionException; -import javax.management.StandardMBean; - -public class ObjectNameTemplateTest { - - private static MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - private static final String NAME_TEMPLATE_MULTI = - "com.example:type=MultiStdCache,name={Name}"; - private static final String NAME_TEMPLATE_MONO = - "com.example:{Type}={TypeValue}"; - private static final String NAME_TEMPLATE_QUOTED = - "com.example:type=Quotted,name=\"{Name}\""; - private static final String NAME_TEMPLATE_WRAPPED = - "com.example:type=MgtInterface,id={Id}"; - private static final String NAME_TEMPLATE_FULL = - "{Naming}"; - private static final String FULL_NAME = "com.example:type=NotAdvised"; - private static final String NAME1 = "toto1"; - private static final String NAME2 = "toto2"; - private static final String TYPE_KEY = "thisIsTheType"; - private static final String TYPE_VALUE = "aTypeValue"; - private static final String INVALID_NAME = "?,=*,\n, "; - private static final int ID = 999; - private static Object[] EMPTY_PARAMS = {}; - private static String[] EMPTY_SIGNATURE = {}; - private static final ObjectName OBJECTNAME_CACHE = - ObjectName.valueOf("com.example:type=Cache"); - private static final ObjectName OBJECTNAME_SUBCACHE = - ObjectName.valueOf("com.example:type=SubCache"); - private static final ObjectName OBJECTNAME_CACHEMX = - ObjectName.valueOf("com.example:type=CacheMX"); - private static final ObjectName OBJECTNAME_SUBCACHEMX = - ObjectName.valueOf("com.example:type=SubCacheMX"); - private static final ObjectName OBJECTNAME_DYNACACHE = - ObjectName.valueOf("com.example:type=DynaCache"); - private static final ObjectName OBJECTNAME_STDCACHE = - ObjectName.valueOf("com.example:type=StdCache"); - private static final ObjectName OBJECTNAME_STDCACHEMX = - ObjectName.valueOf("com.example:type=StdCacheMX"); - private static final ObjectName OBJECTNAME_MULTI_1 = - ObjectName.valueOf("com.example:" + - "type=MultiStdCache,name=" + NAME1); - private static final ObjectName OBJECTNAME_MULTI_2 = - ObjectName.valueOf("com.example:" + - "type=MultiStdCache,name=" + NAME2); - private static final ObjectName OBJECTNAME_MONO = - ObjectName.valueOf("com.example:" + TYPE_KEY + "=" + - TYPE_VALUE); - private static final ObjectName OBJECTNAME_QUOTED = - ObjectName.valueOf("com.example:type=Quotted," + - "name="+ObjectName.quote(INVALID_NAME)); - private static final ObjectName OBJECTNAME_WRAPPED_RESOURCE = - ObjectName.valueOf("com.example:type=MgtInterface,id=" + ID); - private static final ObjectName OBJECTNAME_FULL = - ObjectName.valueOf(FULL_NAME); - - private static void test(Class mbean, Object[] params, - String[] signature, ObjectName name, String template) - throws Exception { - mbs.createMBean(mbean.getName(), null, params, signature); - test(name, template); - List> parameters = new ArrayList>(); - for (String sig : signature) { - parameters.add(Class.forName(sig)); - } - Class classes[] = new Class[parameters.size()]; - Constructor ctr = mbean.getConstructor(parameters.toArray(classes)); - Object inst = ctr.newInstance(params); - test(inst, name, template); - } - - private static void test(Object obj, ObjectName name, String template) - throws Exception { - mbs.registerMBean(obj, null); - test(name, template); - } - - private static void test(ObjectName name, String template) - throws Exception { - if (!mbs.isRegistered(name)) { - throw new Exception("Wrong " + name + " name"); - } - if (template != null && !mbs.getMBeanInfo(name).getDescriptor(). - getFieldValue("objectNameTemplate").equals(template)) { - throw new Exception("Invalid Derscriptor"); - } - mbs.unregisterMBean(name); - } - - public static void main(String[] args) throws Exception { - test(Cache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_CACHE, - OBJECTNAME_CACHE.toString()); - - test(CacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_CACHEMX, - OBJECTNAME_CACHEMX.toString()); - - test(SubCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_SUBCACHE, - OBJECTNAME_SUBCACHE.toString()); - - test(SubCacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_SUBCACHEMX, - OBJECTNAME_SUBCACHEMX.toString()); - - test(DynaCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_DYNACACHE, - null); - - test(StdCacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_STDCACHEMX, - OBJECTNAME_STDCACHEMX.toString()); - - test(StdCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_STDCACHE, - OBJECTNAME_STDCACHE.toString()); - String[] sig = {String.class.getName()}; - Object[] params = {NAME1}; - test(MultiStdCache.class, params, sig, OBJECTNAME_MULTI_1, - NAME_TEMPLATE_MULTI); - Object[] params2 = {NAME2}; - test(MultiStdCache.class, params2, sig, OBJECTNAME_MULTI_2, - NAME_TEMPLATE_MULTI); - - test(MonoStdCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_MONO, - NAME_TEMPLATE_MONO); - - test(Quoted.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_QUOTED, - NAME_TEMPLATE_QUOTED); - - test(new StandardMBean(new WrappedResource(), MgtInterface.class), - OBJECTNAME_WRAPPED_RESOURCE, NAME_TEMPLATE_WRAPPED); - - test(FullName.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_FULL, - NAME_TEMPLATE_FULL); - try { - test(Wrong.class, EMPTY_PARAMS, EMPTY_SIGNATURE, null, null); - throw new Exception("No treceived expected Exception"); - } catch (NotCompliantMBeanException ncex) { - if (!(ncex.getCause() instanceof AttributeNotFoundException)) { - throw new Exception("Invalid initCause"); - } - } - } - - @MBean - @ObjectNameTemplate("{Naming}") - public static class FullName { - - @ManagedAttribute - public String getNaming() { - return FULL_NAME; - } - } - - @ObjectNameTemplate("com.example:type=MgtInterface,id={Id}") - public interface MgtInterface { - - public int getId(); - } - - public static class WrappedResource implements MgtInterface { - - public int getId() { - return ID; - } - } - - @MBean - @ObjectNameTemplate("com.example:type=Cache") - public static class Cache { - } - - @ObjectNameTemplate("com.example:type=SubCache") - public static class SubCache extends Cache { - } - - @MXBean - @ObjectNameTemplate("com.example:type=CacheMX") - public static class CacheMX { - } - - @ObjectNameTemplate("com.example:type=SubCacheMX") - public static class SubCacheMX extends CacheMX { - } - - @ObjectNameTemplate("com.example:type=StdCache") - public interface StdCacheMBean { - } - - public static class StdCache implements StdCacheMBean { - } - - @ObjectNameTemplate("com.example:type=StdCacheMX") - public interface StdCacheMXBean { - } - - public static class StdCacheMX implements StdCacheMXBean { - } - - public static class DynaCache implements DynamicMBean { - - public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public AttributeList getAttributes(String[] attributes) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public AttributeList setAttributes(AttributeList attributes) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public MBeanInfo getMBeanInfo() { - ImmutableDescriptor d = new ImmutableDescriptor(JMX.OBJECT_NAME_TEMPLATE + "=com.example:type=DynaCache"); - - return new MBeanInfo("DynaCache", "Description", null, null, null, null, d); - } - } - - @ObjectNameTemplate("com.example:type=MultiStdCache,name={Name}") - public interface MultiStdCacheMXBean { - - public String getName(); - } - - public static class MultiStdCache implements MultiStdCacheMXBean { - - private String name; - - public MultiStdCache(String name) { - this.name = name; - } - - public String getName() { - return name; - } - } - - @ObjectNameTemplate("com.example:{Type}={TypeValue}") - public interface MonoStdCacheMXBean { - - public String getTypeValue(); - - public String getType(); - } - - public static class MonoStdCache implements MonoStdCacheMXBean { - - public String getTypeValue() { - return TYPE_VALUE; - } - - public String getType() { - return TYPE_KEY; - } - } - - @ObjectNameTemplate("com.example:type=Quotted,name=\"{Name}\"") - public interface QuottedMXBean { - - public String getName(); - } - - public static class Quoted implements QuottedMXBean { - - public String getName() { - return INVALID_NAME; - } - } - - @ObjectNameTemplate("com.example:{Type}={TypeValue}, name={Name}") - public interface WrongMXBean { - - public String getTypeValue(); - - public String getType(); - } - - public static class Wrong implements WrongMXBean { - - public String getTypeValue() { - return TYPE_VALUE; - } - - public String getType() { - return TYPE_KEY; - } - } -} diff --git a/test/javax/management/Introspector/ParameterNameTest.java b/test/javax/management/Introspector/ParameterNameTest.java deleted file mode 100644 index bf5649b8e..000000000 --- a/test/javax/management/Introspector/ParameterNameTest.java +++ /dev/null @@ -1,116 +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. - * - * 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. - */ - -/* - * @test %M% %I% - * @bug 6323980 - * @summary Test that parameter names can be specified with @Name. - * @author Eamonn McManus - */ - -import javax.management.MBean; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.MXBean; -import javax.management.ObjectName; - -import annot.Name; -import javax.management.ManagedOperation; - -public class ParameterNameTest { - public static interface NoddyMBean { - public int add(int x, @Name("y") int y); - } - - public static class Noddy implements NoddyMBean { - public int add(int x, int y) { - return x + y; - } - } - - public static interface NoddyMXBean { - public int add(int x, @Name("y") int y); - } - - public static class NoddyImpl implements NoddyMXBean { - public int add(int x, int y) { - return x + y; - } - } - - @MBean - public static class NoddyAnnot { - @ManagedOperation - public int add(int x, @Name("y") int y) { - return x + y; - } - } - - @MXBean - public static class NoddyAnnotMX { - @ManagedOperation - public int add(int x, @Name("y") int y) { - return x + y; - } - } - - private static final Object[] mbeans = { - new Noddy(), new NoddyImpl(), new NoddyAnnot(), new NoddyAnnotMX(), - }; - - public static void main(String[] args) throws Exception { - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - ObjectName name = new ObjectName("a:b=c"); - for (Object mbean : mbeans) { - System.out.println("Testing " + mbean.getClass().getName()); - mbs.registerMBean(mbean, name); - MBeanInfo mbi = mbs.getMBeanInfo(name); - MBeanOperationInfo[] mbois = mbi.getOperations(); - assertEquals(1, mbois.length); - MBeanParameterInfo[] mbpis = mbois[0].getSignature(); - assertEquals(2, mbpis.length); - boolean mx = Boolean.parseBoolean( - (String) mbi.getDescriptor().getFieldValue("mxbean")); - assertEquals(mx ? "p0" : "p1", mbpis[0].getName()); - assertEquals("y", mbpis[1].getName()); - mbs.unregisterMBean(name); - } - System.out.println("TEST PASSED"); - } - - private static void assertEquals(Object expect, Object actual) - throws Exception { - boolean eq; - if (expect == null) - eq = (actual == null); - else - eq = expect.equals(actual); - if (!eq) { - throw new Exception( - "TEST FAILED: expected " + expect + ", found " + actual); - } - } -} diff --git a/test/javax/management/Introspector/ResourceInjectionTest.java b/test/javax/management/Introspector/ResourceInjectionTest.java deleted file mode 100644 index 0a8882b54..000000000 --- a/test/javax/management/Introspector/ResourceInjectionTest.java +++ /dev/null @@ -1,656 +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. - * - * 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. - */ - -/* - * @test %M% %I% - * @bug 6323980 - * @summary Test resource injection via @Resource - * @author Eamonn McManus - * @run main/othervm -ea ResourceInjectionTest - */ - -import java.io.File; -import java.io.PrintWriter; -import java.io.Serializable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import javax.annotation.Resource; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.MBean; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.MXBean; -import javax.management.MalformedObjectNameException; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.ReflectionException; -import javax.management.SendNotification; -import javax.management.StandardEmitterMBean; -import javax.management.StandardMBean; -import javax.management.openmbean.MXBeanMappingFactory; - -public class ResourceInjectionTest { - private static MBeanServer mbs; - private static final ObjectName objectName; - static { - try { - objectName = new ObjectName("test:type=Test"); - } catch (MalformedObjectNameException e) { - throw new RuntimeException(e); - } - } - - /* This is somewhat nasty. In the current state of affairs, a - * StandardEmitterMBean can only get the - * MBeanServer to rewrite the source of a Notification from - * the originating object's reference to its ObjectName IF - * StandardEmitterMBean.getResource() returns a reference to the - * wrapped object. By default it doesn't, and you need to specify - * the option below to make it do so. We may hope that this is - * obscure enough for users to run into it rarely if ever. - */ - private static final StandardMBean.Options withWrappedVisible; - private static final StandardMBean.Options withWrappedVisibleMX; - static { - withWrappedVisible = new StandardMBean.Options(); - withWrappedVisible.setWrappedObjectVisible(true); - withWrappedVisibleMX = withWrappedVisible.clone(); - withWrappedVisibleMX.setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); - } - - @Retention(RetentionPolicy.RUNTIME) - private static @interface ExpectException { - Class value(); - } - - public static void main(String[] args) throws Exception { - if (!ResourceInjectionTest.class.desiredAssertionStatus()) - throw new Exception("Test must be run with -ea"); - - File policyFile = File.createTempFile("jmxperms", ".policy"); - policyFile.deleteOnExit(); - PrintWriter pw = new PrintWriter(policyFile); - pw.println("grant {"); - pw.println(" permission javax.management.MBeanPermission \"*\", \"*\";"); - pw.println(" permission javax.management.MBeanServerPermission \"*\";"); - pw.println(" permission javax.management.MBeanTrustPermission \"*\";"); - pw.println("};"); - pw.close(); - - System.setProperty("java.security.policy", policyFile.getAbsolutePath()); - System.setSecurityManager(new SecurityManager()); - - String failure = null; - - for (Method m : ResourceInjectionTest.class.getDeclaredMethods()) { - if (Modifier.isStatic(m.getModifiers()) && - m.getName().startsWith("test") && - m.getParameterTypes().length == 0) { - ExpectException expexc = m.getAnnotation(ExpectException.class); - mbs = MBeanServerFactory.newMBeanServer(); - try { - m.invoke(null); - if (expexc != null) { - failure = - m.getName() + " did not got expected exception " + - expexc.value().getName(); - System.out.println(failure); - } else - System.out.println(m.getName() + " OK"); - } catch (InvocationTargetException ite) { - Throwable t = ite.getCause(); - String prob = null; - if (expexc != null) { - if (expexc.value().isInstance(t)) { - System.out.println(m.getName() + " OK (got expected " + - expexc.value().getName() + ")"); - } else - prob = "got wrong exception"; - } else - prob = "got exception"; - if (prob != null) { - failure = m.getName() + ": " + prob + " " + - t.getClass().getName(); - System.out.println(failure); - t.printStackTrace(System.out); - } - } - } - } - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static interface Send { - public void send(); - } - - // Test @Resource in MBean defined by annotations - - @MBean - public static class Annotated { - @Resource - private volatile MBeanServer mbeanServer; - @Resource - private volatile ObjectName myName; - - @ManagedAttribute - public ObjectName getMyName() { - return myName; - } - - @ManagedOperation - public void unregisterSelf() - throws InstanceNotFoundException, MBeanRegistrationException { - mbeanServer.unregisterMBean(myName); - } - } - - private static void testAnnotated() throws Exception { - testMBean(new Annotated()); - } - - private static void testAnnotatedWrapped() throws Exception { - testMBean(new StandardMBean(new Annotated(), null)); - } - - @MBean - public static class AnnotatedSend extends Annotated implements Send { - @Resource - private volatile SendNotification sender; - - @ManagedOperation - public void send() { - sender.sendNotification(new Notification("type", this, 0L)); - } - } - - private static void testAnnotatedSend() throws Exception { - testMBean(new AnnotatedSend()); - } - - private static void testAnnotatedSendWrapped() throws Exception { - testMBean(new StandardEmitterMBean( - new AnnotatedSend(), null, withWrappedVisible, null)); - } - - // Test @Resource in MXBean defined by annotations - - @MXBean - public static class AnnotatedMX { - @Resource - private volatile MBeanServer mbeanServer; - @Resource - private volatile ObjectName myName; - - @ManagedAttribute - public ObjectName getMyName() { - return myName; - } - - @ManagedOperation - public void unregisterSelf() - throws InstanceNotFoundException, MBeanRegistrationException { - mbeanServer.unregisterMBean(myName); - } - } - - private static void testAnnotatedMX() throws Exception { - testMBean(new AnnotatedMX()); - } - - private static void testAnnotatedMXWrapped() throws Exception { - testMBean(new StandardMBean(new AnnotatedMX(), null, true)); - } - - public static class AnnotatedMXSend extends AnnotatedMX implements Send { - @Resource - private volatile SendNotification sender; - - @ManagedOperation - public void send() { - sender.sendNotification(new Notification("type", this, 0L)); - } - } - - private static void testAnnotatedMXSend() throws Exception { - testMBean(new AnnotatedMXSend()); - } - - private static void testAnnotatedMXSendWrapped() throws Exception { - testMBean(new StandardEmitterMBean( - new AnnotatedMXSend(), null, withWrappedVisibleMX, null)); - } - - // Test @Resource in Standard MBean - - public static interface SimpleStandardMBean { - public ObjectName getMyName(); - public void unregisterSelf() throws Exception; - } - - public static class SimpleStandard implements SimpleStandardMBean { - @Resource(type = MBeanServer.class) - private volatile Object mbeanServer; - @Resource(type = ObjectName.class) - private volatile Object myName; - - public ObjectName getMyName() { - return (ObjectName) myName; - } - - public void unregisterSelf() throws Exception { - ((MBeanServer) mbeanServer).unregisterMBean(getMyName()); - } - } - - private static void testStandard() throws Exception { - testMBean(new SimpleStandard()); - } - - private static void testStandardWrapped() throws Exception { - testMBean(new StandardMBean(new SimpleStandard(), SimpleStandardMBean.class)); - } - - public static interface SimpleStandardSendMBean extends SimpleStandardMBean { - public void send(); - } - - public static class SimpleStandardSend - extends SimpleStandard implements SimpleStandardSendMBean { - @Resource(type = SendNotification.class) - private volatile Object sender; - - public void send() { - ((SendNotification) sender).sendNotification( - new Notification("type", this, 0L)); - } - } - - private static void testStandardSend() throws Exception { - testMBean(new SimpleStandardSend()); - } - - private static void testStandardSendWrapped() throws Exception { - testMBean(new StandardEmitterMBean( - new SimpleStandardSend(), SimpleStandardSendMBean.class, - withWrappedVisible, null)); - } - - // Test @Resource in MXBean - - public static interface SimpleMXBean { - public ObjectName getMyName(); - public void unregisterSelf() throws Exception; - } - - public static class SimpleMX implements SimpleMXBean { - @Resource(type = MBeanServer.class) - private volatile Object mbeanServer; - @Resource(type = ObjectName.class) - private volatile Object myName; - - public ObjectName getMyName() { - return (ObjectName) myName; - } - - public void unregisterSelf() throws Exception { - ((MBeanServer) mbeanServer).unregisterMBean(getMyName()); - } - } - - private static void testMX() throws Exception { - testMBean(new SimpleMX()); - } - - private static void testMXWrapped() throws Exception { - testMBean(new StandardMBean(new SimpleMX(), SimpleMXBean.class, true)); - } - - public static interface SimpleMXBeanSend extends SimpleMXBean { - public void send(); - } - - public MBeanServer getMbs() { - return mbs; - } - - public static class SimpleMXSend extends SimpleMX implements SimpleMXBeanSend { - @Resource(type = SendNotification.class) - private volatile Object sender; - - public void send() { - ((SendNotification) sender).sendNotification( - new Notification("type", this, 0L)); - } - } - - private static void testMXSend() throws Exception { - testMBean(new SimpleMXSend()); - } - - private static void testMXSendWrapped() throws Exception { - testMBean(new StandardEmitterMBean( - new SimpleMXSend(), SimpleMXBeanSend.class, - withWrappedVisibleMX, null)); - } - - // Test @Resource in Dynamic MBean - - private static class SimpleDynamic implements DynamicMBean { - private MBeanServer mbeanServer; - private ObjectName myName; - - @Resource - private synchronized void setMBeanServer(MBeanServer mbs) { - mbeanServer = mbs; - } - - @Resource(type = ObjectName.class) - private synchronized void setObjectName(Serializable name) { - myName = (ObjectName) name; - } - - public synchronized Object getAttribute(String attribute) - throws AttributeNotFoundException { - if (attribute.equals("MyName")) - return myName; - throw new AttributeNotFoundException(attribute); - } - - public void setAttribute(Attribute attribute) - throws AttributeNotFoundException { - throw new AttributeNotFoundException(attribute.getName()); - } - - public synchronized AttributeList getAttributes(String[] attributes) { - AttributeList list = new AttributeList(); - for (String name : attributes) { - if (name.equals("MyName")) - list.add(new Attribute("MyName", myName)); - } - return list; - } - - public AttributeList setAttributes(AttributeList attributes) { - return new AttributeList(); - } - - public synchronized Object invoke( - String actionName, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - if (actionName.equals("unregisterSelf") && - (params == null || params.length == 0) && - (signature == null || signature.length == 0)) { - try { - mbeanServer.unregisterMBean(myName); - return null; - } catch (Exception x) { - throw new MBeanException(x); - } - } else { - Exception x = new NoSuchMethodException( - actionName + Arrays.toString(signature)); - throw new MBeanException(x); - } - } - - public MBeanInfo getMBeanInfo() { - DynamicMBean mbean = new StandardMBean( - new SimpleStandard(), SimpleStandardMBean.class, false); - return mbean.getMBeanInfo(); - } - } - - private static void testDynamic() throws Exception { - testMBean(new SimpleDynamic()); - } - - private static class SimpleDynamicSend extends SimpleDynamic { - private SendNotification sender; - - @Resource - private synchronized void setSender(SendNotification sender) { - this.sender = sender; - } - - @Override - public synchronized Object invoke( - String actionName, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - if (actionName.equals("send")) { - sender.sendNotification(new Notification("type", this, 0L)); - return null; - } else - return super.invoke(actionName, params, signature); - } - } - - private static void testDynamicSend() throws Exception { - testMBean(new SimpleDynamicSend()); - } - - // Test that @Resource classes don't have to be public - // They can even be defined within methods! - // But you can't have any @ManagedAttributes or @ManagedOperations - // in such MBeans so their utility is limited. - - private static void testNonPublic() throws Exception { - @MBean - class NonPublic { - @Resource - ObjectName myName; - } - assert !Modifier.isPublic(NonPublic.class.getModifiers()); - NonPublic mbean = new NonPublic(); - mbs.registerMBean(mbean, objectName); - assert objectName.equals(mbean.myName); - } - - // Test inheritance and multiple injections of the same value - - private static class ManyResources extends AnnotatedSend { - @Resource - private volatile ObjectName myName; // same name as in parent! - @Resource(type=ObjectName.class) - private volatile Object myOtherName; - private volatile ObjectName myThirdName; - private volatile ObjectName myFourthName; - private volatile int methodCalls; - @Resource - private volatile SendNotification send1; - @Resource(type = SendNotification.class) - private volatile Object send2; - - @Resource - void setMyName(ObjectName name) { - myThirdName = name; - methodCalls++; - } - - @Resource(type=ObjectName.class) - private void setMyNameAgain(ObjectName name) { - myFourthName = name; - methodCalls++; - } - - void check() { - assert objectName.equals(myName) : myName; - for (ObjectName name : new ObjectName[] { - (ObjectName)myOtherName, myThirdName, myFourthName - }) { - assert myName == name : name; - } - assert methodCalls == 2 : methodCalls; - assert send1 != null && send2 == send1; - } - } - - private static void testManyResources() throws Exception { - ManyResources mr = new ManyResources(); - testMBean(mr); - mr.check(); - } - - // Test that method override doesn't lead to multiple calls of the same method - - private static class ManyResourcesSub extends ManyResources { - private boolean called; - - @Override - @Resource - void setMyName(ObjectName name) { - super.setMyName(name); - called = true; - } - - void check2() { - assert called; - } - } - - private static void testOverride() throws Exception { - ManyResourcesSub mrs = new ManyResourcesSub(); - testMBean(mrs); - mrs.check(); - mrs.check2(); - } - - // Test that @Resource is illegal on static fields - - @MBean - public static class StaticResource { - @Resource - private static ObjectName name; - } - - @ExpectException(NotCompliantMBeanException.class) - private static void testStaticResource() throws Exception { - testMBean(new StaticResource()); - } - - // Test that @Resource is illegal on static methods - - @MBean - public static class StaticResourceMethod { - @Resource - private static void setObjectName(ObjectName name) {} - } - - @ExpectException(NotCompliantMBeanException.class) - private static void testStaticResourceMethod() throws Exception { - testMBean(new StaticResourceMethod()); - } - - // Test that @Resource is illegal on methods that don't return void - - @MBean - public static class NonVoidMethod { - @Resource - private String setObjectName(ObjectName name) { - return "oops"; - } - } - - @ExpectException(NotCompliantMBeanException.class) - private static void testNonVoidMethod() throws Exception { - testMBean(new NonVoidMethod()); - } - - // Test that @Resource is illegal on methods with no arguments - - @MBean - public static class NoArgMethod { - @Resource(type=ObjectName.class) - private void setObjectName() {} - } - - @ExpectException(NotCompliantMBeanException.class) - private static void testNoArgMethod() throws Exception { - testMBean(new NoArgMethod()); - } - - // Test that @Resource is illegal on methods with more than one argument - - @MBean - public static class MultiArgMethod { - @Resource - private void setObjectName(ObjectName name, String what) {} - } - - @ExpectException(NotCompliantMBeanException.class) - private static void testMultiArgMethod() throws Exception { - testMBean(new MultiArgMethod()); - } - - private static class CountListener implements NotificationListener { - volatile int count; - public void handleNotification(Notification notification, Object handback) { - count++; - } - } - - private static void testMBean(Object mbean) throws Exception { - mbs.registerMBean(mbean, objectName); - - final ObjectName name = (ObjectName) mbs.getAttribute(objectName, "MyName"); - assert objectName.equals(name) : name; - - if (mbean instanceof Send || mbean instanceof NotificationEmitter) { - assert mbs.isInstanceOf(name, NotificationEmitter.class.getName()); - CountListener countL = new CountListener(); - mbs.addNotificationListener(name, countL, null, null); - NotificationListener checkSource = new NotificationListener() { - public void handleNotification(Notification n, Object h) { - assert n.getSource().equals(name) : n.getSource(); - } - }; - mbs.addNotificationListener(name, checkSource, null, null); - mbs.invoke(objectName, "send", null, null); - assert countL.count == 1; - mbs.removeNotificationListener(name, checkSource); - mbs.removeNotificationListener(name, countL, null, null); - } - - mbs.invoke(objectName, "unregisterSelf", null, null); - assert !mbs.isRegistered(objectName); - } -} diff --git a/test/javax/management/MBeanServer/AttributeListMapTest.java b/test/javax/management/MBeanServer/AttributeListMapTest.java deleted file mode 100644 index 94dd39306..000000000 --- a/test/javax/management/MBeanServer/AttributeListMapTest.java +++ /dev/null @@ -1,115 +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. - * - * 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. - */ - -/* - * @test - * @bug 6336968 - * @summary Test AttributeList.toMap - * @author Eamonn McManus - */ - -import java.math.BigInteger; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import javax.management.Attribute; -import javax.management.AttributeList; - -public class AttributeListMapTest { - - private static String failure; - - public static void main(String[] args) throws Exception { - AttributeList attrs = new AttributeList(Arrays.asList( - new Attribute("Str", "Five"), - new Attribute("Int", 5), - new Attribute("Flt", 5.0))); - - Map map = attrs.toMap(); - final Map expectMap = new HashMap(); - for (Attribute attr : attrs.asList()) - expectMap.put(attr.getName(), attr.getValue()); - assertEquals("Initial map", expectMap, map); - assertEquals("Initial map size", 3, map.size()); - assertEquals("Name set", expectMap.keySet(), map.keySet()); - assertEquals("Values", new HashSet(expectMap.values()), - new HashSet(map.values())); - assertEquals("Entry set", expectMap.entrySet(), map.entrySet()); - - AttributeList attrs2 = new AttributeList(map); - assertEquals("AttributeList from Map", attrs, attrs2); - // This assumes that the Map conserves the order of the attributes, - // which is not specified but true because we use LinkedHashMap. - - // Check that toMap fails if the list contains non-Attribute elements. - AttributeList attrs3 = new AttributeList(attrs); - attrs3.add("Hello"); // allowed but curious - try { - map = attrs3.toMap(); - fail("toMap succeeded on list with non-Attribute elements"); - } catch (Exception e) { - assertEquals("Exception for toMap with non-Atttribute elements", - IllegalArgumentException.class, e.getClass()); - } - - // Check that the Map does not reflect changes made to the list after - // the Map was obtained. - AttributeList attrs4 = new AttributeList(attrs); - map = attrs4.toMap(); - attrs4.add(new Attribute("Big", new BigInteger("5"))); - assertEquals("Map after adding element to list", expectMap, map); - - // Check that if there is more than one Attribute with the same name - // then toMap() chooses the last of them. - AttributeList attrs5 = new AttributeList(attrs); - attrs5.add(new Attribute("Str", "Cinq")); - map = attrs5.toMap(); - assertEquals("Size of Map for list with duplicate attribute name", - 3, map.size()); - Object value = map.get("Str"); - assertEquals("Value of Str in Map for list with two values for it", - "Cinq", value); - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static void assertEquals(String what, Object expect, Object actual) { - if (eq(expect, actual)) - System.out.println("OK: " + what); - else - fail(what + ": expected " + expect + ", got " + actual); - } - - private static boolean eq(Object x, Object y) { - return (x == null) ? (y == null) : x.equals(y); - } - - private static void fail(String why) { - System.out.println("FAIL: " + why); - failure = why; - } -} diff --git a/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java b/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java deleted file mode 100644 index fc52711c7..000000000 --- a/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java +++ /dev/null @@ -1,405 +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. - * - * 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. - */ - -/* - * @test DynamicWrapperMBeanTest - * @bug 6624232 6776225 - * @summary Test the DynamicWrapperMBean interface - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import javax.annotation.Resource; -import javax.management.JMX; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationInfo; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.SendNotification; -import javax.management.StandardEmitterMBean; -import javax.management.StandardMBean; -import javax.management.modelmbean.ModelMBeanInfo; -import javax.management.modelmbean.ModelMBeanInfoSupport; -import javax.management.modelmbean.ModelMBeanOperationInfo; -import javax.management.modelmbean.RequiredModelMBean; -import static javax.management.StandardMBean.Options; - -public class DynamicWrapperMBeanTest { - private static String failure; - - public static void main(String[] args) throws Exception { - wrapTest(); - notifTest(); - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static final Options wrappedVisOpts = new Options(); - private static final Options wrappedInvisOpts = new Options(); - static { - wrappedVisOpts.setWrappedObjectVisible(true); - wrappedInvisOpts.setWrappedObjectVisible(false); - } - - public static interface WrappedMBean { - public void sayHello(); - } - public static class Wrapped implements WrappedMBean { - public void sayHello() { - System.out.println("Hello"); - } - } - - private static void wrapTest() throws Exception { - if (Wrapped.class.getClassLoader() == - StandardMBean.class.getClassLoader()) { - throw new Exception( - "TEST ERROR: Resource and StandardMBean have same ClassLoader"); - } - - assertEquals("Options withWrappedObjectVisible(false)", - new Options(), wrappedInvisOpts); - - Wrapped resource = new Wrapped(); - - StandardMBean visible = - new StandardMBean(resource, WrappedMBean.class, wrappedVisOpts); - StandardMBean invisible = - new StandardMBean(resource, WrappedMBean.class, wrappedInvisOpts); - - assertEquals("getResource withWrappedObjectVisible(true)", - resource, visible.getWrappedObject()); - assertEquals("getResource withWrappedObjectVisible(false)", - invisible, invisible.getWrappedObject()); - - System.out.println("===Testing StandardMBean==="); - - ObjectName visibleName = new ObjectName("a:type=visible"); - ObjectName invisibleName = new ObjectName("a:type=invisible"); - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - mbs.registerMBean(visible, visibleName); - mbs.registerMBean(invisible, invisibleName); - - assertEquals("ClassLoader for visible resource", - Wrapped.class.getClassLoader(), - mbs.getClassLoaderFor(visibleName)); - assertEquals("ClassLoader for invisible resource", - StandardMBean.class.getClassLoader(), - mbs.getClassLoaderFor(invisibleName)); - - assertEquals("isInstanceOf(WrappedMBean) for visible wrapped", - true, mbs.isInstanceOf(visibleName, WrappedMBean.class.getName())); - assertEquals("isInstanceOf(WrappedMBean) for invisible wrapped", - false, mbs.isInstanceOf(invisibleName, WrappedMBean.class.getName())); - assertEquals("isInstanceOf(StandardMBean) for visible wrapped", - false, mbs.isInstanceOf(visibleName, StandardMBean.class.getName())); - assertEquals("isInstanceOf(StandardMBean) for invisible wrapped", - true, mbs.isInstanceOf(invisibleName, StandardMBean.class.getName())); - - mbs.unregisterMBean(visibleName); - mbs.unregisterMBean(invisibleName); - - System.out.println("===Testing RequiredModelMBean==="); - - // Godawful Model MBeans... - ModelMBeanOperationInfo mmboi = new ModelMBeanOperationInfo( - "say hello to the nice man", Wrapped.class.getMethod("sayHello")); - ModelMBeanInfo visibleMmbi = new ModelMBeanInfoSupport( - Wrapped.class.getName(), "Visible wrapped", null, null, - new ModelMBeanOperationInfo[] {mmboi}, null); - ModelMBeanInfo invisibleMmbi = new ModelMBeanInfoSupport( - Wrapped.class.getName(), "Invisible wrapped", null, null, - new ModelMBeanOperationInfo[] {mmboi}, null); - RequiredModelMBean visibleRmmb = new RequiredModelMBean(visibleMmbi); - RequiredModelMBean invisibleRmmb = new RequiredModelMBean(invisibleMmbi); - visibleRmmb.setManagedResource(resource, "VisibleObjectReference"); - invisibleRmmb.setManagedResource(resource, "ObjectReference"); - - mbs.registerMBean(visibleRmmb, visibleName); - mbs.registerMBean(invisibleRmmb, invisibleName); - - assertEquals("ClassLoader for visible wrapped", - Wrapped.class.getClassLoader(), - mbs.getClassLoaderFor(visibleName)); - assertEquals("ClassLoader for invisible wrapped", - StandardMBean.class.getClassLoader(), - mbs.getClassLoaderFor(invisibleName)); - - assertEquals("isInstanceOf(WrappedMBean) for visible resource", - true, mbs.isInstanceOf(visibleName, WrappedMBean.class.getName())); - assertEquals("isInstanceOf(WrappedMBean) for invisible resource", - false, mbs.isInstanceOf(invisibleName, WrappedMBean.class.getName())); - assertEquals("isInstanceOf(RequiredModelMBean) for visible resource", - false, mbs.isInstanceOf(visibleName, RequiredModelMBean.class.getName())); - assertEquals("isInstanceOf(RequiredModelMBean) for invisible resource", - true, mbs.isInstanceOf(invisibleName, RequiredModelMBean.class.getName())); - - mbs.unregisterMBean(visibleName); - mbs.unregisterMBean(invisibleName); - } - - private static enum WrapType { - NBS("NotificationBroadcasterSupport"), - INJ("@Resource SendNotification"), - STD_MBEAN_NBS("StandardMBean delegating to NotificationBroadcasterSupport"), - STD_MBEAN_INJ("StandardMBean delegating to @Resource SendNotification"), - STD_MBEAN_SUB_NBS("StandardMBean subclass implementing NotificationBroadcaster"), - STD_MBEAN_SUB_INJ("StandardMBean subclass with @Resource SendNotification"), - STD_EMIT_MBEAN_NBS("StandardEmitterMBean delegating to NotificationBroadcasterSupport"), - STD_EMIT_MBEAN_INJ("StandardEmitterMBean delegating to @Resource SendNotification"), - STD_EMIT_MBEAN_SUB("StandardEmitterMBean subclass"), - STD_EMIT_MBEAN_SUB_INJ("StandardEmitterMBean subclass with @Resource SendNotification"); - - WrapType(String s) { - this.s = s; - } - - @Override - public String toString() { - return s; - } - - private final String s; - } - - @NotificationInfo( - types = {"foo", "bar"} - ) - public static interface BroadcasterMBean { - public void send(Notification n); - } - - public static class Broadcaster - extends NotificationBroadcasterSupport implements BroadcasterMBean { - public void send(Notification n) { - super.sendNotification(n); - } - } - - public static interface SendNotifMBean extends BroadcasterMBean { - } - - public static class SendNotif implements SendNotifMBean { - @Resource - private volatile SendNotification sendNotif; - - public void send(Notification n) { - sendNotif.sendNotification(n); - } - } - - public static class StdBroadcaster - extends StandardMBean - implements BroadcasterMBean, NotificationBroadcaster { - private final NotificationBroadcasterSupport nbs = - new NotificationBroadcasterSupport(); - - public StdBroadcaster() throws Exception { - super(BroadcasterMBean.class); - } - - public void send(Notification n) { - nbs.sendNotification(n); - } - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) { - nbs.addNotificationListener(listener, filter, handback); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - return null; - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - nbs.removeNotificationListener(listener); - } - } - - public static class StdSendNotif - extends StandardMBean implements SendNotifMBean { - @Resource - private volatile SendNotification sendNotif; - - public StdSendNotif() throws Exception { - super(SendNotifMBean.class); - } - - public void send(Notification n) { - sendNotif.sendNotification(n); - } - } - - public static class StdEmitterBroadcaster // :-) - extends StandardEmitterMBean - implements BroadcasterMBean { - - public StdEmitterBroadcaster() throws Exception { - super(BroadcasterMBean.class, null); - } - - public void send(Notification n) { - super.sendNotification(n); - } - } - - // This case is unlikely - if you're using @Resource SendNotification - // then there's no point in using StandardEmitterMBean, since - // StandardMBean would suffice. - public static class StdEmitterSendNotif - extends StandardEmitterMBean implements SendNotifMBean { - @Resource - private volatile SendNotification sendNotif; - - public StdEmitterSendNotif() { - super(SendNotifMBean.class, null); - } - - public void send(Notification n) { - sendNotif.sendNotification(n); - } - } - - // Test that JMX.isNotificationSource and - // mbs.isInstanceOf("NotificationBroadcaster") work correctly even when - // the MBean is a broadcaster by virtue of its wrapped resource. - // Test that we find the MBeanNotificationInfo[] from the @NotificationInfo - // annotation on BroadcasterMBean. We cover a large number of different - // MBean types, but all ultimately implement that interface. - private static void notifTest() throws Exception { - System.out.println("===Testing notification senders==="); - - for (WrapType wrapType : WrapType.values()) { - System.out.println("---" + wrapType); - - final Object mbean; - - switch (wrapType) { - case NBS: - // An MBean that extends NotificationBroadcasterSupport - mbean = new Broadcaster(); - break; - case INJ: - // An MBean that injects SendNotification - mbean = new SendNotif(); - break; - case STD_MBEAN_NBS: - // A StandardMBean that delegates to a NotificationBroadcasterSupport - mbean = new StandardMBean( - new Broadcaster(), BroadcasterMBean.class, wrappedVisOpts); - break; - case STD_MBEAN_INJ: - // A StandardMBean that delegates to an object that injects - // SendNotification - mbean = new StandardMBean( - new SendNotif(), BroadcasterMBean.class, wrappedVisOpts); - break; - case STD_EMIT_MBEAN_NBS: { - // A StandardEmitterMBean that delegates to a NotificationBroadcasterSupport - Broadcaster broadcaster = new Broadcaster(); - mbean = new StandardEmitterMBean( - broadcaster, BroadcasterMBean.class, wrappedVisOpts, - broadcaster); - break; - } - case STD_EMIT_MBEAN_INJ: { - // A StandardEmitterMBean that delegates to an object that injects - // SendNotification - SendNotif sendNotif = new SendNotif(); - mbean = new StandardEmitterMBean( - sendNotif, BroadcasterMBean.class, wrappedVisOpts, - null); - break; - } - case STD_MBEAN_SUB_NBS: - // A subclass of StandardMBean that implements NotificationBroadcaster - mbean = new StdBroadcaster(); - break; - case STD_MBEAN_SUB_INJ: - // A subclass of StandardMBean that injects SendNotification - mbean = new StdSendNotif(); - break; - case STD_EMIT_MBEAN_SUB: - // A subclass of StandardEmitterMBean - mbean = new StdEmitterBroadcaster(); - break; - case STD_EMIT_MBEAN_SUB_INJ: - // A subclass of StandardEmitterMBean that injects SendNotification - // (which is a rather strange thing to do and probably a user - // misunderstanding but we should do the right thing anyway). - mbean = new StdEmitterSendNotif(); - break; - default: - throw new AssertionError(); - } - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - - final ObjectName name = new ObjectName("a:type=Sender"); - mbs.registerMBean(mbean, name); - boolean isBroadcaster = mbs.isInstanceOf( - name, NotificationBroadcaster.class.getName()); - assertEquals("JMX.isNotificationSource(mbean)", - true, JMX.isNotificationSource(mbean)); - assertEquals("isInstanceOf(NotificationBroadcaster)", - true, isBroadcaster); - MBeanNotificationInfo[] mbnis = - mbs.getMBeanInfo(name).getNotifications(); - assertEquals("MBeanNotificationInfo not empty", - true, (mbnis.length > 0)); - - mbs.unregisterMBean(name); - } - } - - private static void assertEquals(String what, Object expect, Object actual) { - if (equal(expect, actual)) - System.out.println("OK: " + what + " = " + expect); - else - fail(what + " should be " + expect + ", is " + actual); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - return x.equals(y); - } - - private static void fail(String why) { - failure = why; - System.out.println("FAIL: " + why); - } -} diff --git a/test/javax/management/MBeanServer/InstanceNotFoundExceptionTest.java b/test/javax/management/MBeanServer/InstanceNotFoundExceptionTest.java deleted file mode 100644 index 300796553..000000000 --- a/test/javax/management/MBeanServer/InstanceNotFoundExceptionTest.java +++ /dev/null @@ -1,76 +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. - * - * 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. - */ - -/* - * @test - * @bug 6669137 - * @summary Test the constructors of InstanceNotFoundExceptionTest. - * @author Daniel Fuchs - * @compile InstanceNotFoundExceptionTest.java - * @run main InstanceNotFoundExceptionTest - */ - -import javax.management.InstanceNotFoundException; -import javax.management.ObjectName; - -public class InstanceNotFoundExceptionTest { - public static void main(String[] args) throws Exception { - final InstanceNotFoundException x = - new InstanceNotFoundException(); - System.out.println("InstanceNotFoundException(): "+x.getMessage()); - - final String msg = "who is toto?"; - final InstanceNotFoundException x2 = - new InstanceNotFoundException(msg); - if (!msg.equals(x2.getMessage())) - throw new Exception("Bad message: expected "+msg+ - ", got "+x2.getMessage()); - System.out.println("InstanceNotFoundException(" + - msg+"): "+x2.getMessage()); - - final InstanceNotFoundException x3 = - new InstanceNotFoundException((String)null); - if (x3.getMessage() != null) - throw new Exception("Bad message: expected "+null+ - ", got "+x3.getMessage()); - System.out.println("InstanceNotFoundException((String)null): "+ - x3.getMessage()); - - final ObjectName n = new ObjectName("who is toto?:type=msg"); - final InstanceNotFoundException x4 = - new InstanceNotFoundException(n); - if (!String.valueOf(n).equals(x4.getMessage())) - throw new Exception("Bad message: expected "+n+ - ", got "+x4.getMessage()); - System.out.println("InstanceNotFoundException(" + - n+"): "+x4.getMessage()); - - final InstanceNotFoundException x5 = - new InstanceNotFoundException((ObjectName)null); - if (!String.valueOf((ObjectName)null).equals(x5.getMessage())) - throw new Exception("Bad message: expected " + - String.valueOf((ObjectName)null)+" got "+x5.getMessage()); - System.out.println("InstanceNotFoundException((ObjectName)null): "+ - x5.getMessage()); - } -} diff --git a/test/javax/management/MBeanServer/MBeanExceptionTest.java b/test/javax/management/MBeanServer/MBeanExceptionTest.java index 6bb6f77b7..1a6b44d8f 100644 --- a/test/javax/management/MBeanServer/MBeanExceptionTest.java +++ b/test/javax/management/MBeanServer/MBeanExceptionTest.java @@ -34,8 +34,16 @@ import java.util.Collections; import java.util.Set; -import javax.management.*; -import javax.management.namespace.MBeanServerSupport; +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.DynamicMBean; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.ObjectName; +import javax.management.RuntimeMBeanException; +import javax.management.StandardMBean; public class MBeanExceptionTest { public static void main(String[] args) throws Exception { @@ -62,46 +70,41 @@ public class MBeanExceptionTest { final boolean[] booleans = {false, true}; - for (boolean mbss : booleans) { - for (boolean runtimeX : booleans) { - Class excC = - runtimeX ? RuntimeMBeanException.class : MBeanException.class; - String excS = - runtimeX ? "a RuntimeMBeanException" : "an MBeanException"; - String mbsS = - mbss ? "a conformant MBeanServerSupport" : "a plain MBeanServer"; - MBeanServer xmbs = - mbss ? new CreateExceptionMBS() : mbs; + for (boolean runtimeX : booleans) { + Class excC = + runtimeX ? RuntimeMBeanException.class : MBeanException.class; + String excS = + runtimeX ? "a RuntimeMBeanException" : "an MBeanException"; + String mbsS = "a plain MBeanServer"; + System.out.println( + "Test that, with " + mbsS + ", " + excS + " is wrapped " + + "in " + excS); + // E.g. "Test that, with a plain MBeanServer, an MBeanException + // is wrapped in an MBeanException". + try { + mbs.createMBean( + Except.class.getName(), new ObjectName(":name=Oops"), + new Object[] {runtimeX}, + new String[] {boolean.class.getName()}); System.out.println( - "Test that, with " + mbsS + ", " + excS + " is wrapped " + - "in " + excS); - // E.g. "Test that, with a plain MBeanServer, an MBeanException - // is wrapped in an MBeanException". - try { - mbs.createMBean( - Except.class.getName(), new ObjectName(":name=Oops"), - new Object[] {runtimeX}, - new String[] {boolean.class.getName()}); + "FAIL: createMBean succeeded but should not have"); + failures++; + } catch (Exception e) { + if (!excC.isInstance(e)) { System.out.println( - "FAIL: createMBean succeeded but should not have"); + "FAIL: expected " + excC.getName() + " from " + + "createMBean, got " + e); failures++; - } catch (Exception e) { - if (!excC.isInstance(e)) { + } else { + Throwable cause = e.getCause(); + if (!excC.isInstance(cause)) { System.out.println( - "FAIL: expected " + excC.getName() + " from " + - "createMBean, got " + e); + "FAIL: expected " + excC.getName() + + " as cause of " + excC.getName() + + ", got " + e); failures++; - } else { - Throwable cause = e.getCause(); - if (!excC.isInstance(cause)) { - System.out.println( - "FAIL: expected " + excC.getName() + - " as cause of " + excC.getName() + - ", got " + e); - failures++; - } else - System.out.println("...ok"); - } + } else + System.out.println("...ok"); } } } @@ -280,28 +283,4 @@ public class MBeanExceptionTest { private static final RuntimeException theUncheckedException = new UnsupportedOperationException("The unchecked exception " + "that should be seen"); - - private static class CreateExceptionMBS extends MBeanServerSupport { - @Override - protected Set getNames() { - return Collections.emptySet(); - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - throw new InstanceNotFoundException(name); - } - - @Override - public ObjectInstance createMBean(String className, - ObjectName name, ObjectName loaderName, Object[] params, - String[] signature, boolean useCLR) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - Exception wrapped = new MBeanException(new Exception(), "Bang"); - throw new MBeanException(wrapped, "Bang"); - } - } } diff --git a/test/javax/management/MBeanServerFactory/NamedMBeanServerTest.java b/test/javax/management/MBeanServerFactory/NamedMBeanServerTest.java deleted file mode 100644 index f2114f967..000000000 --- a/test/javax/management/MBeanServerFactory/NamedMBeanServerTest.java +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Copyright 2003-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. - * - * 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. - */ - -/* - * @test - * @summary Test named MBeanServers. - * @author Daniel Fuchs - * @bug 6299231 - * @run clean NamedMBeanServerTest - * @run build NamedMBeanServerTest - * @run main NamedMBeanServerTest - */ - -import java.util.Arrays; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.management.MBeanServer; -import javax.management.MBeanServerBuilder; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; - -/** - * This test can probably be leveraged in the JCK to test compatibilty - * of MBeanServerFactory *Name* method implementation. - * @author dfuchs - */ -public class NamedMBeanServerTest { - - /** - * One enum value for each way of creating an MBeanServer through the - * MBeanServerFactory - */ - public static enum Creator { - newMBeanServer() { - public MBeanServer create(String domain) { - return MBeanServerFactory.newMBeanServer(domain); - } - public String test(MBeanServer server, String domain) { - System.out.println(toString()+"("+domain+")"); - return test(server, - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME, - domain); - } - public MBeanServer[] servers(Config config) { - return config.ndServers; - } - public String[] strings(Config config) { - return domains(config); - } - public String[] domains(Config config) { - return config.newDomains; - } - public String[] names(Config config) { - return null; - } - }, - createMBeanServer() { - public MBeanServer create(String domain) { - return MBeanServerFactory.createMBeanServer(domain); - } - public String test(MBeanServer server, String domain) { - System.out.println(toString()+"("+domain+")"); - return test(server,MBeanServerFactory.DEFAULT_MBEANSERVER_NAME, - domain); - } - public MBeanServer[] servers(Config config) { - return config.cdServers; - } - public String[] strings(Config config) { - return domains(config); - } - public String[] domains(Config config) { - return config.createDomains; - } - public String[] names(Config config) { - return null; - } - }, - newNamedMBeanServer() { - public MBeanServer create(String name) { - return MBeanServerFactory.newNamedMBeanServer(name,null); - } - public String test(MBeanServer server, String name) { - System.out.println(toString()+"("+name+",null)"); - return test(server,name,"DefaultDomain"); - } - public MBeanServer[] servers(Config config) { - return config.nnServers; - } - public String[] strings(Config config) { - return names(config); - } - public String[] domains(Config config) { - return null; - } - public String[] names(Config config) { - return config.newNames; - } - }, - createNamedMBeanServer() { - public MBeanServer create(String name) { - return MBeanServerFactory.createNamedMBeanServer(name,null); - } - public String test(MBeanServer server, String name) { - System.out.println(toString()+"("+name+",null)"); - return test(server,name,"DefaultDomain"); - } - public MBeanServer[] servers(Config config) { - return config.cnServers; - } - public String[] strings(Config config) { - return names(config); - } - public String[] domains(Config config) { - return null; - } - public String[] names(Config config) { - return config.createNames; - } - }; - - // creates an MBeanServer using the specified input string. - // either a domain, (for UNNAMED) or a mbeanServerName (for NAMED) - public abstract MBeanServer create(String string); - - // test the created server against the string used as input to create - // it. - public abstract String test(MBeanServer server, String ref); - - public abstract MBeanServer[] servers(Config config); - public abstract String[] strings(Config config); - public abstract String[] names(Config config); - public abstract String[] domains(Config config); - - public MBeanServer[] servers(Config config, String... refs) { - final MBeanServer[] servers = servers(config); - final String[] strings = strings(config); - final MBeanServer[] res = new MBeanServer[refs.length]; - for (int i=0;i found = - MBeanServerFactory.findMBeanServerByName(name); - if (!registered && found.contains(server)) - return " Server "+name+" found by name - " + - "but should not be registered"; - if (!registered && - !name.equals(MBeanServerFactory.DEFAULT_MBEANSERVER_NAME) && - found.size()>0) - return " Server "+name+" had too many matches: " + found.size(); - if (registered && !found.contains(server)) - return " Server "+name+" not found by name - " + - "but is registered!"; - if (registered && - !name.equals(MBeanServerFactory.DEFAULT_MBEANSERVER_NAME) && - !(found.size()==1)) - return " Server "+name+" had too many matches: " + found.size(); - return null; - } - - public static final EnumSet NAMED = - EnumSet.of(createNamedMBeanServer, newNamedMBeanServer); - public static final EnumSet UNNAMED = - EnumSet.complementOf(NAMED); - public static final EnumSet REFERENCED = - EnumSet.of(createMBeanServer, createNamedMBeanServer); - public static final EnumSet UNREFERENCED = - EnumSet.complementOf(REFERENCED); - - } - - public static class Config { - final String[] newDomains; - final String[] createDomains; - final String[] newNames; - final String[] createNames; - final MBeanServer[] ndServers; - final MBeanServer[] cdServers; - final MBeanServer[] nnServers; - final MBeanServer[] cnServers; - final Map> queries; - Config(String[][] data) { - this(data[0],data[1],data[2],data[3]); - } - Config(String[] nd, String[] cd, String[] nn, String[] cn) { - this.newDomains=nd.clone(); - this.createDomains=cd.clone(); - this.newNames=nn.clone(); - this.createNames=cn.clone(); - ndServers = new MBeanServer[nd.length]; - cdServers = new MBeanServer[cd.length]; - nnServers = new MBeanServer[nn.length]; - cnServers = new MBeanServer[cn.length]; - queries = new HashMap>(); - init(); - } - private void init() { - for (Creator c : Creator.values()) fill(c); - addQuery(null,Creator.createMBeanServer.servers(this)); - addQuery(null,Creator.createNamedMBeanServer.servers(this)); - addQuery("?*",Creator.createMBeanServer.servers(this)); - addQuery("?*",Creator.createNamedMBeanServer.servers(this)); - addQuery("*",Creator.createMBeanServer.servers(this)); - addQuery("*",Creator.createNamedMBeanServer.servers(this)); - addQuery(MBeanServerFactory.DEFAULT_MBEANSERVER_NAME, - Creator.createMBeanServer.servers(this)); - } - private void addQuery(String pattern, MBeanServer... servers) { - final Set s = getQuery(pattern); - s.addAll(Arrays.asList(servers)); - } - public Set getQuery(String pattern) { - final Set s = queries.get(pattern); - if (s != null) return s; - queries.put(pattern,new HashSet()); - return queries.get(pattern); - } - public Set getPatterns() { - return queries.keySet(); - } - private void fill(Creator creator) { - fill(creator.servers(this),creator.strings(this),creator); - } - private void fill(MBeanServer[] dest, String[] src, Creator creator) { - for(int i=0;i found = - MBeanServerFactory.findMBeanServerByName(pat); - String sep=" "; - for (MBeanServer m : found) { - System.out.print(sep+MBeanServerFactory.getMBeanServerName(m)); - sep=", "; - } - System.out.println(" ]"); - final Set founds = new HashSet(); - founds.addAll(found); - if (!founds.equals(config.getQuery(pat))) { - final String msg = - "bad result for findMBeanServerByName(\""+ - pat+"\"): expected "+config.getQuery(pat).size()+", "+ - "got "+founds.size(); - throw new Exception(msg); - } - } - } - - public static void testexception(Creator c, String name, - Class error) throws Exception { - Exception failed = null; - MBeanServer server = null; - try { - server = c.create(name); - } catch (Exception x) { - failed = x; - } finally { - if (Creator.REFERENCED.contains(c) && server!=null) { - MBeanServerFactory.releaseMBeanServer(server); - } - } - if (failed == null && error != null) { - throw new Exception("Expected "+error.getName()+ - " for "+c+"("+name+")"); - } - if (error != null && !error.isInstance(failed)) - throw new Exception("Expected "+error.getName()+ - " for "+c+"("+name+"), caught "+failed); - System.out.println(""+c+"("+name+") PASSED: "+ - (failed==null?"no exception":String.valueOf(failed))); - } - - private static final Map> failures = - new LinkedHashMap>(); - private static final Map> legacy = - new LinkedHashMap>(); - private static final String[] illegalnames = { - "", "-", ":", ";", "?", "*", "wom?bat", "ran:tan.plan", - "rin;tin.tin", "tab*mow" - - }; - private static final String[] legalnames = { - "wombat", "top.tip", "ran.tan.plan", "rin.tin.tin!" - }; - private static final String[] nofailures = { - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME, "default", null - }; - static { - for (String s:illegalnames) - failures.put(s, IllegalArgumentException.class); - for (String s:nofailures) - failures.put(s, null); - legacy.putAll(failures); - for (String s:legalnames) - legacy.put(s, UnsupportedOperationException.class); - - } - - public static void test2(Map> config) - throws Exception { - for (Creator c:Creator.NAMED) { - for (String s:config.keySet()) testexception(c, s, config.get(s)); - } - } - - public static class LegacyBuilder extends MBeanServerBuilder { - - @Override - public MBeanServerDelegate newMBeanServerDelegate() { - return new MBeanServerDelegate() { - @Override - public synchronized String getMBeanServerId() { - return "gloups"; - } - }; - } - - } - public static class LegacyBuilder2 extends MBeanServerBuilder { - - @Override - public MBeanServerDelegate newMBeanServerDelegate() { - return new MBeanServerDelegate() { - @Override - public synchronized String getMBeanServerId() { - return "c'est la vie..."; - } - @Override - public synchronized void setMBeanServerName(String name) { - } - - }; - } - - } - - public static void test3(Map> config, - String builderClassName) - throws Exception { - final String builder = - System.getProperty("javax.management.builder.initial"); - System.setProperty("javax.management.builder.initial", - builderClassName); - try { - test2(config); - } finally { - if (builder != null) - System.setProperty("javax.management.builder.initial", builder); - else - System.clearProperty("javax.management.builder.initial"); - } - } - - public static void main(String[] args) throws Exception { - test(test1); - test2(failures); - test3(legacy,LegacyBuilder.class.getName()); - test3(legacy,LegacyBuilder2.class.getName()); - } -} diff --git a/test/javax/management/ObjectName/ApplyWildcardTest.java b/test/javax/management/ObjectName/ApplyWildcardTest.java index 0301636e9..b265e7bf6 100644 --- a/test/javax/management/ObjectName/ApplyWildcardTest.java +++ b/test/javax/management/ObjectName/ApplyWildcardTest.java @@ -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 @@ -28,13 +28,10 @@ * with wildcards in the key properties value part. * @author Luis-Miguel Alventosa * @run clean ApplyWildcardTest - * @compile -XDignore.symbol.file=true ApplyWildcardTest.java * @run build ApplyWildcardTest * @run main ApplyWildcardTest */ -import com.sun.jmx.mbeanserver.Repository; -import com.sun.jmx.mbeanserver.Util; import javax.management.ObjectName; public class ApplyWildcardTest { @@ -77,75 +74,6 @@ public class ApplyWildcardTest { { "d:k1=\"a?b\",k2=\"c*d\"", "d:k1=\"axb\",k2=\"cyzd\"" }, { "d:k1=\"a?b\",k2=\"c*d\",*", "d:k1=\"axb\",k2=\"cyzd\",k3=\"v3\"" }, { "d:*,k1=\"a?b\",k2=\"c*d\"", "d:k1=\"axb\",k2=\"cyzd\",k3=\"v3\"" }, - - // with namespaces - - { "*//:*", "d//:k=v" }, - { "//?:*", "///:k=v" }, - { "z*x//:*", "zaxcx//:k=v" }, - { "*//:*", "d/xx/q//:k=v" }, - { "z*x//:*", "z/a/x/c/x//:k=v" }, - { "*x?//:*", "dbdbdxk//:k=v" }, - { "z*x?x//:*", "zaxcx//:k=v" }, - { "*x?f//:*", "d/xxf/qxbf//:k=v" }, - { "z*x?c*x//:*", "z/a/x/c/x//:k=v" }, - - { "*//*:*", "d/c/v//x/vgh/:k=v" }, - { "z*x//z*x:*", "zaxcx//zaxcxcx:k=v" }, - { "//*//:*", "//d/xx/q//:k=v" }, - { "z*//*//:*", "z/x/x/z//z/a/x/c/x//:k=v" }, - { "*x?//blur?g*:*", "dbdbdxk//blurhgblurgh/x/:k=v" }, - { "z*x??x//??:*", "zaxcxccx///.:k=v" }, - { "*x?f//?:*", "d/xxf/qxbf///:k=v" }, - { "z*x?c*x//*//z????//g:*", "z/a/x/c/x//gloubs/././/zargh//g:k=v" }, - { "z*x?c*x//*//:*", "z/a/x/c/x//gloubs/././/:k=v"}, - { "*//*//:*", "aza//bzb//:k=v" }, - { "*//:*", "aza//:k=v" }, - - // with or without namespaces, * can also match nothing - { "x*z:*", "xz:k=v"}, - - { "*//:*", "//:k=v" }, - { "z*x//:*", "zx//:k=v" }, - { "*x?//:*", "xk//:k=v" }, - { "z*x?x//:*", "zxcx//:k=v" }, - { "*x?f//:*", "xbf//:k=v" }, - { "z*x?c*x//:*", "zx/cx//:k=v" }, - - { "*//*:*", "//:k=v" }, - { "z*x//z*x:*", "zx//zx:k=v" }, - { "//*//:*", "////:k=v" }, - { "z*//*//:*", "z////:k=v" }, - { "*x?//blur?g*:*", "xk//blurhg:k=v" }, - { "z*x??x//??:*", "zxccx///.:k=v" }, - { "*x?f//?:*", "xbf///:k=v" }, - { "z*x?c*x//*//z????//g:*", "zx/cx////zargh//g:k=v" }, - { "z*x?c*x//*//:*", "zx/cx////:k=v"}, - { "*//*//:*", "////:k=v" }, - { "*//:*", "//:k=v" }, - - // recursive namespace meta-wildcard - {"**//D:k=v", "a//D:k=v"}, - {"**//D:k=v", "a//b//c//D:k=v"}, - {"a//**//D:k=v", "a//b//c//D:k=v"}, - {"a//**//d//D:k=v", "a//b//c//d//D:k=v"}, - {"a//**//d//D:k=v", "a//b//c//d//d//D:k=v"}, - {"a//**//d//D:k=v", "a//a//b//c//d//d//D:k=v"}, - {"a//**//d//**//e//D:k=v", "a//a//b//d//c//d//e//D:k=v"}, - - // special cases for names ending with // - { "*:*", "d//:k=v" }, - { "z*x*:*", "zaxcx//:k=v" }, - { "*:*", "d/xx/q//:k=v" }, - { "z*x??:*", "z/a/x/c/x//:k=v" }, - { "*x???:*", "dbdbdxk//:k=v" }, - { "z*x?c*x*:*", "z/a/x/c/x//:k=v" }, - { "?/*/?:*", "d/xx/q//:k=v" }, - { "**//*:*", "a//b//jmx.rmi:k=v"}, - { "**//*:*", "a//b//jmx.rmi//:k=v"}, - { "*//*:*", "wombat//:type=Wombat" }, - { "**//*:*", "jmx.rmi//:k=v"}, - }; private static final String negativeTests[][] = { @@ -186,33 +114,6 @@ public class ApplyWildcardTest { { "d:k1=\"a?b\",k2=\"c*d\"", "d:k1=\"ab\",k2=\"cd\"" }, { "d:k1=\"a?b\",k2=\"c*d\",*", "d:k1=\"ab\",k2=\"cd\",k3=\"v3\"" }, { "d:*,k1=\"a?b\",k2=\"c*d\"", "d:k1=\"ab\",k2=\"cd\",k3=\"v3\"" }, - - // with namespaces - - { "z*x?x*:*", "zaxcx//blougs:k=v" }, - { "*x?f??rata:*", "d/xxf/qxbf//rata:k=v" }, - { "z*x?c*x*b*:*", "z/a/x/c/x//b//:k=v" }, - - { "*:*", "d/c/v//x/vgh/:k=v" }, - { "z*x??z*x:*", "zaxcx//zaxcxcx:k=v" }, - { "?/*/?:*", "//d/xx/q//:k=v" }, - { "z*/?*/?:*", "z/x/x/z//z/a/x/c/x//:k=v" }, - { "*x?/?blur?g*:*", "dbdbdxk//blurhgblurgh/x/:k=v" }, - { "z*x??x/???:*", "zaxcxccx///.:k=v" }, - { "*x?f?/?:*", "d/xxf/qxbf///:k=v" }, - { "z*x?c*x/?*z????*g:*", "z/a/x/c/x//gloubs/././/zargh//g:k=v" }, - - // recursive namespace meta-wildcard - {"**//D:k=v", "D:k=v"}, - {"b//**//D:k=v", "a//b//c//D:k=v"}, - {"a//**//D:k=v", "a//D:k=v"}, - {"a//**//d//D:k=v", "a//b//c//d//e//D:k=v"}, - {"a//**//d//D:k=v", "a//b//c//D:k=v"}, - {"a//**//d//D:k=v", "a//b//c//d//d//e//D:k=v"}, - {"a//**//d//**//e//D:k=v", "a//a//b//c//d//e//D:k=v"}, - {"a//**//d//**//e//D:k=v", "a//a//b//c//e//D:k=v"}, - { "**//*:*", "jmx.rmi:k=v"}, - }; private static int runPositiveTests() { @@ -228,8 +129,6 @@ public class ApplyWildcardTest { if (result == false) { error++; System.out.println("Test failed!"); - throw new Error("test failed for "+ - "\"" + on1 + "\".apply(\"" + on2 + "\")"); } else { System.out.println("Test passed!"); } @@ -269,85 +168,10 @@ public class ApplyWildcardTest { return error; } - private static int runRepositoryPositiveTests() { - int error = 0; - for (int i = 0; i < positiveTests.length; i++) { - try { - ObjectName on1 = ObjectName.getInstance(positiveTests[i][0]); - ObjectName on2 = ObjectName.getInstance(positiveTests[i][1]); - if (on1.isPropertyPattern()) { - if (!on1.getKeyPropertyListString().equals("")) continue; - } else if (!on1.getCanonicalKeyPropertyListString() - .equals(on2.getCanonicalKeyPropertyListString())) { - continue; - } - System.out.println("Repository Positive Match Test ---------------"); - final String dom1 = on1.getDomain(); - final String dom2 = on2.getDomain(); - System.out.println("Util.wildpathmatch(\"" + dom2 + "\",\"" + dom1 + "\")"); - boolean result = - Util.wildpathmatch(dom2,dom1); - System.out.println("Result = " + result); - if (result == false) { - error++; - System.out.println("Test failed!"); - } else { - System.out.println("Test passed!"); - } - } catch (Exception e) { - error++; - System.out.println("Got Unexpected Exception = " + e.toString()); - System.out.println("Test failed!"); - } - System.out.println("----------------------------------------------"); - } - return error; - } - - private static int runRepositoryNegativeTests() { - int error = 0; - for (int i = 0; i < negativeTests.length; i++) { - try { - ObjectName on1 = ObjectName.getInstance(negativeTests[i][0]); - ObjectName on2 = ObjectName.getInstance(negativeTests[i][1]); - if (on1.isPropertyPattern()) { - if (!on1.getKeyPropertyListString().equals("")) continue; - } else if (!on1.getCanonicalKeyPropertyListString() - .equals(on2.getCanonicalKeyPropertyListString())) { - continue; - } - System.out.println("Repository Negative Match Test ---------------"); - final String dom1 = on1.getDomain(); - final String dom2 = on2.getDomain(); - System.out.println("Util.wildpathmatch(\"" + dom2 + "\",\"" + dom1 + "\")"); - boolean result = - Util.wildpathmatch(dom2,dom1); - System.out.println("Result = " + result); - if (result == true) { - error++; - System.out.println("Test failed!"); - } else { - System.out.println("Test passed!"); - } - } catch (Exception e) { - error++; - System.out.println("Got Unexpected Exception = " + e.toString()); - System.out.println("Test failed!"); - } - System.out.println("----------------------------------------------"); - } - return error; - } - public static void main(String[] args) throws Exception { - int error = 0; - if (!(new ObjectName("z*x*:*").apply(new ObjectName("zaxcx//:k=v")))) - throw new Exception(); - - // Check null values // System.out.println("----------------------------------------------"); @@ -429,10 +253,6 @@ public class ApplyWildcardTest { error += runPositiveTests(); error += runNegativeTests(); - System.out.println("----------------------------------------------"); - error += runRepositoryPositiveTests(); - System.out.println("----------------------------------------------"); - error += runRepositoryNegativeTests(); if (error > 0) { final String msg = "Test FAILED! Got " + error + " error(s)"; diff --git a/test/javax/management/ObjectName/ValueOfTest.java b/test/javax/management/ObjectName/ValueOfTest.java deleted file mode 100644 index 4a68a3d4c..000000000 --- a/test/javax/management/ObjectName/ValueOfTest.java +++ /dev/null @@ -1,175 +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. - * - * 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. - */ - -/* - * @test - * @bug 6734813 - * @summary Test the ObjectName.valueOf methods - * @author Eamonn McManus - */ - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Hashtable; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -public class ValueOfTest { - public static void main(String[] args) throws Exception { - // Calls that should work - testPositive("d:foo=bar,baz=buh"); - testPositive("foo", "bar", "baz"); - Hashtable h = new Hashtable(); - h.put("foo", "bar"); - h.put("baz", "buh"); - testPositive("domain", h); - - // Calls that should not work - testNegative("d"); - testNegative("d:"); - testNegative("d::foo=bar"); - testNegative("d:", "foo", "bar"); - testNegative("d", "foo=", "bar"); - testNegative("d:", h); - testNegative("d", new Hashtable()); - } - - private static void testPositive(Object... args) throws Exception { - Method valueOf = valueOfMethod(args); - Method getInstance = getInstanceMethod(args); - Constructor constructor = constructor(args); - - Object valueOfValue = valueOf.invoke(null, args); - Object getInstanceValue = getInstance.invoke(null, args); - Object constructorValue = constructor.newInstance(args); - - String argString = - Arrays.toString(args).replace('[', '(').replace(']', ')'); - - if (!valueOfValue.equals(getInstanceValue)) { - throw new Exception( - "valueOf" + argString + " differs from getInstance" + - argString); - } - - if (!valueOfValue.equals(constructorValue)) { - throw new Exception( - "valueOf" + argString + " differs from new ObjectName " + - argString); - } - - System.out.println("OK: valueOf" + argString); - } - - private static void testNegative(Object... args) throws Exception { - Method valueOf = valueOfMethod(args); - Method getInstance = getInstanceMethod(args); - - String argString = - Arrays.toString(args).replace('[', '(').replace(']', ')'); - - final Throwable valueOfException; - try { - valueOf.invoke(null, args); - throw new Exception("valueOf" + argString + " did not fail but should"); - } catch (InvocationTargetException e) { - valueOfException = e.getCause(); - } - if (!(valueOfException instanceof IllegalArgumentException)) { - throw new Exception( - "valueOf" + argString + " threw " + - valueOfException.getClass().getName() + " instead of " + - "IllegalArgumentException", valueOfException); - } - - final Throwable valueOfCause = valueOfException.getCause(); - if (!(valueOfCause instanceof MalformedObjectNameException)) { - throw new Exception( - "valueOf" + argString + " threw exception with wrong " + - "type of cause", valueOfCause); - } - - if (!valueOfException.getMessage().equals(valueOfCause.getMessage())) { - // The IllegalArgumentException should have the same message as - // the MalformedObjectNameException it wraps. - // This isn't specified but is desirable. - throw new Exception( - "valueOf" + argString + ": message in wrapping " + - "IllegalArgumentException (" + valueOfException.getMessage() + - ") differs from message in wrapped " + - "MalformedObjectNameException (" + valueOfCause.getMessage() + - ")"); - } - - final Throwable getInstanceException; - try { - getInstance.invoke(null, args); - throw new Exception("getInstance" + argString + " did not fail but should"); - } catch (InvocationTargetException e) { - getInstanceException = e.getCause(); - } - if (!(getInstanceException instanceof MalformedObjectNameException)) { - throw new Exception( - "getInstance" + argString + " threw wrong exception", - getInstanceException); - } - - if (!valueOfException.getMessage().equals(getInstanceException.getMessage())) { - // Again this is not specified. - throw new Exception( - "Exception message from valueOf" + argString + " (" + - valueOfException.getMessage() + ") differs from message " + - "from getInstance" + argString + " (" + - getInstanceException.getMessage() + ")"); - } - - System.out.println("OK (correct exception): valueOf" + argString); - } - - private static Method valueOfMethod(Object[] args) throws Exception { - return method("valueOf", args); - } - - private static Method getInstanceMethod(Object[] args) throws Exception { - return method("getInstance", args); - } - - private static Method method(String name, Object[] args) throws Exception { - Class[] argTypes = argTypes(args); - return ObjectName.class.getMethod(name, argTypes); - } - - private static Constructor constructor(Object[] args) throws Exception { - Class[] argTypes = argTypes(args); - return ObjectName.class.getConstructor(argTypes); - } - - private static Class[] argTypes(Object[] args) { - Class[] argTypes = new Class[args.length]; - for (int i = 0; i < args.length; i++) - argTypes[i] = args[i].getClass(); - return argTypes; - } -} diff --git a/test/javax/management/context/ContextForwarderTest.java b/test/javax/management/context/ContextForwarderTest.java deleted file mode 100644 index d82acd3b6..000000000 --- a/test/javax/management/context/ContextForwarderTest.java +++ /dev/null @@ -1,103 +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. - * - * 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. - */ - -/* - * @test - * @bug 5072267 - * @summary Test that a context forwarder can be created and then installed. - * @author Eamonn McManus - */ - -/* The specific thing we're testing for is that the forwarder can be created - * with a null "next", and then installed with a real "next". An earlier - * defect meant that in this case the simulated jmx.context// namespace had a - * null handler that never changed. - */ - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import javax.management.ClientContext; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.MBeanServerForwarder; - -public class ContextForwarderTest { - private static String failure; - - public static void main(String[] args) throws Exception { - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); - Map env = new HashMap(); - env.put(JMXConnectorServer.CONTEXT_FORWARDER, "false"); - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( - url, env, mbs); - MBeanServerForwarder sysMBSF = cs.getSystemMBeanServerForwarder(); - MBeanServerForwarder mbsf = ClientContext.newContextForwarder(mbs, sysMBSF); - sysMBSF.setMBeanServer(mbsf); - - int localCount = mbs.getMBeanCount(); - - cs.start(); - try { - JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress()); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - mbsc = ClientContext.withContext(mbsc, "foo", "bar"); - int contextCount = mbsc.getMBeanCount(); - if (localCount + 1 != contextCount) { - fail("Local MBean count %d, context MBean count %d", - localCount, contextCount); - } - Set localNames = - new TreeSet(mbs.queryNames(null, null)); - ObjectName contextNamespaceObjectName = - new ObjectName(ClientContext.NAMESPACE + "//:type=JMXNamespace"); - if (!localNames.add(contextNamespaceObjectName)) - fail("Local names already contained context namespace handler"); - Set contextNames = mbsc.queryNames(null, null); - if (!localNames.equals(contextNames)) { - fail("Name set differs locally and in context: " + - "local: %s; context: %s", localNames, contextNames); - } - } finally { - cs.stop(); - } - if (failure != null) - throw new Exception("TEST FAILED: " + failure); - else - System.out.println("TEST PASSED"); - } - - private static void fail(String msg, Object... params) { - failure = String.format(msg, params); - System.out.println("FAIL: " + failure); - } -} diff --git a/test/javax/management/context/ContextTest.java b/test/javax/management/context/ContextTest.java deleted file mode 100644 index e943364ce..000000000 --- a/test/javax/management/context/ContextTest.java +++ /dev/null @@ -1,534 +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. - * - * 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. - */ - -/* - * @test ContextTest - * @bug 5072267 - * @summary Test client contexts. - * @author Eamonn McManus - * TODO: Try registering with a null name replaced by preRegister (for example - * from the MLet class) and see if it now works. - */ - -import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.TreeMap; -import java.util.concurrent.Callable; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.ClientContext; -import javax.management.DynamicMBean; -import javax.management.JMX; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import javax.management.loading.MLet; -import javax.management.namespace.JMXNamespace; - -import javax.management.remote.MBeanServerForwarder; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; - -public class ContextTest { - private static String failure; - private static final Map emptyContext = emptyMap(); - - public static interface ShowContextMBean { - public Map getContext(); - public Map getCreationContext(); - public Set getCalledOps(); - public String getThing(); - public void setThing(String x); - public int add(int x, int y); - } - - public static class ShowContext - extends NotificationBroadcasterSupport - implements ShowContextMBean, MBeanRegistration { - private final Map creationContext; - private final Set calledOps = new HashSet(); - - public ShowContext() { - creationContext = getContext(); - } - - public Map getContext() { - return ClientContext.getContext(); - } - - public Map getCreationContext() { - return creationContext; - } - - public Set getCalledOps() { - return calledOps; - } - - public String getThing() { - return "x"; - } - - public void setThing(String x) { - } - - public int add(int x, int y) { - return x + y; - } - - public ObjectName preRegister(MBeanServer server, ObjectName name) { - assertEquals("preRegister context", creationContext, getContext()); - calledOps.add("preRegister"); - return name; - } - - public void postRegister(Boolean registrationDone) { - assertEquals("postRegister context", creationContext, getContext()); - calledOps.add("postRegister"); - } - - // The condition checked here is not guaranteed universally true, - // but is true every time we unregister an instance of this MBean - // in this test. - public void preDeregister() throws Exception { - assertEquals("preDeregister context", creationContext, getContext()); - } - - public void postDeregister() { - assertEquals("postDeregister context", creationContext, getContext()); - } - - // Same remark as for preDeregister - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - calledOps.add("getNotificationInfo"); - return super.getNotificationInfo(); - } - - @Override - public void addNotificationListener( - NotificationListener listener, NotificationFilter filter, Object handback) { - calledOps.add("addNotificationListener"); - super.addNotificationListener(listener, filter, handback); - } - - @Override - public void removeNotificationListener( - NotificationListener listener) - throws ListenerNotFoundException { - calledOps.add("removeNL1"); - super.removeNotificationListener(listener); - } - - @Override - public void removeNotificationListener( - NotificationListener listener, NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - calledOps.add("removeNL3"); - super.removeNotificationListener(listener, filter, handback); - } - } - - private static class LogRecord { - final String op; - final Object[] params; - final Map context; - LogRecord(String op, Object[] params, Map context) { - this.op = op; - this.params = params; - this.context = context; - } - - @Override - public String toString() { - return op + Arrays.deepToString(params) + " " + context; - } - } - - /* - * InvocationHandler that forwards all methods to a contained object - * but also records each forwarded method. This allows us to check - * that the appropriate methods were called with the appropriate - * parameters. It's similar to what's typically available in - * Mock Object frameworks. - */ - private static class LogIH implements InvocationHandler { - private final Object wrapped; - Queue log = new LinkedList(); - - LogIH(Object wrapped) { - this.wrapped = wrapped; - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (method.getDeclaringClass() != Object.class) { - LogRecord lr = - new LogRecord( - method.getName(), args, ClientContext.getContext()); - log.add(lr); - } - try { - return method.invoke(wrapped, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static T newSnoop(Class wrappedClass, LogIH logIH) { - return wrappedClass.cast(Proxy.newProxyInstance( - wrappedClass.getClassLoader(), - new Class[] {wrappedClass}, - logIH)); - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - System.out.println(mbs.queryNames(null, null)); - ObjectName name = new ObjectName("a:b=c"); - mbs.registerMBean(new ShowContext(), name); - final ShowContextMBean show = - JMX.newMBeanProxy(mbs, name, ShowContextMBean.class); - - // Test local setting and getting within the MBeanServer - - assertEquals("initial context", emptyContext, show.getContext()); - ClientContext.doWithContext(singletonMap("foo", "bar"), new Callable() { - public Void call() { - assertEquals("context in doWithContext", - singletonMap("foo", "bar"), show.getContext()); - return null; - } - }); - assertEquals("initial context after doWithContext", - emptyContext, show.getContext()); - String got = ClientContext.doWithContext( - singletonMap("foo", "baz"), new Callable() { - public String call() { - return ClientContext.getContext().get("foo"); - } - }); - assertEquals("value extracted from context", "baz", got); - - Map combined = ClientContext.doWithContext( - singletonMap("foo", "baz"), new Callable>() { - public Map call() throws Exception { - return ClientContext.doWithContext( - singletonMap("fred", "jim"), - new Callable>() { - public Map call() { - return ClientContext.getContext(); - } - }); - } - }); - assertEquals("nested doWithContext context", - singletonMap("fred", "jim"), combined); - - final String ugh = "a!\u00c9//*=:\"% "; - ClientContext.doWithContext(singletonMap(ugh, ugh), new Callable() { - public Void call() { - assertEquals("context with tricky encoding", - singletonMap(ugh, ugh), show.getContext()); - return null; - } - }); - Map ughMap = new TreeMap(); - ughMap.put(ugh, ugh); - ughMap.put("fred", "jim"); - // Since this is a TreeMap and "fred" is greater than ugh (which begins - // with "a"), we will see the encoding of ugh first in the output string. - String encoded = ClientContext.encode(ughMap); - String expectedUghCoding = "a%21%C3%89%2F%2F%2A%3D%3A%22%25+"; - String expectedUghMapCoding = - ClientContext.NAMESPACE + "//" + expectedUghCoding + "=" + - expectedUghCoding + ";fred=jim"; - assertEquals("hairy context encoded as string", - expectedUghMapCoding, encoded); - - // Wrap the MBeanServer with a context MBSF so we can test withContext. - // Also check the simulated namespace directly. - - LogIH mbsIH = new LogIH(mbs); - MBeanServer snoopMBS = newSnoop(MBeanServer.class, mbsIH); - MBeanServerForwarder ctxMBS = - ClientContext.newContextForwarder(snoopMBS, null); - - // The MBSF returned by ClientContext is actually a compound of two - // forwarders, but that is supposed to be hidden by changing the - // behaviour of get/setMBeanServer. Check that it is indeed so. - assertEquals("next MBS of context forwarder", - snoopMBS, ctxMBS.getMBeanServer()); - // If the above assertion fails you may get a confusing message - // because the toString() of the two objects is likely to be the same - // so it will look as if they should be equal. - ctxMBS.setMBeanServer(null); - assertEquals("next MBS of context forwarder after setting it null", - null, ctxMBS.getMBeanServer()); - ctxMBS.setMBeanServer(snoopMBS); - - // The MBSF should look the same as the original MBeanServer except - // that it has the JMXNamespace for the simulated namespace. - - Set origNames = mbs.queryNames(null, null); - Set mbsfNames = ctxMBS.queryNames(null, null); - assertEquals("number of MBeans returned by queryNames within forwarder", - origNames.size() + 1, mbsfNames.size()); - assertEquals("MBeanCount within forwarder", - mbsfNames.size(), ctxMBS.getMBeanCount()); - assertCalled(mbsIH, "queryNames", emptyContext); - assertCalled(mbsIH, "getMBeanCount", emptyContext); - - ObjectName ctxNamespaceName = new ObjectName( - ClientContext.NAMESPACE + "//:" + JMXNamespace.TYPE_ASSIGNMENT); - origNames.add(ctxNamespaceName); - assertEquals("MBeans within forwarder", origNames, mbsfNames); - Set domains = new HashSet(Arrays.asList(ctxMBS.getDomains())); - assertEquals("domains include context namespace MBean", - true, domains.contains(ClientContext.NAMESPACE + "//")); - assertCalled(mbsIH, "getDomains", emptyContext); - - // Now test ClientContext.withContext. - - MBeanServer ughMBS = ClientContext.withContext(ctxMBS, ugh, ugh); - - ShowContextMBean ughshow = - JMX.newMBeanProxy(ughMBS, name, ShowContextMBean.class); - Map ughCtx = ughshow.getContext(); - Map ughExpect = singletonMap(ugh, ugh); - assertEquals("context seen by MBean accessed within namespace", - ughExpect, ughCtx); - assertCalled(mbsIH, "getAttribute", ughExpect, name, "Context"); - - MBeanServer cmbs = ClientContext.withContext( - ctxMBS, "mickey", "mouse"); - ShowContextMBean cshow = - JMX.newMBeanProxy(cmbs, name, ShowContextMBean.class); - assertEquals("context seen by MBean accessed within namespace", - singletonMap("mickey", "mouse"), cshow.getContext()); - - MBeanServer ccmbs = ClientContext.withContext( - cmbs, "donald", "duck"); - ShowContextMBean ccshow = - JMX.newMBeanProxy(ccmbs, name, ShowContextMBean.class); - Map disney = new HashMap(); - disney.put("mickey", "mouse"); - disney.put("donald", "duck"); - assertEquals("context seen by MBean in nested namespace", - disney, ccshow.getContext()); - - // Test that all MBS ops produce reasonable results - - ObjectName logger = new ObjectName("a:type=Logger"); - DynamicMBean showMBean = - new StandardMBean(new ShowContext(), ShowContextMBean.class); - LogIH mbeanLogIH = new LogIH(showMBean); - DynamicMBean logMBean = newSnoop(DynamicMBean.class, mbeanLogIH); - ObjectInstance loggerOI = ccmbs.registerMBean(logMBean, logger); - assertEquals("ObjectName returned by createMBean", - logger, loggerOI.getObjectName()); - - // We get an getMBeanInfo call to determine the className in the - // ObjectInstance to return from registerMBean. - assertCalled(mbeanLogIH, "getMBeanInfo", disney); - - ccmbs.getAttribute(logger, "Thing"); - assertCalled(mbeanLogIH, "getAttribute", disney); - - ccmbs.getAttributes(logger, new String[] {"Thing", "Context"}); - assertCalled(mbeanLogIH, "getAttributes", disney); - - ccmbs.setAttribute(logger, new Attribute("Thing", "bar")); - assertCalled(mbeanLogIH, "setAttribute", disney); - - ccmbs.setAttributes(logger, new AttributeList( - Arrays.asList(new Attribute("Thing", "baz")))); - assertCalled(mbeanLogIH, "setAttributes", disney); - - ccmbs.getMBeanInfo(logger); - assertCalled(mbeanLogIH, "getMBeanInfo", disney); - - Set names = ccmbs.queryNames(null, null); - Set expectedNames = new HashSet( - Collections.singleton(MBeanServerDelegate.DELEGATE_NAME)); - assertEquals("context namespace query includes expected names", - true, names.containsAll(expectedNames)); - - Set nsNames = ccmbs.queryNames(new ObjectName("*//:*"), null); - Set expectedNsNames = new HashSet( - Arrays.asList( - new ObjectName(ClientContext.NAMESPACE + - ObjectName.NAMESPACE_SEPARATOR + ":" + - JMXNamespace.TYPE_ASSIGNMENT))); - assertEquals("context namespace query includes namespace MBean", - true, nsNames.containsAll(expectedNsNames)); - - - - Set insts = ccmbs.queryMBeans( - MBeanServerDelegate.DELEGATE_NAME, null); - assertEquals("size of set from MBeanServerDelegate query", 1, insts.size()); - assertEquals("ObjectName from MBeanServerDelegate query", - MBeanServerDelegate.DELEGATE_NAME, - insts.iterator().next().getObjectName()); - - ObjectName createdName = new ObjectName("a:type=Created"); - ObjectInstance createdOI = - ccmbs.createMBean(ShowContext.class.getName(), createdName); - assertEquals("class name from createMBean", - ShowContext.class.getName(), createdOI.getClassName()); - assertEquals("ObjectName from createMBean", - createdName, createdOI.getObjectName()); - assertEquals("context within createMBean", - disney, ccmbs.getAttribute(createdName, "CreationContext")); - - NotificationListener nothingListener = new NotificationListener() { - public void handleNotification(Notification n, Object h) {} - }; - ccmbs.addNotificationListener(createdName, nothingListener, null, null); - ccmbs.removeNotificationListener(createdName, nothingListener, null, null); - ccmbs.addNotificationListener(createdName, nothingListener, null, null); - ccmbs.removeNotificationListener(createdName, nothingListener); - Set expectedOps = new HashSet(Arrays.asList( - "preRegister", "postRegister", "addNotificationListener", - "removeNL1", "removeNL3", "getNotificationInfo")); - assertEquals("operations called on MBean", - expectedOps, ccmbs.getAttribute(createdName, "CalledOps")); - - assertEquals("ClassLoader for MBean", - ShowContext.class.getClassLoader(), - ccmbs.getClassLoaderFor(createdName)); - - assertEquals("isRegistered", true, ccmbs.isRegistered(createdName)); - assertEquals("isInstanceOf", true, ccmbs.isInstanceOf(createdName, - ShowContext.class.getName())); - assertEquals("isInstanceOf", false, ccmbs.isInstanceOf(createdName, - DynamicMBean.class.getName())); - ccmbs.unregisterMBean(createdName); - assertEquals("isRegistered after unregister", - false, ccmbs.isRegistered(createdName)); - - MLet mlet = new MLet(); - ObjectName defaultMLetName = new ObjectName("DefaultDomain:type=MLet"); - - ccmbs.registerMBean(mlet, defaultMLetName); - - assertEquals("getClassLoader", mlet, ccmbs.getClassLoader(defaultMLetName)); - - assertEquals("number of MBean operations", 0, mbeanLogIH.log.size()); - - // Test that contexts still work when we can't combine two encoded contexts. - // Here, we wrap cmbs (mickey=mouse) so that ccmbs2 (donald=duck) cannot - // see that it already contains a context and therefore cannot combine - // into mickey=mouse;donald=duck. We don't actually use the snoop - // capabilities of the returned object -- we just want an opaque - // MBeanServer wrapper - MBeanServer cmbs2 = newSnoop(MBeanServer.class, new LogIH(cmbs)); - MBeanServer ccmbs2 = ClientContext.withContext(cmbs2, "donald", "duck"); - assertEquals("context when combination is impossible", - disney, ccmbs2.getAttribute(name, "Context")); - - // Test failure cases of ClientContext.encode - final List> badEncodeArgs = - Arrays.asList( - null, - Collections.singletonMap(null, "foo"), - Collections.singletonMap("foo", null)); - for (Map bad : badEncodeArgs) { - try { - String oops = ClientContext.encode(bad); - failed("ClientContext.encode(" + bad + ") should have failed: " - + oops); - } catch (Exception e) { - assertEquals("Exception for ClientContext.encode(" + bad + ")", - IllegalArgumentException.class, e.getClass()); - } - } - - // ADD NEW TESTS HERE ^^^ - - if (failure != null) - throw new Exception(failure); - } - - private static void assertEquals(String what, Object x, Object y) { - if (!equal(x, y)) - failed(what + ": expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - private static void assertCalled( - LogIH logIH, String op, Map expectedContext) { - assertCalled(logIH, op, expectedContext, (Object[]) null); - } - - private static void assertCalled( - LogIH logIH, String op, Map expectedContext, - Object... params) { - LogRecord lr = logIH.log.remove(); - assertEquals("called operation", op, lr.op); - if (params != null) - assertEquals("operation parameters", params, lr.params); - assertEquals("operation context", expectedContext, lr.context); - } - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } -} diff --git a/test/javax/management/context/LocaleAwareBroadcasterTest.java b/test/javax/management/context/LocaleAwareBroadcasterTest.java deleted file mode 100644 index 7963f9f33..000000000 --- a/test/javax/management/context/LocaleAwareBroadcasterTest.java +++ /dev/null @@ -1,328 +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. - * - * 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. - */ - -/* - * @test - * @bug 5072267 - * @summary Test that an MBean can handle localized Notification messages. - * @author Eamonn McManus - */ - -import java.util.Collections; -import java.util.ListResourceBundle; -import java.util.Locale; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.ResourceBundle; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import javax.management.ClientContext; -import javax.management.JMX; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.SendNotification; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class LocaleAwareBroadcasterTest { - static final ObjectName mbeanName = ObjectName.valueOf("d:type=LocaleAware"); - - static final String - messageKey = "broken.window", - defaultMessage = "broken window", - frenchMessage = "fen\u00eatre bris\u00e9e", - irishMessage = "fuinneog briste"; - - public static class Bundle extends ListResourceBundle { - @Override - protected Object[][] getContents() { - return new Object[][] { - {messageKey, defaultMessage}, - }; - } - } - - public static class Bundle_fr extends ListResourceBundle { - @Override - protected Object[][] getContents() { - return new Object[][] { - {messageKey, frenchMessage}, - }; - } - } - - public static class Bundle_ga extends ListResourceBundle { - @Override - protected Object[][] getContents() { - return new Object[][] { - {messageKey, irishMessage}, - }; - } - } - - static volatile String failure; - - public static interface LocaleAwareMBean { - public void sendNotification(Notification n); - } - - public static class LocaleAware - implements LocaleAwareMBean, NotificationEmitter, SendNotification { - - private final ConcurrentMap - localeToEmitter = newConcurrentMap(); - - public void sendNotification(Notification n) { - for (Map.Entry entry : - localeToEmitter.entrySet()) { - Notification localizedNotif = - localizeNotification(n, entry.getKey()); - entry.getValue().sendNotification(localizedNotif); - } - } - - public void addNotificationListener( - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws IllegalArgumentException { - Locale locale = ClientContext.getLocale(); - NotificationBroadcasterSupport broadcaster; - broadcaster = localeToEmitter.get(locale); - if (broadcaster == null) { - broadcaster = new NotificationBroadcasterSupport(); - NotificationBroadcasterSupport old = - localeToEmitter.putIfAbsent(locale, broadcaster); - if (old != null) - broadcaster = old; - } - broadcaster.addNotificationListener(listener, filter, handback); - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - Locale locale = ClientContext.getLocale(); - NotificationBroadcasterSupport broadcaster = - localeToEmitter.get(locale); - if (broadcaster == null) - throw new ListenerNotFoundException(); - broadcaster.removeNotificationListener(listener); - } - - public void removeNotificationListener( - NotificationListener listener, - NotificationFilter filter, - Object handback) - throws ListenerNotFoundException { - Locale locale = ClientContext.getLocale(); - NotificationBroadcasterSupport broadcaster = - localeToEmitter.get(locale); - if (broadcaster == null) - throw new ListenerNotFoundException(); - broadcaster.removeNotificationListener(listener, filter, handback); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[0]; - } - } - - // Localize notif using the convention that the message looks like - // [resourcebundlename:resourcekey]defaultmessage - // for example [foo.bar.Resources:unknown.problem] - static Notification localizeNotification(Notification n, Locale locale) { - String msg = n.getMessage(); - if (!msg.startsWith("[")) - return n; - int close = msg.indexOf(']'); - if (close < 0) - throw new IllegalArgumentException("Bad notification message: " + msg); - int colon = msg.indexOf(':'); - if (colon < 0 || colon > close) - throw new IllegalArgumentException("Bad notification message: " + msg); - String bundleName = msg.substring(1, colon); - String key = msg.substring(colon + 1, close); - ClassLoader loader = LocaleAwareBroadcasterTest.class.getClassLoader(); - ResourceBundle bundle = - ResourceBundle.getBundle(bundleName, locale, loader); - try { - msg = bundle.getString(key); - } catch (MissingResourceException e) { - msg = msg.substring(close + 1); - } - n = (Notification) n.clone(); - n.setMessage(msg); - return n; - } - - public static void main(String[] args) throws Exception { - Locale.setDefault(new Locale("en")); - testLocal(); - testRemote(); - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - static interface AddListenerInLocale { - public void addListenerInLocale( - MBeanServerConnection mbsc, - NotificationListener listener, - Locale locale) throws Exception; - } - - private static void testLocal() throws Exception { - System.out.println("Test local MBeanServer using doWithContext"); - MBeanServer mbs = makeMBS(); - AddListenerInLocale addListener = new AddListenerInLocale() { - public void addListenerInLocale( - final MBeanServerConnection mbsc, - final NotificationListener listener, - Locale locale) throws Exception { - Map localeContext = Collections.singletonMap( - ClientContext.LOCALE_KEY, locale.toString()); - ClientContext.doWithContext( - localeContext, new Callable() { - public Void call() throws Exception { - mbsc.addNotificationListener( - mbeanName, listener, null, null); - return null; - } - }); - } - }; - test(mbs, addListener); - } - - private static void testRemote() throws Exception { - System.out.println("Test remote MBeanServer using withLocale"); - MBeanServer mbs = makeMBS(); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); - JMXConnectorServer cs = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); - cs.start(); - JMXServiceURL addr = cs.getAddress(); - JMXConnector cc = JMXConnectorFactory.connect(addr); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - AddListenerInLocale addListenerInLocale = new AddListenerInLocale() { - public void addListenerInLocale( - MBeanServerConnection mbsc, - NotificationListener listener, - Locale locale) throws Exception { - mbsc = ClientContext.withLocale(mbsc, locale); - mbsc.addNotificationListener(mbeanName, listener, null, null); - } - }; - try { - test(mbsc, addListenerInLocale); - } finally { - try { - cc.close(); - } catch (Exception e) {} - cs.stop(); - } - } - - static class QueueListener implements NotificationListener { - final BlockingQueue queue = - new ArrayBlockingQueue(10); - - public void handleNotification(Notification notification, - Object handback) { - queue.add(notification); - } - } - - private static void test( - MBeanServerConnection mbsc, AddListenerInLocale addListener) - throws Exception { - QueueListener defaultListener = new QueueListener(); - QueueListener frenchListener = new QueueListener(); - QueueListener irishListener = new QueueListener(); - mbsc.addNotificationListener(mbeanName, defaultListener, null, null); - addListener.addListenerInLocale(mbsc, frenchListener, new Locale("fr")); - addListener.addListenerInLocale(mbsc, irishListener, new Locale("ga")); - - LocaleAwareMBean proxy = - JMX.newMBeanProxy(mbsc, mbeanName, LocaleAwareMBean.class); - String notifMsg = "[" + Bundle.class.getName() + ":" + messageKey + "]" + - "broken window (default message that should never be seen)"; - Notification notif = new Notification( - "notif.type", mbeanName, 0L, notifMsg); - proxy.sendNotification(notif); - - final Object[][] expected = { - {defaultListener, defaultMessage}, - {frenchListener, frenchMessage}, - {irishListener, irishMessage}, - }; - for (Object[] exp : expected) { - QueueListener ql = (QueueListener) exp[0]; - String msg = (String) exp[1]; - System.out.println("Checking: " + msg); - Notification n = ql.queue.poll(1, TimeUnit.SECONDS); - if (n == null) - fail("Did not receive expected notif: " + msg); - if (!n.getMessage().equals(msg)) { - fail("Received notif with wrong message: got " + - n.getMessage() + ", expected " + msg); - } - n = ql.queue.poll(2, TimeUnit.MILLISECONDS); - if (n != null) - fail("Received unexpected extra notif: " + n); - } - } - - private static MBeanServer makeMBS() throws Exception { - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - LocaleAware aware = new LocaleAware(); - mbs.registerMBean(aware, mbeanName); - return mbs; - } - - static ConcurrentMap newConcurrentMap() { - return new ConcurrentHashMap(); - } - - static void fail(String why) { - System.out.println("FAIL: " + why); - failure = why; - } -} diff --git a/test/javax/management/context/LocaleTest.java b/test/javax/management/context/LocaleTest.java deleted file mode 100644 index 023c0c7df..000000000 --- a/test/javax/management/context/LocaleTest.java +++ /dev/null @@ -1,140 +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. - * - * 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. - */ - -/* - * @test LocaleTest.java - * @bug 5072267 - * @summary Test client locales. - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import java.util.Collections; -import java.util.ListResourceBundle; -import java.util.Locale; -import java.util.Map; -import java.util.ResourceBundle; -import java.util.concurrent.Callable; -import javax.management.ClientContext; -import java.util.Arrays; -import javax.management.MBeanServer; -import javax.management.ObjectName; - -public class LocaleTest { - private static String failure; - - public static void main(String[] args) throws Exception { - - // Test the translation String -> Locale - - Locale[] locales = Locale.getAvailableLocales(); - System.out.println("Testing String->Locale for " + locales.length + - " locales"); - for (Locale loc : locales) { - Map ctx = Collections.singletonMap( - ClientContext.LOCALE_KEY, loc.toString()); - Locale loc2 = ClientContext.doWithContext( - ctx, new Callable() { - public Locale call() { - return ClientContext.getLocale(); - } - }); - assertEquals(loc, loc2); - } - - // Test that a locale-sensitive attribute works - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - mbs = ClientContext.newContextForwarder(mbs, null); - ObjectName name = new ObjectName("a:type=LocaleSensitive"); - mbs.registerMBean(new LocaleSensitive(), name); - Locale.setDefault(Locale.US); - - assertEquals("spectacular failure", - mbs.getAttribute(name, "LastProblemDescription")); - - MBeanServer frmbs = ClientContext.withContext( - mbs, ClientContext.LOCALE_KEY, Locale.FRANCE.toString()); - assertEquals("\u00e9chec r\u00e9tentissant", - frmbs.getAttribute(name, "LastProblemDescription")); - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - public static interface LocaleSensitiveMBean { - public String getLastProblemDescription(); - } - - public static class LocaleSensitive implements LocaleSensitiveMBean { - public String getLastProblemDescription() { - Locale loc = ClientContext.getLocale(); - ResourceBundle rb = ResourceBundle.getBundle( - MyResources.class.getName(), loc); - return rb.getString("spectacular"); - } - } - - public static class MyResources extends ListResourceBundle { - protected Object[][] getContents() { - return new Object[][] { - {"spectacular", "spectacular failure"}, - }; - } - } - - public static class MyResources_fr extends ListResourceBundle { - protected Object[][] getContents() { - return new Object[][] { - {"spectacular", "\u00e9chec r\u00e9tentissant"}, - }; - } - } - - private static void assertEquals(Object x, Object y) { - if (!equal(x, y)) - failed("expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } -} diff --git a/test/javax/management/context/LocalizableTest.java b/test/javax/management/context/LocalizableTest.java deleted file mode 100644 index 43f736e49..000000000 --- a/test/javax/management/context/LocalizableTest.java +++ /dev/null @@ -1,192 +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. - * - * 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. - */ - -/* - * @test LocalizableTest - * @bug 5072267 6635499 - * @summary Test localizable MBeanInfo using LocalizableMBeanFactory. - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import java.util.Locale; -import java.util.ResourceBundle; -import javax.management.ClientContext; -import javax.management.Description; -import javax.management.JMX; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.MBeanServer; -import javax.management.ObjectName; - -import localizable.MBeanDescriptions_fr; -import localizable.Whatsit; - -import static localizable.WhatsitMBean.*; - -public class LocalizableTest { - // If you change the order of the array elements or their number then - // you must also change these constants. - private static final int - MBEAN = 0, ATTR = 1, OPER = 2, PARAM = 3, CONSTR = 4, - CONSTR_PARAM = 5; - private static final String[] englishDescriptions = { - englishMBeanDescription, englishAttrDescription, englishOperDescription, - englishParamDescription, englishConstrDescription, - englishConstrParamDescription, - }; - private static final String[] defaultDescriptions = englishDescriptions.clone(); - static { - defaultDescriptions[MBEAN] = defaultMBeanDescription; - } - private static final String[] frenchDescriptions = { - frenchMBeanDescription, frenchAttrDescription, frenchOperDescription, - frenchParamDescription, frenchConstrDescription, - frenchConstrParamDescription, - }; - - private static String failure; - - @Description(unlocalizedMBeanDescription) - public static interface UnlocalizedMBean {} - public static class Unlocalized implements UnlocalizedMBean {} - - public static void main(String[] args) throws Exception { - ResourceBundle frenchBundle = new MBeanDescriptions_fr(); - // The purpose of the previous line is to force that class to be compiled - // when the test is run so it will be available for reflection. - // Yes, we could do this with a @build tag. - - MBeanServer plainMBS = ManagementFactory.getPlatformMBeanServer(); - MBeanServer unlocalizedMBS = - ClientContext.newContextForwarder(plainMBS, null); - MBeanServer localizedMBS = - ClientContext.newLocalizeMBeanInfoForwarder(plainMBS); - localizedMBS = ClientContext.newContextForwarder(localizedMBS, null); - ObjectName name = new ObjectName("a:b=c"); - - Whatsit whatsit = new Whatsit(); - Object[][] locales = { - {null, englishDescriptions}, - {"en", englishDescriptions}, - {"fr", frenchDescriptions}, - }; - - for (Object[] localePair : locales) { - String locale = (String) localePair[0]; - String[] localizedDescriptions = (String[]) localePair[1]; - System.out.println("===Testing locale " + locale + "==="); - for (boolean localized : new boolean[] {false, true}) { - String[] descriptions = localized ? - localizedDescriptions : defaultDescriptions; - MBeanServer mbs = localized ? localizedMBS : unlocalizedMBS; - System.out.println("Testing MBean " + whatsit + " with " + - "localized=" + localized); - mbs.registerMBean(whatsit, name); - System.out.println(mbs.getMBeanInfo(name)); - try { - test(mbs, name, locale, descriptions); - } catch (Exception e) { - fail("Caught exception: " + e); - } finally { - mbs.unregisterMBean(name); - } - } - } - - System.out.println("===Testing unlocalizable MBean==="); - Object mbean = new Unlocalized(); - localizedMBS.registerMBean(mbean, name); - try { - MBeanInfo mbi = localizedMBS.getMBeanInfo(name); - assertEquals("MBean description", unlocalizedMBeanDescription, - mbi.getDescription()); - } finally { - localizedMBS.unregisterMBean(name); - } - - System.out.println("===Testing MBeanInfo.localizeDescriptions==="); - plainMBS.registerMBean(whatsit, name); - MBeanInfo mbi = plainMBS.getMBeanInfo(name); - Locale french = new Locale("fr"); - mbi = mbi.localizeDescriptions(french, whatsit.getClass().getClassLoader()); - checkDescriptions(mbi, frenchDescriptions); - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: Last failure: " + failure); - } - - private static void test(MBeanServer mbs, ObjectName name, String locale, - String[] expectedDescriptions) - throws Exception { - if (locale != null) - mbs = ClientContext.withLocale(mbs, new Locale(locale)); - MBeanInfo mbi = mbs.getMBeanInfo(name); - checkDescriptions(mbi, expectedDescriptions); - } - - private static void checkDescriptions(MBeanInfo mbi, - String[] expectedDescriptions) { - assertEquals("MBean description", - expectedDescriptions[MBEAN], mbi.getDescription()); - MBeanAttributeInfo mbai = mbi.getAttributes()[0]; - assertEquals("Attribute description", - expectedDescriptions[ATTR], mbai.getDescription()); - MBeanOperationInfo mboi = mbi.getOperations()[0]; - assertEquals("Operation description", - expectedDescriptions[OPER], mboi.getDescription()); - MBeanParameterInfo mbpi = mboi.getSignature()[0]; - assertEquals("Parameter description", - expectedDescriptions[PARAM], mbpi.getDescription()); - MBeanConstructorInfo[] mbcis = mbi.getConstructors(); - assertEquals("Number of constructors", 2, mbcis.length); - for (MBeanConstructorInfo mbci : mbcis) { - MBeanParameterInfo[] mbcpis = mbci.getSignature(); - String constrName = mbcpis.length + "-arg constructor"; - assertEquals(constrName + " description", - expectedDescriptions[CONSTR], mbci.getDescription()); - if (mbcpis.length > 0) { - assertEquals(constrName + " parameter description", - expectedDescriptions[CONSTR_PARAM], - mbcpis[0].getDescription()); - } - } - } - - private static void assertEquals(String what, Object expect, Object actual) { - if (expect.equals(actual)) - System.out.println("...OK: " + what + " = " + expect); - else - fail(what + " should be " + expect + ", was " + actual); - } - - private static void fail(String why) { - System.out.println("FAIL: " + why); - failure = why; - } -} diff --git a/test/javax/management/context/RemoteContextTest.java b/test/javax/management/context/RemoteContextTest.java deleted file mode 100644 index 56c7eab6c..000000000 --- a/test/javax/management/context/RemoteContextTest.java +++ /dev/null @@ -1,496 +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. - * - * 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. - */ - -/* - * @test RemoteContextTest.java - * @bug 5072267 - * @summary Test client contexts with namespaces. - * @author Eamonn McManus, Daniel Fuchs - */ - -import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Map; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.Callable; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.ClientContext; -import javax.management.DynamicMBean; -import javax.management.JMX; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerDelegate; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import javax.management.loading.MLet; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.namespace.JMXNamespace; - -import static java.util.Collections.singletonMap; -import javax.management.MBeanServerFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class RemoteContextTest { - private static String failure; - - public static interface ShowContextMBean { - public Map getContext(); - public Map getCreationContext(); - public Set getCalledOps(); - public String getThing(); - public void setThing(String x); - public int add(int x, int y); - } - - public static class ShowContext - extends NotificationBroadcasterSupport - implements ShowContextMBean, MBeanRegistration { - private final Map creationContext; - private final Set calledOps = new HashSet(); - - public ShowContext() { - creationContext = getContext(); - } - - public Map getContext() { - return ClientContext.getContext(); - } - - public Map getCreationContext() { - return creationContext; - } - - public Set getCalledOps() { - return calledOps; - } - - public String getThing() { - return "x"; - } - - public void setThing(String x) { - } - - public int add(int x, int y) { - return x + y; - } - - public ObjectName preRegister(MBeanServer server, ObjectName name) { - assertEquals(creationContext, getContext()); - calledOps.add("preRegister"); - return name; - } - - public void postRegister(Boolean registrationDone) { - assertEquals(creationContext, getContext()); - calledOps.add("postRegister"); - } - - // The condition checked here is not guaranteed universally true, - // but is true every time we unregister an instance of this MBean - // in this test. - public void preDeregister() throws Exception { - assertEquals(creationContext, getContext()); - } - - public void postDeregister() { - assertEquals(creationContext, getContext()); - } - - // Same remark as for preDeregister - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - calledOps.add("getNotificationInfo"); - return super.getNotificationInfo(); - } - - @Override - public void addNotificationListener( - NotificationListener listener, NotificationFilter filter, Object handback) { - calledOps.add("addNotificationListener"); - super.addNotificationListener(listener, filter, handback); - } - - @Override - public void removeNotificationListener( - NotificationListener listener) - throws ListenerNotFoundException { - calledOps.add("removeNL1"); - super.removeNotificationListener(listener); - } - - @Override - public void removeNotificationListener( - NotificationListener listener, NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - calledOps.add("removeNL3"); - super.removeNotificationListener(listener, filter, handback); - } - } - - private static class LogRecord { - final String op; - final Object[] params; - final Map context; - LogRecord(String op, Object[] params, Map context) { - this.op = op; - this.params = params; - this.context = context; - } - - @Override - public String toString() { - return op + Arrays.deepToString(params) + " " + context; - } - } - - private static class LogIH implements InvocationHandler { - private final Object wrapped; - Queue log = new LinkedList(); - - LogIH(Object wrapped) { - this.wrapped = wrapped; - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (method.getDeclaringClass() != Object.class) { - LogRecord lr = - new LogRecord( - method.getName(), args, ClientContext.getContext()); - log.add(lr); - } - try { - return method.invoke(wrapped, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static T newSnoop(Class wrappedClass, LogIH logIH) { - return wrappedClass.cast(Proxy.newProxyInstance( - wrappedClass.getClassLoader(), - new Class[] {wrappedClass}, - logIH)); - } - - public static void main(String[] args) throws Exception { - final String subnamespace = "sub"; - final ObjectName locname = new ObjectName("a:b=c"); - final ObjectName name = JMXNamespaces.insertPath(subnamespace,locname); - final MBeanServer mbs = ClientContext.newContextForwarder( - ManagementFactory.getPlatformMBeanServer(), null); - final MBeanServer sub = ClientContext.newContextForwarder( - MBeanServerFactory.newMBeanServer(), null); - final JMXServiceURL anonym = new JMXServiceURL("rmi",null,0); - final Map env = Collections.emptyMap(); - final Map emptyContext = Collections.emptyMap(); - final JMXConnectorServer srv = - JMXConnectorServerFactory.newJMXConnectorServer(anonym,env,sub); - sub.registerMBean(new ShowContext(), locname); - - srv.start(); - - try { - JMXRemoteNamespace subns = JMXRemoteNamespace. - newJMXRemoteNamespace(srv.getAddress(),null); - mbs.registerMBean(subns, JMXNamespaces.getNamespaceObjectName("sub")); - mbs.invoke(JMXNamespaces.getNamespaceObjectName("sub"), - "connect", null,null); - final ShowContextMBean show = - JMX.newMBeanProxy(mbs, name, ShowContextMBean.class); - - assertEquals(emptyContext, show.getContext()); - ClientContext.doWithContext(singletonMap("foo", "bar"), new Callable() { - public Void call() { - assertEquals(singletonMap("foo", "bar"), show.getContext()); - return null; - } - }); - assertEquals(emptyContext, show.getContext()); - String got = ClientContext.doWithContext( - singletonMap("foo", "baz"), new Callable() { - public String call() { - return ClientContext.getContext().get("foo"); - } - }); - assertEquals("baz", got); - - Map combined = ClientContext.doWithContext( - singletonMap("foo", "baz"), new Callable>() { - public Map call() throws Exception { - return ClientContext.doWithContext( - singletonMap("fred", "jim"), - new Callable>() { - public Map call() { - return ClientContext.getContext(); - } - }); - } - }); - assertEquals(singletonMap("fred", "jim"), combined); - - final String ugh = "a!?//*=:\"% "; - ClientContext.doWithContext(singletonMap(ugh, ugh), new Callable() { - public Void call() { - assertEquals(Collections.singletonMap(ugh, ugh), - ClientContext.getContext()); - return null; - } - }); - - // Basic withContext tests - - LogIH mbsIH = new LogIH(mbs); - MBeanServer snoopMBS = newSnoop(MBeanServer.class, mbsIH); - MBeanServer ughMBS = ClientContext.withContext(snoopMBS, ugh, ugh); - // ughMBS is never referenced but we check that the withContext call - // included a call to snoopMBS.isRegistered. - String encodedUgh = URLEncoder.encode(ugh, "UTF-8").replace("*", "%2A"); - ObjectName expectedName = new ObjectName( - ClientContext.NAMESPACE + ObjectName.NAMESPACE_SEPARATOR + - encodedUgh + "=" + encodedUgh + - ObjectName.NAMESPACE_SEPARATOR + ":" + - JMXNamespace.TYPE_ASSIGNMENT); - assertCalled(mbsIH, "isRegistered", new Object[] {expectedName}, - emptyContext); - - // Test withDynamicContext - - MBeanServerConnection dynamicSnoop = - ClientContext.withDynamicContext(snoopMBS); - assertCalled(mbsIH, "isRegistered", - new Object[] { - JMXNamespaces.getNamespaceObjectName(ClientContext.NAMESPACE) - }, - emptyContext); - final ShowContextMBean dynamicShow = - JMX.newMBeanProxy(dynamicSnoop, name, ShowContextMBean.class); - assertEquals(Collections.emptyMap(), dynamicShow.getContext()); - assertCalled(mbsIH, "getAttribute", new Object[] {name, "Context"}, - emptyContext); - - Map expectedDynamic = - Collections.singletonMap("gladstone", "gander"); - Map dynamic = ClientContext.doWithContext( - expectedDynamic, - new Callable>() { - public Map call() throws Exception { - return dynamicShow.getContext(); - } - }); - assertEquals(expectedDynamic, dynamic); - ObjectName expectedDynamicName = new ObjectName( - ClientContext.encode(expectedDynamic) + - ObjectName.NAMESPACE_SEPARATOR + name); - assertCalled(mbsIH, "getAttribute", - new Object[] {expectedDynamicName, "Context"}, dynamic); - - MBeanServer cmbs = ClientContext.withContext( - mbs, "mickey", "mouse"); - ShowContextMBean cshow = - JMX.newMBeanProxy(cmbs, name, ShowContextMBean.class); - assertEquals(Collections.singletonMap("mickey", "mouse"), cshow.getContext()); - - MBeanServer ccmbs = ClientContext.withContext( - cmbs, "donald", "duck"); - ShowContextMBean ccshow = - JMX.newMBeanProxy(ccmbs, name, ShowContextMBean.class); - Map disney = new HashMap(); - disney.put("mickey", "mouse"); - disney.put("donald", "duck"); - assertEquals(disney, ccshow.getContext()); - - // Test that all MBS ops produce reasonable results - - ObjectName logger = new ObjectName("a:type=Logger"); - DynamicMBean showMBean = - new StandardMBean(new ShowContext(), ShowContextMBean.class); - LogIH mbeanLogIH = new LogIH(showMBean); - DynamicMBean logMBean = newSnoop(DynamicMBean.class, mbeanLogIH); - ObjectInstance loggerOI = ccmbs.registerMBean(logMBean, logger); - assertEquals(logger, loggerOI.getObjectName()); - - // We get a getMBeanInfo call to determine the className in the - // ObjectInstance to return from registerMBean. - assertCalled(mbeanLogIH, "getMBeanInfo", disney); - - ccmbs.getAttribute(logger, "Thing"); - assertCalled(mbeanLogIH, "getAttribute", disney); - - ccmbs.getAttributes(logger, new String[] {"Thing", "Context"}); - assertCalled(mbeanLogIH, "getAttributes", disney); - - ccmbs.setAttribute(logger, new Attribute("Thing", "bar")); - assertCalled(mbeanLogIH, "setAttribute", disney); - - ccmbs.setAttributes(logger, new AttributeList( - Arrays.asList(new Attribute("Thing", "baz")))); - assertCalled(mbeanLogIH, "setAttributes", disney); - - ccmbs.getMBeanInfo(logger); - assertCalled(mbeanLogIH, "getMBeanInfo", disney); - - Set names = ccmbs.queryNames(null, null); - Set expectedNames = new HashSet( - Collections.singleton(MBeanServerDelegate.DELEGATE_NAME)); - expectedNames.removeAll(names); - assertEquals(0, expectedNames.size()); - - Set nsNames = - ccmbs.queryNames(new ObjectName("**?*?//:*"), null); - Set expectedNsNames = new HashSet( - Arrays.asList( - new ObjectName(ClientContext.NAMESPACE + - ObjectName.NAMESPACE_SEPARATOR + ":" + - JMXNamespace.TYPE_ASSIGNMENT))); - expectedNsNames.removeAll(nsNames); - assertEquals(0, expectedNsNames.size()); - - Set insts = ccmbs.queryMBeans( - MBeanServerDelegate.DELEGATE_NAME, null); - assertEquals(1, insts.size()); - assertEquals(MBeanServerDelegate.DELEGATE_NAME, - insts.iterator().next().getObjectName()); - - ObjectName createdName = new ObjectName("a:type=Created"); - ObjectInstance createdOI = - ccmbs.createMBean(ShowContext.class.getName(), createdName); - assertEquals(ShowContext.class.getName(), createdOI.getClassName()); - assertEquals(createdName, createdOI.getObjectName()); - assertEquals(disney, ccmbs.getAttribute(createdName, "CreationContext")); - - NotificationListener nothingListener = new NotificationListener() { - public void handleNotification(Notification n, Object h) {} - }; - ccmbs.addNotificationListener(createdName, nothingListener, null, null); - ccmbs.removeNotificationListener(createdName, nothingListener, null, null); - ccmbs.addNotificationListener(createdName, nothingListener, null, null); - ccmbs.removeNotificationListener(createdName, nothingListener); - Set expectedOps = new HashSet(Arrays.asList( - "preRegister", "postRegister", "addNotificationListener", - "removeNL1", "removeNL3", "getNotificationInfo")); - assertEquals(expectedOps, ccmbs.getAttribute(createdName, "CalledOps")); - - assertEquals(ShowContext.class.getClassLoader(), - ccmbs.getClassLoaderFor(createdName)); - - assertEquals(true, ccmbs.isRegistered(createdName)); - assertEquals(true, ccmbs.isInstanceOf(createdName, - ShowContext.class.getName())); - assertEquals(false, ccmbs.isInstanceOf(createdName, - DynamicMBean.class.getName())); - ccmbs.unregisterMBean(createdName); - assertEquals(false, ccmbs.isRegistered(createdName)); - - MLet mlet = new MLet(); - ObjectName defaultMLetName = new ObjectName("DefaultDomain:type=MLet"); - - ccmbs.registerMBean(mlet, defaultMLetName); - - assertEquals(mlet, ccmbs.getClassLoader(defaultMLetName)); - - assertEquals(0, mbeanLogIH.log.size()); - - // Test that contexts still work when we can't combine two encoded contexts. - // Here, we wrap cmbs (mickey=mouse) so that ccmbs2 (donald=duck) cannot - // see that it already contains a context and therefore cannot combine - // into mickey=mouse;donald=duck. We don't actually use the snoop - // capabilities of the returned object -- we just want an opaque - // MBeanServer wrapper - MBeanServer cmbs2 = newSnoop(MBeanServer.class, new LogIH(cmbs)); - MBeanServer ccmbs2 = ClientContext.withContext(cmbs2, "donald", "duck"); - assertEquals(disney, ccmbs2.getAttribute(name, "Context")); - - // ADD NEW TESTS HERE ^^^ - - if (failure != null) - throw new Exception(failure); - } finally { - srv.stop(); - } - } - - private static void assertEquals(Object x, Object y) { - if (!equal(x, y)) - failed("expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - private static void assertCalled( - LogIH logIH, String op, Map expectedContext) { - assertCalled(logIH, op, null, expectedContext); - } - - private static void assertCalled( - LogIH logIH, String op, Object[] params, - Map expectedContext) { - LogRecord lr = logIH.log.remove(); - assertEquals(op, lr.op); - if (params != null) - assertEquals(params, lr.params); - assertEquals(expectedContext, lr.context); - } - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } -} diff --git a/test/javax/management/context/localizable/MBeanDescriptions.properties b/test/javax/management/context/localizable/MBeanDescriptions.properties deleted file mode 100644 index 4722c5b5a..000000000 --- a/test/javax/management/context/localizable/MBeanDescriptions.properties +++ /dev/null @@ -1,9 +0,0 @@ -# This is the default description ResourceBundle for MBeans in this package. -# Resources here override the descriptions specified with @Description -# but only when localization is happening and when there is not a more -# specific resource for the description (for example from MBeanDescriptions_fr). - -WhatsitMBean.mbean = A whatsit -# This must be the same as WhatsitMBean.englishMBeanDescription for the -# purposes of this test. - diff --git a/test/javax/management/context/localizable/MBeanDescriptions_fr.java b/test/javax/management/context/localizable/MBeanDescriptions_fr.java deleted file mode 100644 index 3e1ec2d9e..000000000 --- a/test/javax/management/context/localizable/MBeanDescriptions_fr.java +++ /dev/null @@ -1,42 +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. - * - * 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 localizable; - -import java.util.ListResourceBundle; -import static localizable.WhatsitMBean.*; - -public class MBeanDescriptions_fr extends ListResourceBundle { - @Override - protected Object[][] getContents() { - String constrProp = "WhatsitMBean.constructor." + Whatsit.class.getName(); - return new Object[][] { - {"WhatsitMBean.mbean", frenchMBeanDescription}, - {"WhatsitMBean.attribute.Whatsit", frenchAttrDescription}, - {"WhatsitMBean.operation.frob", frenchOperDescription}, - {"WhatsitMBean.operation.frob.p1", frenchParamDescription}, - {constrProp, frenchConstrDescription}, - {constrProp + ".p1", frenchConstrParamDescription}, - }; - } -} diff --git a/test/javax/management/context/localizable/Whatsit.java b/test/javax/management/context/localizable/Whatsit.java deleted file mode 100644 index 5c10d7bc6..000000000 --- a/test/javax/management/context/localizable/Whatsit.java +++ /dev/null @@ -1,59 +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. - * - * 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 localizable; - -import javax.management.Description; - -public class Whatsit implements WhatsitMBean { - /** - * Attribute : NewAttribute0 - */ - private String newAttribute0; - @Description(englishConstrDescription) - public Whatsit() {} - - @Description(englishConstrDescription) - public Whatsit(@Description(englishConstrParamDescription) int type) {} - - public String getWhatsit() { - return "whatsit"; - } - - public void frob(String whatsit) { - } - - /** - * Get Tiddly - */ - public String getNewAttribute0() { - return newAttribute0; - } - - /** - * Set Tiddly - */ - public void setNewAttribute0(String value) { - newAttribute0 = value; - } -} diff --git a/test/javax/management/context/localizable/WhatsitMBean.java b/test/javax/management/context/localizable/WhatsitMBean.java deleted file mode 100644 index 8781f5273..000000000 --- a/test/javax/management/context/localizable/WhatsitMBean.java +++ /dev/null @@ -1,53 +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. - * - * 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 localizable; - -import javax.management.Description; - -@Description(WhatsitMBean.defaultMBeanDescription) -public interface WhatsitMBean { - public static final String - defaultMBeanDescription = "Default whatsit MBean description", - englishMBeanDescription = "A whatsit", - // Previous description appears in MBeanDescriptions.properties - // so it overrides the @Description when that file is used. - frenchMBeanDescription = "Un bidule", - englishAttrDescription = "The whatsit", - frenchAttrDescription = "Le bidule", - englishOperDescription = "Frob the whatsit", - frenchOperDescription = "Frober le bidule", - englishParamDescription = "The whatsit to frob", - frenchParamDescription = "Le bidule \u00e0 frober", - englishConstrDescription = "Make a whatsit", - frenchConstrDescription = "Fabriquer un bidule", - englishConstrParamDescription = "Type of whatsit to make", - frenchConstrParamDescription = "Type de bidule \u00e0 fabriquer", - unlocalizedMBeanDescription = "Unlocalized MBean"; - - @Description(englishAttrDescription) - public String getWhatsit(); - - @Description(englishOperDescription) - public void frob(@Description(englishParamDescription) String whatsit); -} diff --git a/test/javax/management/descriptor/DescriptorConstructorTest.java b/test/javax/management/descriptor/DescriptorConstructorTest.java deleted file mode 100644 index 0906cead4..000000000 --- a/test/javax/management/descriptor/DescriptorConstructorTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2004-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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * @test - * @bug 6501362 - * @summary DescriptorSupport(String) could recognize "name=value" as well as XML format - * @author Jean-Francois Denise - * @run clean DescriptorConstructorTest - * @run build DescriptorConstructorTest - * @run main DescriptorConstructorTest - */ - -import javax.management.modelmbean.DescriptorSupport; - -public class DescriptorConstructorTest { - public static void main(String[] args) throws Exception { - DescriptorSupport d1 = new DescriptorSupport("MyName1=MyValue1"); - if(!d1.getFieldValue("MyName1").equals("MyValue1")) - throw new Exception("Invalid parsing"); - DescriptorSupport d2 = new DescriptorSupport("" + - ""); - if(!d2.getFieldValue("MyName2").equals("MyValue2")) - throw new Exception("Invalid parsing"); - } -} diff --git a/test/javax/management/eventService/AddRemoveListenerTest.java b/test/javax/management/eventService/AddRemoveListenerTest.java deleted file mode 100644 index 72a8c6926..000000000 --- a/test/javax/management/eventService/AddRemoveListenerTest.java +++ /dev/null @@ -1,371 +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. - * - * 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. - */ - -/* - * @test AddRemoveListenerTest.java - * @bug 5108776 - * @summary Basic test for EventClient to see internal thread management. - * @author Shanliang JIANG - * @run clean AddRemoveListenerTest - * @run build AddRemoveListenerTest - * @run main AddRemoveListenerTest - */ - -import java.io.IOException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.FetchingEventRelay; -import javax.management.event.RMIPushEventRelay; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - - -// This thread creates a single MBean that emits a number of parallel -// sequences of notifications. Each sequence is distinguished by an id -// and each id corresponds to a thread that is filtering the notifications -// so it only sees its own ones. The notifications for a given id have -// contiguous sequence numbers and each thread checks that the notifications -// it receives do indeed have these numbers. If notifications are lost or -// if the different sequences interfere with each other then the test will -// fail. As an added tweak, a "noise" thread periodically causes notifications -// to be emitted that do not correspond to any sequence and do not have any id. -public class AddRemoveListenerTest { - - private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer(); - private static ObjectName emitter; - private static NotificationSender emitterImpl; - private static JMXServiceURL url; - private static JMXConnectorServer server; - - private static int toSend = 100; - private static final long bigWaiting = 10000; - private static int counter = 0; - private static int jobs = 10; - private static int endedJobs = 0; - - private static volatile String failure; - - public static void main(String[] args) throws Exception { - System.out.println(">>> Test on multiple adding/removing listeners."); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - emitter = new ObjectName("Default:name=NotificationSender"); - emitterImpl = new NotificationSender(); - mbeanServer.registerMBean(emitterImpl, emitter); - - String[] types = new String[]{"PushEventRelay", "FetchingEventRelay"}; - String[] protos = new String[]{"rmi", "iiop", "jmxmp"}; - for (String prot : protos) { - url = new JMXServiceURL(prot, null, 0); - - try { - server = - JMXConnectorServerFactory.newJMXConnectorServer(url, - null, mbeanServer); - server.start(); - } catch (Exception e) { - System.out.println(">>> Skip "+prot+", not supported."); - continue; - } - - url = server.getAddress(); - - // noise - Thread noise = new Thread(new Runnable() { - public void run() { - while (true) { - emitterImpl.sendNotif(1, null); - try { - Thread.sleep(10); - } catch (Exception e) { - // OK - } - } - } - }); - noise.setDaemon(true); - noise.start(); - - try { - for (String type: types) { - System.out.println("\n\n>>> Testing "+type+" on "+url+" ..."); - JMXConnector conn = newConn(); - try { - testType(type, conn); - } finally { - conn.close(); - System.out.println(">>> Testing "+type+" on "+url+" ... done"); - } - } - } finally { - server.stop(); - } - } - } - - private static void testType(String type, JMXConnector conn) throws Exception { - Thread[] threads = new Thread[jobs]; - for (int i=0; i 0 && failure == null) { - AddRemoveListenerTest.class.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - if (endedJobs != jobs && failure == null) { - throw new RuntimeException("Need to set bigger waiting timeout?"); - } - - endedJobs = 0; - } - - public static class Job implements Runnable { - public Job(String type, JMXConnector conn) { - this.type = type; - this.conn = conn; - } - public void run() { - try { - test(type, conn); - - synchronized(AddRemoveListenerTest.class) { - endedJobs++; - if (endedJobs>=jobs) { - AddRemoveListenerTest.class.notify(); - } - } - } catch (RuntimeException re) { - throw re; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private final String type; - private final JMXConnector conn; - } - - private static void test(String type, JMXConnector conn) throws Exception { - EventClient ec = newEventClient(type, conn); - try { - test(type, conn, ec); - } finally { - ec.close(); - } - } - - private static void test(String type, JMXConnector conn, EventClient ec) - throws Exception { - String id = getId(); - - Listener listener = new Listener(id); - Filter filter = new Filter(id); - - System.out.println(">>> ("+id+") To receive notifications "+toSend); - ec.addNotificationListener(emitter, - listener, filter, null); - - emitterImpl.sendNotif(toSend, id); - listener.waitNotifs(bigWaiting, toSend); - if (listener.received != toSend) { - throw new RuntimeException(">>> ("+id+") Expected to receive: " - +toSend+", but got: "+listener.received); - } - - listener.clear(); - ec.removeNotificationListener(emitter, listener, filter, null); - - System.out.println(">>> ("+id+") Repeat adding and removing ..."); - for (int j=0; j<10; j++) { - ec.addNotificationListener(emitter, dummyListener, null, id); - Thread.yield(); // allow to start listening - ec.removeNotificationListener(emitter, dummyListener, null, id); - } - - System.out.println(">>> ("+id+") To receive again notifications "+toSend); - ec.addNotificationListener(emitter, - listener, filter, null); - - emitterImpl.sendNotif(toSend, id); - listener.waitNotifs(bigWaiting, toSend); - Thread.yield(); //any duplicated? - if (listener.received != toSend) { - throw new RuntimeException("("+id+") Expected to receive: " - +toSend+", but got: "+listener.received); - } - } - -//-------------------------- -// private classes -//-------------------------- - - private static class Listener implements NotificationListener { - public Listener(String id) { - this.id = id; - } - public void handleNotification(Notification notif, Object handback) { - if (!id.equals(notif.getUserData())) { - System.out.println("("+id+") Filter error, my id is: "+id+ - ", but got "+notif.getUserData()); - System.exit(1); - } - - synchronized (this) { - received++; - - if(++sequenceNB != notif.getSequenceNumber()) { - fail("(" + id + ") Wrong sequence number, expected: " - +sequenceNB+", but got: "+notif.getSequenceNumber()); - } - if (received >= toSend || failure != null) { - this.notify(); - } - } - } - - public void waitNotifs(long timeout, int nb) throws Exception { - long toWait = timeout; - long stopTime = System.currentTimeMillis() + timeout; - synchronized(this) { - while (received < nb && toWait > 0 && failure == null) { - this.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - } - - public void clear() { - synchronized(this) { - received = 0; - sequenceNB = -1; - } - } - - private String id; - private int received = 0; - - private long sequenceNB = -1; - } - - private static class Filter implements NotificationFilter { - public Filter(String id) { - this.id = id; - } - - public boolean isNotificationEnabled(Notification n) { - return id.equals(n.getUserData()); - } - private String id; - } - - private static NotificationListener dummyListener = new NotificationListener() { - public void handleNotification(Notification notif, Object handback) { - } - }; - - public static class NotificationSender extends NotificationBroadcasterSupport - implements NotificationSenderMBean { - - /** - * Send Notification objects. - * - * @param nb The number of notifications to send - */ - public void sendNotif(int nb, String userData) { - long sequenceNumber = 0; - for (int i = 0; i nonFatalNotifs = - new ArrayBlockingQueue(1); - final BlockingQueue failedNotifs = - new ArrayBlockingQueue(1); - NotificationListener lostListener = new NotificationListener() { - public void handleNotification(Notification notification, Object handback) { - if (notification.getType().equals(EventClient.NOTIFS_LOST)) { - System.out.println("Got lost-notifs notif: count=" + - notification.getUserData()); - lostCountSema.release(((Long) notification.getUserData()).intValue()); - } else if (notification.getType().equals(EventClient.NONFATAL)) { - System.out.println("Got nonFatal notif"); - nonFatalNotifs.add(notification); - } else if (notification.getType().equals(EventClient.FAILED)) { - System.out.println("Got failed notif"); - failedNotifs.add(notification); - } else - System.out.println("Mysterious EventClient notif: " + notification); - } - }; - client.addEventClientListener(lostListener, null, null); - - final BlockingQueue notifQueue = - new ArrayBlockingQueue(10); - NotificationListener countListener = new NotificationListener() { - public void handleNotification(Notification notification, Object handback) { - System.out.println("Received: " + notification); - notifQueue.add(notification); - if (!"tiddly".equals(handback)) { - System.err.println("TEST FAILED: bad handback: " + handback); - System.exit(1); - } - } - }; - - final AtomicInteger filterCount = new AtomicInteger(0); - NotificationFilter countFilter = new NotificationFilter() { - private static final long serialVersionUID = 1234L; - - public boolean isNotificationEnabled(Notification notification) { - System.out.println("Filter called for: " + notification); - filterCount.incrementAndGet(); - return true; - } - }; - - client.addNotificationListener(name, countListener, countFilter, "tiddly"); - - assertEquals("Initial notif count", 0, notifQueue.size()); - assertEquals("Initial filter count", 0, filterCount.get()); - - Notification n = nextNotif(name); - mbean.send(n); - - System.out.println("Waiting for notification to arrive..."); - - Notification n1 = notifQueue.poll(10, TimeUnit.SECONDS); - - assertEquals("Received notif", n, n1); - assertEquals("Notif queue size after receive", 0, notifQueue.size()); - assertEquals("Filter count after notif", 1, filterCount.get()); - assertEquals("Lost notif count", 0, lostCountSema.availablePermits()); - - System.out.println("Dropping notifs"); - - UdpEventForwarder.setDrop(true); - for (int i = 0; i < 3; i++) - mbean.send(nextNotif(name)); - UdpEventForwarder.setDrop(false); - - Thread.sleep(2); - assertEquals("Notif queue size after drops", 0, notifQueue.size()); - - System.out.println("Turning off dropping and sending a notif"); - n = nextNotif(name); - mbean.send(n); - - System.out.println("Waiting for dropped notifications to be detected..."); - boolean acquired = lostCountSema.tryAcquire(3, 5, TimeUnit.SECONDS); - assertEquals("Correct count of lost notifs", true, acquired); - - n1 = notifQueue.poll(10, TimeUnit.SECONDS); - assertEquals("Received non-dropped notif", n, n1); - - assertEquals("Notif queue size", 0, notifQueue.size()); - assertEquals("Filter count after drops", 5, filterCount.get()); - - Thread.sleep(10); - assertEquals("Further lost-notifs", 0, lostCountSema.availablePermits()); - - System.out.println("Testing error notifs"); - relay.simulateNonFatal(); - n = nonFatalNotifs.poll(10, TimeUnit.SECONDS); - assertEquals("Exception message for non-fatal exception", "NonFatal", - ((Throwable) n.getSource()).getMessage()); - relay.simulateFailed(); - n = failedNotifs.poll(10, TimeUnit.SECONDS); - assertEquals("Exception message for failed exception", "Failed", - ((Throwable) n.getSource()).getMessage()); - - // 6759619 - System.out.println("Test EventClient.getEventClientNotificationInfo"); - MBeanNotificationInfo[] mbnis = client.getEventClientNotificationInfo(); - final String[] expectedTypes = { - EventClient.NOTIFS_LOST, EventClient.NONFATAL, EventClient.FAILED - }; - check: - for (String type : expectedTypes) { - for (MBeanNotificationInfo mbni : mbnis) { - for (String t : mbni.getNotifTypes()) { - if (type.equals(t)) { - System.out.println("...found " + type); - continue check; - } - } - } - throw new Exception("TEST FAILED: Did not find notif type " + type); - } - - client.close(); - - System.out.println("TEST PASSED"); - } - - private static AtomicLong nextSeqNo = new AtomicLong(0); - private static Notification nextNotif(ObjectName name) { - long n = nextSeqNo.incrementAndGet(); - return new Notification("type", name, n, "" + n); - } - - private static void assertEquals(String what, Object expected, Object got) { - if (equals(expected, got)) - System.out.println(what + " = " + expected + ", as expected"); - else { - Map traces = Thread.getAllStackTraces(); - for (Thread t : traces.keySet()) { - System.out.println(t.getName()); - for (StackTraceElement elmt : traces.get(t)) { - System.out.println(" " + elmt); - } - } - throw new RuntimeException( - "TEST FAILED: " + what + " is " + got + "; should be " + - expected); - } - } - - private static boolean equals(Object expected, Object got) { - if (!(expected instanceof Notification)) - return expected.equals(got); - if (expected.getClass() != got.getClass()) - return false; - // Notification doesn't override Object.equals so two distinct - // notifs are never equal even if they have the same contents. - // Although the test doesn't serialize the notifs, if at some - // stage it did then it would fail because the deserialized notif - // was not equal to the original one. Therefore we compare enough - // notif fields to detect when notifs really are different. - Notification en = (Notification) expected; - Notification gn = (Notification) got; - return (en.getType().equals(gn.getType()) && - en.getSource().equals(gn.getSource()) && - en.getSequenceNumber() == gn.getSequenceNumber()); - } -} diff --git a/test/javax/management/eventService/EventClientExecutorTest.java b/test/javax/management/eventService/EventClientExecutorTest.java deleted file mode 100644 index 5201335e8..000000000 --- a/test/javax/management/eventService/EventClientExecutorTest.java +++ /dev/null @@ -1,190 +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. - * - * 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. - */ - -/* - * @test - * @bug 5108776 - * @summary Test that the various Executor parameters in an EventClient do - * what they are supposed to. - * @author Eamonn McManus - */ - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.FetchingEventRelay; -import javax.management.remote.MBeanServerForwarder; - -public class EventClientExecutorTest { - private static volatile String failure; - private static final Set testedPrefixes = new HashSet(); - - public static void main(String[] args) throws Exception { - Executor fetchExecutor = Executors.newSingleThreadExecutor( - new NamedThreadFactory("FETCH")); - Executor listenerExecutor = Executors.newSingleThreadExecutor( - new NamedThreadFactory("LISTENER")); - ScheduledExecutorService leaseScheduler = - Executors.newSingleThreadScheduledExecutor( - new NamedThreadFactory("LEASE")); - - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - MBeanServerForwarder mbsf = EventClientDelegate.newForwarder(mbs, null); - mbs = mbsf; - - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(mbs); - ecd = (EventClientDelegateMBean) Proxy.newProxyInstance( - EventClientDelegateMBean.class.getClassLoader(), - new Class[] {EventClientDelegateMBean.class}, - new DelegateCheckIH(ecd)); - - ObjectName mbeanName = new ObjectName("d:type=Notifier"); - Notifier notifier = new Notifier(); - mbs.registerMBean(notifier, mbeanName); - - FetchingEventRelay eventRelay = new FetchingEventRelay( - ecd, fetchExecutor); - EventClient ec = new EventClient( - ecd, eventRelay, listenerExecutor, leaseScheduler, 1000L); - NotificationListener checkListener = new NotificationListener() { - public void handleNotification(Notification notification, - Object handback) { - assertThreadName("listener dispatch", "LISTENER"); - } - }; - ec.addNotificationListener(mbeanName, checkListener, null, null); - - mbs.invoke(mbeanName, "send", null, null); - - // Now wait until we have seen all three thread types. - long deadline = System.currentTimeMillis() + 5000; - synchronized (testedPrefixes) { - while (testedPrefixes.size() < 3 && failure == null) { - long remain = deadline - System.currentTimeMillis(); - if (remain <= 0) { - fail("Timed out waiting for all three thread types to show, " + - "saw only " + testedPrefixes); - break; - } - try { - testedPrefixes.wait(remain); - } catch (InterruptedException e) { - fail("Unexpected InterruptedException"); - break; - } - } - } - - // We deliberately don't close the EventClient to check that it has - // not created any non-daemon threads. - - if (failure != null) - throw new Exception("TEST FAILED: " + failure); - else - System.out.println("TEST PASSED"); - } - - public static interface NotifierMBean { - public void send(); - } - - public static class Notifier extends NotificationBroadcasterSupport - implements NotifierMBean { - public void send() { - Notification n = new Notification("a.b.c", this, 0L); - sendNotification(n); - } - } - - static void fail(String why) { - System.out.println("FAIL: " + why); - failure = why; - } - - static void assertThreadName(String what, String prefix) { - String name = Thread.currentThread().getName(); - if (!name.startsWith(prefix)) { - fail("Wrong thread for " + what + ": " + name); - return; - } - - synchronized (testedPrefixes) { - if (testedPrefixes.add(prefix)) - testedPrefixes.notify(); - } - } - - private static class DelegateCheckIH implements InvocationHandler { - private final EventClientDelegateMBean ecd; - - public DelegateCheckIH(EventClientDelegateMBean ecd) { - this.ecd = ecd; - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - String methodName = method.getName(); - if (methodName.equals("fetchNotifications")) - assertThreadName("fetchNotifications", "FETCH"); - else if (methodName.equals("lease")) - assertThreadName("lease renewal", "LEASE"); - try { - return method.invoke(ecd, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static class NamedThreadFactory implements ThreadFactory { - private final String namePrefix; - private int count; - - NamedThreadFactory(String namePrefix) { - this.namePrefix = namePrefix; - } - - public synchronized Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setName(namePrefix + " " + ++count); - t.setDaemon(true); - return t; - } - } -} diff --git a/test/javax/management/eventService/EventClientThreadTest.java b/test/javax/management/eventService/EventClientThreadTest.java deleted file mode 100644 index 910bc9cc2..000000000 --- a/test/javax/management/eventService/EventClientThreadTest.java +++ /dev/null @@ -1,176 +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. - * - * 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. - */ - -/* - * @test - * @bug 6747411 - * @summary Check that EventClient instances don't leak threads. - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.Set; -import java.util.TreeSet; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerNotification; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class EventClientThreadTest { - private static final int MAX_TIME_SECONDS = 20; - - private static final BlockingQueue queue = - new ArrayBlockingQueue(100); - - private static final NotificationListener queueListener = - new NotificationListener() { - public void handleNotification(Notification notification, - Object handback) { - queue.add(notification); - } - }; - - private static final NotificationFilter dummyFilter = - new NotificationFilter() { - public boolean isNotificationEnabled(Notification notification) { - return true; - } - }; - - public static void main(String[] args) throws Exception { - long start = System.currentTimeMillis(); - long deadline = start + MAX_TIME_SECONDS * 1000; - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( - url, null, mbs); - cs.start(); - JMXServiceURL addr = cs.getAddress(); - JMXConnector cc = JMXConnectorFactory.connect(addr); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - - ThreadMXBean threads = ManagementFactory.getThreadMXBean(); - - System.out.println("Opening and closing some EventClients..."); - // If we create a connection, then create and destroy EventClients - // over it, then close it, there should be no "JMX *" threads left. - for (int i = 0; i < 5; i++) - test(mbsc); - - cc.close(); - - showTime("opening and closing initial EventClients", start); - - Set jmxThreads = threadsMatching("JMX .*"); - while (!jmxThreads.isEmpty() && System.currentTimeMillis() < deadline) { - Set jmxThreadsNow = threadsMatching("JMX .*"); - Set gone = new TreeSet(jmxThreads); - gone.removeAll(jmxThreadsNow); - for (String s : gone) - showTime("expiry of \"" + s + "\"", start); - jmxThreads = jmxThreadsNow; - Thread.sleep(10); - } - if (System.currentTimeMillis() >= deadline) { - showThreads(threads); - throw new Exception("Timed out waiting for JMX threads to expire"); - } - - showTime("waiting for JMX threads to expire", start); - - System.out.println("TEST PASSED"); - } - - static void showThreads(ThreadMXBean threads) throws Exception { - long[] ids = threads.getAllThreadIds(); - for (long id : ids) { - ThreadInfo ti = threads.getThreadInfo(id); - String name = (ti == null) ? "(defunct)" : ti.getThreadName(); - System.out.printf("%4d %s\n", id, name); - } - } - - static void showTime(String what, long start) { - long elapsed = System.currentTimeMillis() - start; - System.out.printf("Time after %s: %.3f s\n", what, elapsed / 1000.0); - } - - static Set threadsMatching(String pattern) { - Set matching = new TreeSet(); - ThreadMXBean threads = ManagementFactory.getThreadMXBean(); - long[] ids = threads.getAllThreadIds(); - for (long id : ids) { - ThreadInfo ti = threads.getThreadInfo(id); - String name = (ti == null) ? "(defunct)" : ti.getThreadName(); - if (name.matches(pattern)) - matching.add(name); - } - return matching; - } - - static void test(MBeanServerConnection mbsc) throws Exception { - final ObjectName delegateName = MBeanServerDelegate.DELEGATE_NAME; - final ObjectName testName = new ObjectName("test:type=Test"); - EventClient ec = new EventClient(mbsc); - ec.addNotificationListener(delegateName, queueListener, null, null); - mbsc.createMBean(MBeanServerDelegate.class.getName(), testName); - mbsc.unregisterMBean(testName); - final String[] expectedTypes = { - MBeanServerNotification.REGISTRATION_NOTIFICATION, - MBeanServerNotification.UNREGISTRATION_NOTIFICATION, - }; - for (String s : expectedTypes) { - Notification n = queue.poll(3, TimeUnit.SECONDS); - if (n == null) - throw new Exception("Timed out waiting for notif: " + s); - if (!(n instanceof MBeanServerNotification)) - throw new Exception("Got notif of wrong class: " + n.getClass()); - if (!n.getType().equals(s)) { - throw new Exception("Got notif of wrong type: " + n.getType() + - " (expecting " + s + ")"); - } - } - ec.removeNotificationListener(delegateName, queueListener); - - ec.addNotificationListener(delegateName, queueListener, dummyFilter, "foo"); - ec.removeNotificationListener(delegateName, queueListener, dummyFilter, "foo"); - - ec.close(); - } -} \ No newline at end of file diff --git a/test/javax/management/eventService/EventDelegateSecurityTest.java b/test/javax/management/eventService/EventDelegateSecurityTest.java deleted file mode 100644 index a227e13f5..000000000 --- a/test/javax/management/eventService/EventDelegateSecurityTest.java +++ /dev/null @@ -1,289 +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. - * - * 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. - */ - -/* - * @test - * @bug 5108776 - * @summary Test that the EventClientDelegate MBean does not require extra - * permissions compared with plain addNotificationListener. - * @author Eamonn McManus - * @run main/othervm -Dxjava.security.debug=policy,access,failure EventDelegateSecurityTest - */ - -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.AllPermission; -import java.security.PrivilegedExceptionAction; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.TimeUnit; -import javax.management.MBeanPermission; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.remote.JMXAuthenticator; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXPrincipal; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.MBeanServerForwarder; -import javax.security.auth.Subject; - -public class EventDelegateSecurityTest { - private static final BlockingQueue notifQ = - new SynchronousQueue(); - - private static volatile long seqNo; - private static volatile long expectSeqNo; - - private static class QueueListener implements NotificationListener { - public void handleNotification(Notification notification, - Object handback) { - try { - notifQ.put(notification); - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - } - private static final NotificationListener queueListener = new QueueListener(); - - public static interface SenderMBean { - public void send(); - } - - public static class Sender - extends NotificationBroadcasterSupport implements SenderMBean { - public void send() { - Notification n = new Notification("x", this, seqNo++); - sendNotification(n); - } - } - - private static class LimitInvocationHandler implements InvocationHandler { - private MBeanServer nextMBS; - private final Set allowedMethods = new HashSet(); - - void allow(String... names) { - synchronized (allowedMethods) { - allowedMethods.addAll(Arrays.asList(names)); - } - } - - public Object invoke(Object proxy, Method m, Object[] args) - throws Throwable { - System.out.println( - "filter: " + m.getName() + - ((args == null) ? "[]" : Arrays.deepToString(args))); - String name = m.getName(); - - if (name.equals("getMBeanServer")) - return nextMBS; - - if (name.equals("setMBeanServer")) { - nextMBS = (MBeanServer) args[0]; - return null; - } - - if (m.getDeclaringClass() == Object.class || - allowedMethods.contains(name)) { - try { - return m.invoke(nextMBS, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } else { - System.out.println("...refused"); - throw new SecurityException( - "Method refused: " + m.getDeclaringClass().getName() + - "." + m.getName() + - ((args == null) ? "[]" : Arrays.deepToString(args))); - } - } - - } - - private static interface MakeConnectorServer { - public JMXConnectorServer make(JMXServiceURL url) throws IOException; - } - - - public static void main(String[] args) throws Exception { - JMXPrincipal rootPrincipal = new JMXPrincipal("root"); - Subject rootSubject = new Subject(); - rootSubject.getPrincipals().add(rootPrincipal); - Subject.doAsPrivileged(rootSubject, new PrivilegedExceptionAction() { - public Void run() throws Exception { - mainAsRoot(); - return null; - } - }, null); - } - - private static void mainAsRoot() throws Exception { - AccessControlContext acc = AccessController.getContext(); - Subject subject = Subject.getSubject(acc); - System.out.println("Subject: " + subject); - final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName name = new ObjectName("a:b=c"); - mbs.registerMBean(new Sender(), name); - - System.out.println("Test with no installed security"); - test(mbs, name, new MakeConnectorServer() { - public JMXConnectorServer make(JMXServiceURL url) throws IOException { - return - JMXConnectorServerFactory.newJMXConnectorServer(url, null, null); - } - }); - - System.out.println("Test with filtering MBeanServerForwarder"); - LimitInvocationHandler limitIH = new LimitInvocationHandler(); - // We allow getClassLoaderRepository because the ConnectorServer - // calls it so any real checking MBeanServerForwarder must accept it. - limitIH.allow( - "addNotificationListener", "removeNotificationListener", - "getClassLoaderRepository" - ); - final MBeanServerForwarder limitMBSF = (MBeanServerForwarder) - Proxy.newProxyInstance( - MBeanServerForwarder.class.getClassLoader(), - new Class[] {MBeanServerForwarder.class}, - limitIH); - // We go to considerable lengths to ensure that the ConnectorServer has - // no MBeanServer when the EventClientDelegate forwarder is activated, - // so that the calls it makes when it is later linked to an MBeanServer - // go through the limitMBSF. - test(mbs, name, new MakeConnectorServer() { - public JMXConnectorServer make(JMXServiceURL url) throws IOException { - JMXConnectorServer cs = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, null); - limitMBSF.setMBeanServer(mbs); - cs.setMBeanServerForwarder(limitMBSF); - return cs; - } - }); - - final File policyFile = - File.createTempFile("EventDelegateSecurityTest", ".policy"); - PrintWriter pw = new PrintWriter(policyFile); - String JMXPrincipal = JMXPrincipal.class.getName(); - String AllPermission = AllPermission.class.getName(); - String MBeanPermission = MBeanPermission.class.getName(); - pw.println("grant principal " + JMXPrincipal + " \"root\" {"); - pw.println(" permission " + AllPermission + ";"); - pw.println("};"); - pw.println("grant principal " + JMXPrincipal + " \"user\" {"); - pw.println(" permission " + MBeanPermission + " \"*\", " + - " \"addNotificationListener\";"); - pw.println(" permission " + MBeanPermission + " \"*\", " + - " \"removeNotificationListener\";"); - pw.println("};"); - pw.close(); - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - policyFile.delete(); - } - }); - System.setProperty("java.security.policy", policyFile.getAbsolutePath()); - System.setSecurityManager(new SecurityManager()); - test(mbs, name, new MakeConnectorServer() { - public JMXConnectorServer make(JMXServiceURL url) throws IOException { - Map env = new HashMap(); - env.put(JMXConnectorServer.AUTHENTICATOR, new JMXAuthenticator() { - public Subject authenticate(Object credentials) { - Subject s = new Subject(); - s.getPrincipals().add(new JMXPrincipal("user")); - return s; - } - }); - return - JMXConnectorServerFactory.newJMXConnectorServer(url, env, null); - } - }); - } - - private static void test(MBeanServer mbs, ObjectName name) throws Exception { - test(mbs, name, null); - } - - private static void test( - MBeanServer mbs, ObjectName name, MakeConnectorServer make) - throws Exception { - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///"); - JMXConnectorServer cs = make.make(url); - ObjectName csName = new ObjectName("a:type=ConnectorServer"); - mbs.registerMBean(cs, csName); - cs.start(); - try { - JMXServiceURL addr = cs.getAddress(); - JMXConnector cc = JMXConnectorFactory.connect(addr); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - test(mbs, mbsc, name); - cc.close(); - mbs.unregisterMBean(csName); - } finally { - cs.stop(); - } - } - - private static void test( - MBeanServer mbs, MBeanServerConnection mbsc, ObjectName name) - throws Exception { - EventClient ec = new EventClient(mbsc); - ec.addNotificationListener(name, queueListener, null, null); - mbs.invoke(name, "send", null, null); - - Notification n = notifQ.poll(5, TimeUnit.SECONDS); - if (n == null) - throw new Exception("FAILED: notif not delivered"); - if (n.getSequenceNumber() != expectSeqNo) { - throw new Exception( - "FAILED: notif seqno " + n.getSequenceNumber() + - " should be " + expectSeqNo); - } - expectSeqNo++; - - ec.removeNotificationListener(name, queueListener); - ec.close(); - } -} diff --git a/test/javax/management/eventService/EventManagerTest.java b/test/javax/management/eventService/EventManagerTest.java deleted file mode 100644 index 66e4e36cf..000000000 --- a/test/javax/management/eventService/EventManagerTest.java +++ /dev/null @@ -1,221 +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. - * - * 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. - */ - -/* - * @test EventManagerTest.java 1.8 08/01/22 - * @bug 5108776 - * @summary Basic test for EventManager. - * @author Shanliang JIANG - * @run clean EventManagerTest - * @run build EventManagerTest - * @run main EventManagerTest - */ - -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.*; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * - */ -public class EventManagerTest { - private static MBeanServer mbeanServer; - private static ObjectName emitter; - private static JMXServiceURL url; - private static JMXConnectorServer server; - private static JMXConnector conn; - private static MBeanServerConnection client; - - /** - * @param args the command line arguments - */ - public static void main(String[] args) throws Exception { - System.out.println(">>> EventManagerTest-main basic tests ..."); - mbeanServer = MBeanServerFactory.createMBeanServer(); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - emitter = new ObjectName("Default:name=NotificationEmitter"); - - url = new JMXServiceURL("rmi", null, 0) ; - server = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer); - server.start(); - - url = server.getAddress(); - conn = JMXConnectorFactory.connect(url, null); - client = conn.getMBeanServerConnection(); - - mbeanServer.registerMBean(new NotificationEmitter(), emitter); - - boolean succeed; - - System.out.println(">>> EventManagerTest-main: using the fetching EventRelay..."); - succeed = test(new EventClient(client)); - - System.out.println(">>> EventManagerTest-main: using the pushing EventRelay..."); - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(client); - succeed &= test(new EventClient(ecd, - new RMIPushEventRelay(ecd), - null, null, - EventClient.DEFAULT_REQUESTED_LEASE_TIME)); - - conn.close(); - server.stop(); - - if (succeed) { - System.out.println(">>> EventManagerTest-main: PASSE!"); - } else { - System.out.println("\n>>> EventManagerTest-main: FAILED!"); - System.exit(1); - } - } - - public static boolean test(EventClient efClient) throws Exception { - // add listener from the client side - Listener listener = new Listener(); - efClient.subscribe(emitter, listener, null, null); - - // ask to send notifs - Object[] params = new Object[] {new Integer(sendNB)}; - String[] signatures = new String[] {"java.lang.Integer"}; - client.invoke(emitter, "sendNotifications", params, signatures); - - // waiting - long toWait = 6000; - long stopTime = System.currentTimeMillis() + toWait; - - synchronized(listener) { - while(listener.received < sendNB && toWait > 0) { - listener.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - // clean - System.out.println(">>> EventManagerTest-test: cleaning..."); - efClient.unsubscribe(emitter, listener); - efClient.close(); - - if (listener.received != sendNB) { - System.out.println(">>> EventManagerTest-test: FAILED! Expected to receive "+sendNB+", but got "+listener.received); - - return false; - } else if (listener.seqErr > 0) { - System.out.println(">>> EventManagerTest-test: FAILED! The receiving sequence is not correct."); - - return false; - } else { - System.out.println(">>> EventManagerTest-test: got all expected "+listener.received); - return true; - } - } - - private static class Listener implements NotificationListener { - public int received = 0; - public int seqErr = 0; - - private long lastSeq = -1; - - public void handleNotification(Notification notif, Object handback) { - if (!myType.equals(notif.getType())) { - System.out.println(">>> EventManagerTest-Listener: got unexpected notif: "+notif); - System.exit(1); - } - - if (lastSeq == -1) { - lastSeq = notif.getSequenceNumber(); - } else if (notif.getSequenceNumber() - lastSeq++ != 1) { - seqErr++; - } - - //System.out.println(">>> EventManagerTest-Listener: got notif "+notif.getSequenceNumber()); - - synchronized(this) { - if (++received >= sendNB) { - this.notify(); - } - } - } - } - - public static class NotificationEmitter extends NotificationBroadcasterSupport - implements NotificationEmitterMBean { - - public MBeanNotificationInfo[] getNotificationInfo() { - final String[] ntfTypes = {myType}; - - final MBeanNotificationInfo[] ntfInfoArray = { - new MBeanNotificationInfo(ntfTypes, - "javax.management.Notification", - "Notifications sent by the NotificationEmitter")}; - - return ntfInfoArray; - } - - /** - * Send Notification objects. - * - * @param nb The number of notifications to send - */ - public void sendNotifications(Integer nb) { - Notification notif; - for (int i=1; i<=nb.intValue(); i++) { - notif = new Notification(myType, this, count++); - notif.setUserData("jsl"); - //System.out.println(">>> EventManagerService-NotificationEmitter-sendNotifications: "+i); - - sendNotification(notif); - } - } - } - - public interface NotificationEmitterMBean { - public void sendNotifications(Integer nb); - } - - private static int sendNB = 120; - private static long count = 0; - - private static final String myType = "notification.my_notification"; -} diff --git a/test/javax/management/eventService/FetchingTest.java b/test/javax/management/eventService/FetchingTest.java deleted file mode 100644 index f6fc91691..000000000 --- a/test/javax/management/eventService/FetchingTest.java +++ /dev/null @@ -1,276 +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. - * - * 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. - */ - -/* - * @test - * @bug 5108776 - * @summary Basic test for EventClient. - * @author Shanliang JIANG - * @run clean FetchingTest MyFetchingEventForwarder - * @run build FetchingTest MyFetchingEventForwarder - * @run main FetchingTest MyFetchingEventForwarder - */ - -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.FetchingEventRelay; -import javax.management.event.RMIPushEventForwarder; -import javax.management.event.RMIPushServer; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class FetchingTest { - private static MBeanServer mbeanServer; - private static ObjectName emitter; - private static JMXServiceURL url; - private static JMXConnectorServer server; - private static JMXConnector conn; - private static MBeanServerConnection client; - private static long WAITING_TIME = 6000; - - /** - * @param args the command line arguments - */ - public static void main(String[] args) throws Exception { - - System.out.println(">>> FetchingTest-main basic tests ..."); - mbeanServer = MBeanServerFactory.createMBeanServer(); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - emitter = new ObjectName("Default:name=NotificationEmitter"); - mbeanServer.registerMBean(new NotificationEmitter(), emitter); - boolean succeed = true; - - final String[] protos = new String[] {"rmi", "iiop", "jmxmp"}; - for (String proto : protos) { - System.out.println(">>> FetchingTest-main: testing on "+proto); - - try { - url = new JMXServiceURL(proto, null, 0) ; - server = JMXConnectorServerFactory. - newJMXConnectorServer(url, null, mbeanServer); - server.start(); - } catch (Exception e) { - // OK - System.out.println(">>> FetchingTest-main: skip the proto "+proto); - continue; - } - - url = server.getAddress(); - conn = JMXConnectorFactory.connect(url, null); - client = conn.getMBeanServerConnection(); - - succeed &= test(); - - conn.close(); - server.stop(); - - System.out.println( - ">>> FetchingTest-main: testing on "+proto+" done."); - } - - if (succeed) { - System.out.println(">>> FetchingTest-main: PASSED!"); - } else { - System.out.println("\n>>> FetchingTest-main: FAILED!"); - System.exit(1); - } - } - - public static boolean test() throws Exception { - System.out.println(">>> FetchingTest-test: " + - "using the default fetching forwarder ..."); - EventClient eventClient = - new EventClient(client); - - Listener listener = new Listener(); - eventClient.addNotificationListener(emitter, listener, null, null); - - // ask to send notifs - Object[] params = new Object[] {new Integer(sendNB)}; - String[] signatures = new String[] {"java.lang.Integer"}; - conn.getMBeanServerConnection().invoke(emitter, - "sendNotifications", params, signatures); - - if (listener.waitNotif(WAITING_TIME) != sendNB) { - System.out.println( - ">>> FetchingTest-test: FAILED! Expected to receive "+ - sendNB+", but got "+listener.received); - - return false; - } - - System.out.println( - ">>> ListenerTest-test: got all expected "+listener.received); - //eventClient.removeNotificationListener(emitter, listener); - eventClient.close(); - - System.out.println(">>> FetchingTest-test: " + - "using a user specific List ..."); - - FetchingEventRelay fer = new FetchingEventRelay( - EventClientDelegate.getProxy(client), - 1000, 1000L, 1000, null, - MyFetchingEventForwarder.class.getName(), - null, null); - - eventClient = new EventClient( - EventClientDelegate.getProxy(client), fer, null, null, 10000); - - eventClient.addNotificationListener(emitter, listener, null, null); - listener.received = 0; - - conn.getMBeanServerConnection().invoke(emitter, - "sendNotifications", params, signatures); - - if (listener.waitNotif(WAITING_TIME) != sendNB) { - System.out.println( - ">>> FetchingTest-test: FAILED! Expected to receive "+ - sendNB+", but got "+listener.received); - - return false; - } - - System.out.println( - ">>> FetchingTest-test: got all expected "+listener.received); - - if (!MyFetchingEventForwarder.shared.isUsed()) { - System.out.println( - ">>> FetchingTest-test: FAILED! The user specific list" + - "is not used!"); - - return false; - } - - System.out.println(">>> Negative test to add an EventClient" + - " with a non EventForwarder object."); - try { - MyFetchingEventForwarder.shared.setAgain(); - - System.out.println( - ">>> FetchingTest-test: FAILED! No expected exception" + - "when setting the list after the forwarder started."); - - return false; - } catch (IllegalStateException ise) { - // OK - System.out.println( - ">>> FetchingTest-test: Got expected exception: " + ise); - } - - eventClient.close(); - - try { - fer = new FetchingEventRelay( - EventClientDelegate.getProxy(client), - 1000, 1000L, 1000, null, - Object.class.getName(), - null, null); - - eventClient = new EventClient( - EventClientDelegate.getProxy(client), fer, null, null, 10000); - - System.out.println( - ">>> FetchingTest-test: FAILED! No expected exception" + - "when creating an illegal EventForwarder"); - } catch (IllegalArgumentException iae) { - // OK - // iae.printStackTrace(); - } - - return true; - } - - private static class Listener implements NotificationListener { - public void handleNotification(Notification notif, Object handback) { - synchronized(this) { - if (++received >= sendNB) { - this.notify(); - } - } - - //System.out.println(">>> FetchingTest-Listener: received = "+received); - } - - public int waitNotif(long timeout) throws Exception { - synchronized(this) { - long stopTime = System.currentTimeMillis() + timeout; - long toWait = timeout; - while (toWait > 0 && received < sendNB) { - this.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - return received; - } - - public static int received = 0; - } - - public static class NotificationEmitter extends NotificationBroadcasterSupport - implements NotificationEmitterMBean { - - public void sendNotifications(Integer nb) { - System.out.println( - ">>> FetchingTest-NotificationEmitter-sendNotifications: "+nb); - Notification notif; - for (int i=1; i<=nb.intValue(); i++) { - notif = new Notification(myType, this, count++); - sendNotification(notif); - } - } - } - - public interface NotificationEmitterMBean { - public void sendNotifications(Integer nb); - } - - - - private static int sendNB = 20; - private static int count = 0; - - private static final String myType = "notification.my_notification"; -} diff --git a/test/javax/management/eventService/LeaseManagerDeadlockTest.java b/test/javax/management/eventService/LeaseManagerDeadlockTest.java deleted file mode 100644 index ab7d14d54..000000000 --- a/test/javax/management/eventService/LeaseManagerDeadlockTest.java +++ /dev/null @@ -1,98 +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. - * - * 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. - */ - -/* - * @test - * @bug 6717789 - * @summary Check that a lock is not held when a LeaseManager expires. - * @author Eamonn McManus - * @compile -XDignore.symbol.file=true LeaseManagerDeadlockTest.java - * @run main LeaseManagerDeadlockTest - */ - -import com.sun.jmx.event.LeaseManager; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadMXBean; -import java.util.Arrays; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; - -public class LeaseManagerDeadlockTest { - public static String failure; - public static LeaseManager leaseManager; - public static Semaphore callbackThreadCompleted = new Semaphore(0); - public static Object lock = new Object(); - - public static Runnable triggerDeadlock = new Runnable() { - public void run() { - Runnable pingLeaseManager = new Runnable() { - public void run() { - System.out.println("Ping thread starts"); - synchronized (lock) { - leaseManager.lease(1); - } - System.out.println("Ping thread completes"); - } - }; - Thread t = new Thread(pingLeaseManager); - t.start(); - try { - Thread.sleep(10); // enough time for ping thread to grab lock - synchronized (lock) { - t.join(); - } - } catch (InterruptedException e) { - fail(e.toString()); - } - System.out.println("Callback thread completes"); - callbackThreadCompleted.release(); - } - }; - - public static void main(String[] args) throws Exception { - // Also test that we can shorten the lease from its initial value. - leaseManager = new LeaseManager(triggerDeadlock, 1000000); - leaseManager.lease(1L); - - boolean callbackRan = - callbackThreadCompleted.tryAcquire(3, TimeUnit.SECONDS); - - if (!callbackRan) { - fail("Callback did not complete - probable deadlock"); - ThreadMXBean threads = ManagementFactory.getThreadMXBean(); - System.out.println(Arrays.toString(threads.findDeadlockedThreads())); - System.out.println("PRESS RETURN"); - System.in.read(); - } - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - public static void fail(String why) { - System.out.println("TEST FAILS: " + why); - failure = why; - } -} diff --git a/test/javax/management/eventService/LeaseTest.java b/test/javax/management/eventService/LeaseTest.java deleted file mode 100644 index fb056ad63..000000000 --- a/test/javax/management/eventService/LeaseTest.java +++ /dev/null @@ -1,361 +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. - * - * 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. - */ - -/* - * @test LeaseTest.java 1.6 08/01/22 - * @bug 5108776 - * @summary Basic test for Event service leasing. - * @author Shanliang JIANG - * @run clean LeaseTest - * @run build LeaseTest - * @run main LeaseTest - */ - - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.EventClientNotFoundException; -import javax.management.event.FetchingEventRelay; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class LeaseTest { - - private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer(); - private static List notifList = new ArrayList(); - private static ObjectName emitter; - private static NotificationEmitter emitterImpl; - private static JMXServiceURL url; - private static JMXConnectorServer server; - private static JMXConnector conn; - private static Listener listener = new Listener(); - - private static long leaseTime = 100; - private static final int multiple = 5; - private static final long bigWaiting = 6000; - - public static void main(String[] args) throws Exception { - System.out.println(">>> Test the event service lease"); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - System.setProperty("com.sun.event.lease.time", - String.valueOf(leaseTime)); - emitter = new ObjectName("Default:name=NotificationEmitter"); - emitterImpl = new NotificationEmitter(); - mbeanServer.registerMBean(emitterImpl, emitter); - - String[] types = new String[]{"PushingEventRelay", "FetchingEventRelay"}; - String[] protos = new String[]{"rmi", "iiop", "jmxmp"}; - for (String prot : protos) { - url = new JMXServiceURL(prot, null, 0); - - try { - server = - JMXConnectorServerFactory.newJMXConnectorServer(url, - null, mbeanServer); - server.start(); - } catch (Exception e) { - System.out.println(">>> Skip "+prot+", not support."); - continue; - } - - url = server.getAddress(); - - try { - for (String type: types) { - test(type); - } - } finally { - server.stop(); - } - } - } - - private static void test(String type) throws Exception { - System.out.println("\n\n>>> Testing "+type+" on "+url+" ..."); - newConn(); - EventClient ec = newEventClient(type); - - ec.addNotificationListener(emitter, - listener, null, null); - - System.out.println(">>> Send a notification and should receive it."); - emitterImpl.sendNotif(++counter); - - if (!waitNotif(bigWaiting, counter)) { - throw new RuntimeException(">>> Failed to receive notif."); - } - - System.out.println(">>> Sleep 3 times of requested lease time."); - Thread.sleep(leaseTime*3); - System.out.println(">>> Send again a notification and should receive it."); - emitterImpl.sendNotif(++counter); - - if (!waitNotif(bigWaiting, counter)) { - throw new RuntimeException(">>> Failed to receive notif."); - } - - System.out.println(">>> Close the client connection: "+ - conn.getConnectionId()); - conn.close(); - - System.out.println(">>> Waiting lease timeout to do clean."); - - if (!emitterImpl.waitingClean(leaseTime*multiple)) { - throw new RuntimeException( - ">>> The event lease failed to do clean: "+ - emitterImpl.listenerSize); - } else { - System.out.println(">>> The listener has been removed."); - } - - // Check that the client id has indeed been removed, by trying to - // remove it again, which should fail. - newConn(); - try { - EventClientDelegateMBean proxy = - EventClientDelegate.getProxy(conn.getMBeanServerConnection()); - proxy.removeClient(ec.getEventRelay().getClientId()); - - throw new RuntimeException( - ">>> The client id is not removed."); - } catch (EventClientNotFoundException ecnfe) { - // OK - System.out.println(">>> The client id has been removed."); - } - conn.close(); - - System.out.println(">>> Reconnect to the server."); - newConn(); - - System.out.println(">>> Create a new EventClient and add the listeners" + - " in the failed EventClient into new EventClient"); - EventClient newEC = newEventClient(type); - newEC.addListeners(ec.getListeners()); - // We expect ec.close() to get IOException because we closed the - // underlying connection. - try { - ec.close(); - throw new RuntimeException(">>> EventClient.close did not throw " + - "expected IOException"); - } catch (IOException e) { - System.out.println(">>> EventClient.close threw expected exception: " + e); - } - - emitterImpl.sendNotif(++counter); - - if (!waitNotif(bigWaiting, counter)) { - throw new RuntimeException(">>> The event client failed to add " + - "all old registered listeners after re-connection."); - } else { - System.out.println(">>> Successfully received notification from" + - " new EventClient."); - } - - System.out.println(">>> Clean the failed EventClient."); - ec.close(); - if (ec.getListeners().size() != 0) { - throw new RuntimeException(">>> The event client fails to do clean."); - } - - System.out.println(">>> Clean the new EventClient."); - newEC.close(); - if (newEC.getListeners().size() != 0) { - throw new RuntimeException(">>> The event client fails to do clean."); - } - - conn.close(); - System.out.println(">>> Testing "+type+" on "+url+" ... done"); - } - - private static boolean waitNotif(long time, int sequenceNumber) - throws Exception { - synchronized(notifList) { - if (search(sequenceNumber)) { - return true; - } - - long stopTime = System.currentTimeMillis() + time; - long toWait = time; - while (toWait > 0) { - notifList.wait(toWait); - - if (search(sequenceNumber)) { - return true; - } - - toWait = stopTime - System.currentTimeMillis(); - } - - return false; - } - } - - private static boolean search(int sequenceNumber) { - while(notifList.size() > 0) { - Notification n = notifList.remove(0); - if (n.getSequenceNumber() == sequenceNumber) { - return true; - } - } - - return false; - } - -//-------------------------- -// private classes -//-------------------------- - - private static class Listener implements NotificationListener { - public void handleNotification(Notification notif, Object handback) { - synchronized (notifList) { - notifList.add(notif); - notifList.notify(); - } - } - } - - public static class NotificationEmitter extends NotificationBroadcasterSupport - implements NotificationEmitterMBean { - - public MBeanNotificationInfo[] getNotificationInfo() { - final String[] ntfTypes = {myType}; - - final MBeanNotificationInfo[] ntfInfoArray = { - new MBeanNotificationInfo(ntfTypes, - "javax.management.Notification", - "Notifications sent by the NotificationEmitter")}; - - return ntfInfoArray; - } - - /** - * Send Notification objects. - * - * @param nb The number of notifications to send - */ - public void sendNotif(int sequenceNumber) { - Notification notif = new Notification(myType, this, sequenceNumber); - sendNotification(notif); - } - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) { - super.addNotificationListener(listener, filter, handback); - - listenerSize++; - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - super.removeNotificationListener(listener); - listenerSize--; - - synchronized(this) { - if (listenerSize == 0) { - this.notifyAll(); - } - } - } - - public void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - super.removeNotificationListener(listener, filter, handback); - listenerSize--; - - synchronized(this) { - if (listenerSize == 0) { - this.notifyAll(); - } - } - } - - public boolean waitingClean(long timeout) throws Exception { - synchronized(this) { - long stopTime = System.currentTimeMillis() + timeout; - long toWait = timeout; - while (listenerSize != 0 && toWait > 0) { - this.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - return listenerSize == 0; - } - - public int listenerSize = 0; - - private final String myType = "notification.my_notification"; - } - - public interface NotificationEmitterMBean { - public void sendNotif(int sequenceNumber); - } - - private static void newConn() throws IOException { - conn = JMXConnectorFactory.connect(url); - } - - private static EventClient newEventClient(String type) throws Exception { - EventClientDelegateMBean proxy = - EventClientDelegate.getProxy(conn.getMBeanServerConnection()); - if (type.equals("PushingEventRelay")) { - return new EventClient(proxy, - new FetchingEventRelay(proxy), null, null, leaseTime); - } else if (type.equals("FetchingEventRelay")) { - return new EventClient(proxy, - new FetchingEventRelay(proxy), null, null, leaseTime); - } else { - throw new RuntimeException("Wrong event client type: "+type); - } - } - - private static int counter = 0; -} diff --git a/test/javax/management/eventService/ListenerTest.java b/test/javax/management/eventService/ListenerTest.java deleted file mode 100644 index c4c911356..000000000 --- a/test/javax/management/eventService/ListenerTest.java +++ /dev/null @@ -1,224 +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. - * - * 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. - */ - -/* - * @test ListenerTest.java 1.7 08/01/22 - * @bug 5108776 - * @summary Basic test for EventClient. - * @author Shanliang JIANG - * @run clean ListenerTest - * @run build ListenerTest - * @run main ListenerTest - */ - -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.*; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * - */ -public class ListenerTest { - private static MBeanServer mbeanServer; - private static ObjectName emitter; - private static JMXServiceURL url; - private static JMXConnectorServer server; - private static JMXConnector conn; - private static MBeanServerConnection client; - - /** - * @param args the command line arguments - */ - public static void main(String[] args) throws Exception { - - System.out.println(">>> ListenerTest-main basic tests ..."); - mbeanServer = MBeanServerFactory.createMBeanServer(); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - emitter = new ObjectName("Default:name=NotificationEmitter"); - - url = new JMXServiceURL("rmi", null, 0) ; - server = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer); - server.start(); - - url = server.getAddress(); - conn = JMXConnectorFactory.connect(url, null); - client = conn.getMBeanServerConnection(); - - mbeanServer.registerMBean(new NotificationEmitter(), emitter); - - boolean succeed; - - System.out.println(">>> ListenerTest-main: using the fetching EventRelay..."); - succeed = test(new EventClient(client)); - - System.out.println(">>> ListenerTest-main: using the pushing EventRelay..."); - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(client); - succeed &= test(new EventClient(ecd, - new RMIPushEventRelay(ecd), - null, null, - EventClient.DEFAULT_REQUESTED_LEASE_TIME)); - - conn.close(); - server.stop(); - - if (succeed) { - System.out.println(">>> ListenerTest-main: PASSED!"); - } else { - System.out.println("\n>>> ListenerTest-main: FAILED!"); - System.exit(1); - } - } - - public static boolean test(EventClient efClient) throws Exception { - // add listener from the client side - Listener listener = new Listener(); - efClient.addNotificationListener(emitter, listener, null, null); - - // ask to send notifs - Object[] params = new Object[] {new Integer(sendNB)}; - String[] signatures = new String[] {"java.lang.Integer"}; - client.invoke(emitter, "sendNotifications", params, signatures); - - // waiting - long toWait = 6000; - long stopTime = System.currentTimeMillis() + toWait; - - synchronized(listener) { - while(listener.received < sendNB && toWait > 0) { - listener.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - // clean - efClient.removeNotificationListener(emitter, listener, null, null); - efClient.close(); - - if (listener.received != sendNB) { - System.out.println(">>> ListenerTest-test: FAILED! Expected to receive "+sendNB+", but got "+listener.received); - - return false; - } else if (listener.seqErr > 0) { - System.out.println(">>> ListenerTest-test: FAILED! The receiving sequence is not correct."); - - return false; - } else { - System.out.println(">>> ListenerTest-test: got all expected "+listener.received); - return true; - } - } - - private static class Listener implements NotificationListener { - public int received = 0; - public int seqErr = 0; - - private long lastSeq = -1; - - public void handleNotification(Notification notif, Object handback) { - if (!myType.equals(notif.getType())) { - System.out.println(">>> EventManagerTest-Listener: got unexpected notif: "+notif); - System.exit(1); - } - - if (lastSeq == -1) { - lastSeq = notif.getSequenceNumber(); - } else if (notif.getSequenceNumber() - lastSeq++ != 1) { - seqErr++; - } - - System.out.println(">>> ListenerTest-Listener: got notif "+notif.getSequenceNumber()); - - synchronized(this) { - if (++received >= sendNB) { - this.notify(); - } - } - - System.out.println(">>> ListenerTest-Listener: received = "+received); - } - } - - public static class NotificationEmitter extends NotificationBroadcasterSupport - implements NotificationEmitterMBean { - - public MBeanNotificationInfo[] getNotificationInfo() { - final String[] ntfTypes = {myType}; - - final MBeanNotificationInfo[] ntfInfoArray = { - new MBeanNotificationInfo(ntfTypes, - "javax.management.Notification", - "Notifications sent by the NotificationEmitter")}; - - return ntfInfoArray; - } - - /** - * Send Notification objects. - * - * @param nb The number of notifications to send - */ - public void sendNotifications(Integer nb) { - Notification notif; - for (int i=1; i<=nb.intValue(); i++) { - notif = new Notification(myType, this, count++); - //System.out.println(">>> ListenerTest-NotificationEmitter-sendNotifications: "+i); - - sendNotification(notif); - } - } - - - } - - public interface NotificationEmitterMBean { - public void sendNotifications(Integer nb); - } - - private static int sendNB = 20; - private static int count = 0; - - private static final String myType = "notification.my_notification"; -} diff --git a/test/javax/management/eventService/MyFetchingEventForwarder.java b/test/javax/management/eventService/MyFetchingEventForwarder.java deleted file mode 100644 index 25d308af6..000000000 --- a/test/javax/management/eventService/MyFetchingEventForwarder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * MyList.java - * - * Created on Oct 23, 2007, 2:45:57 PM - * - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -/** - * - * @author sjiang - */ - -import java.io.IOException; -import java.util.ArrayList; -import javax.management.event.FetchingEventForwarder; - -public class MyFetchingEventForwarder extends FetchingEventForwarder { - - public MyFetchingEventForwarder() { - super(1000); - shared = this; - setList(myList); - } - - public void setAgain() { - setList(myList); - } - - public void setClientId(String clientId) throws IOException { - used = true; - super.setClientId(clientId); - } - - public boolean isUsed() { - return used; - } - - private class MyList - extends ArrayList { - - public boolean add(TargetedNotification e) { - used = true; - - return super.add(e); - } - } - - public MyList myList = new MyList(); - public static MyFetchingEventForwarder shared; - private boolean used = false; -} diff --git a/test/javax/management/eventService/NotSerializableNotifTest.java b/test/javax/management/eventService/NotSerializableNotifTest.java deleted file mode 100644 index 4185b4dd9..000000000 --- a/test/javax/management/eventService/NotSerializableNotifTest.java +++ /dev/null @@ -1,227 +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. - * - * 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. - */ - - -/* - * @test NotSerializableNotifTest.java 1.5 08/01/22 - * @bug 5108776 - * @summary Basic test for EventClient. - * @author Shanliang JIANG - * @run clean NotSerializableNotifTest - * @run build NotSerializableNotifTest - * @run main NotSerializableNotifTest - */ - - -// JMX imports -// -import javax.management.* ; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.EventRelay; -import javax.management.event.FetchingEventRelay; - -import javax.management.remote.*; -import javax.management.remote.JMXServiceURL; - -public class NotSerializableNotifTest { - private static MBeanServer mbeanServer = - MBeanServerFactory.createMBeanServer(); - private static ObjectName emitter; - private static int port = 2468; - - private static String[] protocols; - - private static final int sentNotifs = 50; - - public static void main(String[] args) throws Exception { - System.out.println(">>> Test to send a not serializable notification"); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - NotificationEmitter nm = new NotificationEmitter(); - emitter = new ObjectName("Default:name=NotificationEmitter"); - mbeanServer.registerMBean(nm, emitter); - String proto = "rmi"; - - System.out.println(">>> Test for protocol " + proto); - - JMXServiceURL url = new JMXServiceURL(proto, null, 0); - - JMXConnectorServer server = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer); - - server.start(); - - url = server.getAddress(); - JMXConnector conn = JMXConnectorFactory.connect(url, null); - MBeanServerConnection client = conn.getMBeanServerConnection(); - - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(client); - EventRelay eventRelay = new FetchingEventRelay( - ecd, - FetchingEventRelay.DEFAULT_BUFFER_SIZE, - 10, - FetchingEventRelay.DEFAULT_MAX_NOTIFICATIONS, - null); - EventClient ec = new EventClient(ecd, eventRelay, null, null, - EventClient.DEFAULT_REQUESTED_LEASE_TIME); - - // add listener from the client side - Listener listener = new Listener(); - ec.addNotificationListener(emitter, listener, null, null); - - LostListener lostListener = new LostListener(); - ec.addEventClientListener(lostListener, null, null); - - // ask to send one not serializable notif - System.out.println(">>> sending not serializable notifs ..."); - - Object[] params = new Object[] {new Integer(sentNotifs)}; - String[] signatures = new String[] {"java.lang.Integer"}; - client.invoke(emitter, "sendNotserializableNotifs", params, signatures); - -// nm.sendNotserializableNotifs(sentNotifs); -// nm.sendNotifications(1); - - // waiting - synchronized(lostListener) { - if (lostListener.lostCount != sentNotifs) { - lostListener.wait(6000); - } - } - - Thread.sleep(100); - - if (lostListener.lostCount != sentNotifs) { - System.out.println(">>> FAILED. Expected "+sentNotifs+", but got "+lostListener.lostCount); - System.exit(1); - } - - System.out.println(">>> Passed."); - - ec.close(); - conn.close(); - server.stop(); - } - - -//-------------------------- -// private classes -//-------------------------- - private static class Listener implements NotificationListener { - public void handleNotification(Notification n, Object handback) { - System.out.println(">>> Listener: receive: "+n); - } - } - - - private static class LostListener implements NotificationListener { - public void handleNotification(Notification n, Object handback) { - if (!EventClient.NOTIFS_LOST.equals(n.getType())) { - return; - } - - if (!(n.getUserData() instanceof Long)) { - System.out.println(">>> Listener: JMXConnectionNotification userData " + - "not a Long: " + n.getUserData()); - System.exit(1); - } else { - int lost = ((Long) n.getUserData()).intValue(); - lostCount += lost; - if (lostCount >= sentNotifs) { - synchronized(this) { - this.notifyAll(); - } - } - } - - } - - - private int lostCount = 0; - } - - public static class NotificationEmitter extends NotificationBroadcasterSupport - implements NotificationEmitterMBean { - - public MBeanNotificationInfo[] getNotificationInfo() { - final String[] ntfTypes = {myType}; - - final MBeanNotificationInfo[] ntfInfoArray = { - new MBeanNotificationInfo(ntfTypes, - "javax.management.Notification", - "Notifications sent by the NotificationEmitter")}; - - return ntfInfoArray; - } - - /** - * Send not serializable Notifications. - * - * @param nb The number of notifications to send - */ - public void sendNotserializableNotifs(Integer nb) { - - Notification notif; - for (int i=1; i<=nb.intValue(); i++) { - notif = new Notification(myType, this, i); - - notif.setUserData(new Object()); - sendNotification(notif); - } - } - - /** - * Send Notification objects. - * - * @param nb The number of notifications to send - */ - public void sendNotifications(Integer nb) { - Notification notif; - for (int i=1; i<=nb.intValue(); i++) { - notif = new Notification(myType, this, i); - - sendNotification(notif); - } - } - - private final String myType = "notification.my_notification"; - } - - public interface NotificationEmitterMBean { - public void sendNotifications(Integer nb); - - public void sendNotserializableNotifs(Integer nb); - } -} diff --git a/test/javax/management/eventService/PublishTest.java b/test/javax/management/eventService/PublishTest.java deleted file mode 100644 index c1e27b2d2..000000000 --- a/test/javax/management/eventService/PublishTest.java +++ /dev/null @@ -1,184 +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. - * - * 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. - */ - -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.*; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * - */ -public class PublishTest { - private static MBeanServer mbeanServer; - private static EventManager eventManager; - private static ObjectName emitter; - private static JMXServiceURL url; - private static JMXConnectorServer server; - private static JMXConnector conn; - private static MBeanServerConnection client; - - /** - * @param args the command line arguments - */ - public static void main(String[] args) throws Exception { - System.out.println(">>> PublishTest-main basic tests ..."); - mbeanServer = MBeanServerFactory.createMBeanServer(); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - } - - eventManager = EventManager.getEventManager(mbeanServer); - - emitter = new ObjectName("Default:name=NotificationEmitter"); - - url = new JMXServiceURL("rmi", null, 0) ; - server = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer); - server.start(); - - url = server.getAddress(); - conn = JMXConnectorFactory.connect(url, null); - client = conn.getMBeanServerConnection(); - - boolean succeed; - - System.out.println(">>> PublishTest-main: using the fetching EventRelay..."); - succeed = test(new EventClient(client)); - - System.out.println(">>> PublishTest-main: using the pushing EventRelay..."); - succeed &= test(new EventClient(client, - new RMIPushEventRelay(EventClientDelegate.getProxy(client)), - null, - EventClient.DEFAULT_LEASE_TIMEOUT)); - - conn.close(); - server.stop(); - - if (succeed) { - System.out.println(">>> PublishTest-main: PASSE!"); - } else { - System.out.println("\n>>> PublishTest-main: FAILED!"); - System.exit(1); - } - } - - public static boolean test(EventClient efClient) throws Exception { - // add listener from the client side - Listener listener = new Listener(); - efClient.subscribe(emitter, listener, null, null); - - ObjectName other = new ObjectName("Default:name=other"); - // publish notifs - for (int i=0; i>> EventManagerService-NotificationEmitter-sendNotifications: "+i); - - eventManager.publish(emitter, notif); - eventManager.publish(other, notif2); // should not received - } - - // waiting - long toWait = 6000; - long stopTime = System.currentTimeMillis() + toWait; - - synchronized(listener) { - while(listener.received < sendNB && toWait > 0) { - listener.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - // clean - efClient.unsubscribe(emitter, listener); - efClient.close(); - - if (listener.received != sendNB) { - System.out.println(">>> PublishTest-test: FAILED! Expected to receive "+sendNB+", but got "+listener.received); - - return false; - } else if (listener.seqErr > 0) { - System.out.println(">>> PublishTest-test: FAILED! The receiving sequence is not correct."); - - return false; - } else { - System.out.println(">>> PublishTest-test: got all expected "+listener.received); - return true; - } - } - - private static class Listener implements NotificationListener { - public int received = 0; - public int seqErr = 0; - - private long lastSeq = -1; - - public void handleNotification(Notification notif, Object handback) { - if (!myType.equals(notif.getType())) { - System.out.println(">>> PublishTest-Listener: got unexpected notif: "+notif); - System.exit(1); - } else if (!emitter.equals(notif.getSource())) { - System.out.println(">>> PublishTest-Listener: unknown ObjectName: "+notif.getSource()); - System.exit(1); - } - - if (lastSeq == -1) { - lastSeq = notif.getSequenceNumber(); - } else if (notif.getSequenceNumber() - lastSeq++ != 1) { - seqErr++; - } - - System.out.println(">>> PublishTest-Listener: got notif "+notif.getSequenceNumber()); - - synchronized(this) { - if (++received >= sendNB) { - this.notify(); - } - } - - System.out.println(">>> PublishTest-Listener: received = "+received); - } - } - - private static int sendNB = 20; - private static long count = 0; - - private static final String myType = "notification.my_notification"; -} diff --git a/test/javax/management/eventService/ReconnectableConnectorTest.java b/test/javax/management/eventService/ReconnectableConnectorTest.java deleted file mode 100644 index d4b156439..000000000 --- a/test/javax/management/eventService/ReconnectableConnectorTest.java +++ /dev/null @@ -1,488 +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. - * - * 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. - */ - -/* - * @test ReconnectableJMXConnector - * @bug 5108776 - * @summary Check that the Event Service can be used to build a - * ReconnectableJMXConnector. - * @author Eamonn McManus - */ - -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 java.util.Date; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; -import javax.security.auth.Subject; - -/* - * This test checks that it is possible to use the Event Service to create - * a "reconnectable connector". - * - * In the JMX Remote API, we deliberately specified that a connector client - * (JMXConnector) that encounters a network failure is then permanently broken. - * The idea being that adding recovery logic to the basic connector client - * would make it much more complicated and less reliable, and the logic would - * in any case never correspond to what a given situation needs. Some of - * the tough questions are: Should the connector try to mask the failure by - * blocking operations until the failure is resolved? How long should the - * connector try to reestablish the connection before giving up? Rather than - * try to solve this problem in the connector, we suggested that people who - * wanted to recover from network failures could implement the JMXConnector - * interface themselves so that it forwards to a wrapped JMXConnector that can - * be replaced in case of network failure. - * - * This works fine except that the connector client has state, - * in the form of listeners added by the user through the - * MBeanServerConnection.addNotificationListener method. It's possible - * for the wrapper to keep track of these listeners as well as forwarding - * them to the wrapped JMXConnector, so that it can reapply them to - * a replacement JMXConnector after failure recover. But it's quite - * tricky, particularly because of the two- and four-argument versions of - * removeNotificationListener. - * - * The Event Service can take care of this for you through the EventClient - * class. Listeners added through that class are implemented in a way that - * doesn't require the connector client to maintain any state, so they should - * continue to work transparently after replacing the wrapped JMXConnector. - * This test is a proof of concept that shows it works. Quite a number of - * details would need to be changed to build a reliable reconnectable - * connector. - * - * The test simulates network failure by rewrapping the wrapped JMXConnector's - * MBeanServerConnection (MBSC) in a "breakable" MBSC which we can cause - * to stop working. We do this in two phases. The first phase suspends - * any MBSC calls just at the point where they would return to the caller. - * The goal here is to block an EventClientDelegateMBean.fetchNotifications - * operation when it has received notifications but not yet delivered them - * to the EventClient. This is the most delicate point where a breakage - * can occur, because the EventClientDelegate must not drop those notifs - * from its buffer until another fetchNotifs call arrives with a later - * sequence number (which is an implicit ack of the previous set of - * notifs). Once the fetchNotifs call is suspended, we "kill" the MBSC, - * causing it to throw IOException from this and any other calls. That - * triggers the reconnect logic, which will make a new MBSC and issue - * the same fetchNotifs call to it. - * - * The test could be improved by synchronizing explicitly between the - * breakable MBSC and the mainline, so we only proceed to kill the MBSC - * when we are sure that the fetchNotifs call is blocked. As it is, - * we have a small delay which both ensures that no notifs are delivered - * while the connection is suspended, and if the machine is fast enough - * allows the fetchNotifs call to reach the blocking point. - */ -public class ReconnectableConnectorTest { - private static class ReconnectableJMXConnector implements JMXConnector { - private final JMXServiceURL url; - private AtomicReference wrappedJMXC = - new AtomicReference(); - private AtomicReference wrappedMBSC = - new AtomicReference(); - private final NotificationBroadcasterSupport broadcaster = - new NotificationBroadcasterSupport(); - private final Lock connectLock = new ReentrantLock(); - - ReconnectableJMXConnector(JMXServiceURL url) { - this.url = url; - } - - private class ReconnectIH implements InvocationHandler { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - try { - return method.invoke(wrappedMBSC.get(), args); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof IOException) { - connect(); - try { - return method.invoke(wrappedMBSC.get(),args); - } catch (InvocationTargetException ee) { - throw ee.getCause(); - } - } - throw e.getCause(); - } - } - } - - private class FailureListener implements NotificationListener { - public void handleNotification(Notification n, Object h) { - String type = n.getType(); - if (type.equals(JMXConnectionNotification.FAILED)) { - try { - connect(); - } catch (IOException e) { - broadcaster.sendNotification(n); - } - } else if (type.equals(JMXConnectionNotification.NOTIFS_LOST)) - broadcaster.sendNotification(n); - } - } - - public void connect() throws IOException { - connectLock.lock(); - try { - connectWithLock(); - } finally { - connectLock.unlock(); - } - } - - private void connectWithLock() throws IOException { - MBeanServerConnection mbsc = wrappedMBSC.get(); - if (mbsc != null) { - try { - mbsc.getDefaultDomain(); - return; // the connection works - } catch (IOException e) { - // OK: the connection doesn't work, so make a new one - } - } - // This is where we would need to add the fancy logic that - // allows the connection to keep failing for a while - // before giving up. - JMXConnector jmxc = JMXConnectorFactory.connect(url); - jmxc.addConnectionNotificationListener( - new FailureListener(), null, null); - wrappedJMXC.set(jmxc); - if (false) - wrappedMBSC.set(jmxc.getMBeanServerConnection()); - else { - mbsc = jmxc.getMBeanServerConnection(); - InvocationHandler ih = new BreakableIH(mbsc); - mbsc = (MBeanServerConnection) Proxy.newProxyInstance( - MBeanServerConnection.class.getClassLoader(), - new Class[] {MBeanServerConnection.class}, - ih); - wrappedMBSC.set(mbsc); - } - } - - private BreakableIH breakableIH() { - MBeanServerConnection mbsc = wrappedMBSC.get(); - return (BreakableIH) Proxy.getInvocationHandler(mbsc); - } - - void suspend() { - BreakableIH ih = breakableIH(); - ih.suspend(); - } - - void kill() throws IOException { - BreakableIH ih = breakableIH(); - wrappedJMXC.get().close(); - ih.kill(); - } - - public void connect(Map env) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - private final AtomicReference mbscRef = - new AtomicReference(); - - public MBeanServerConnection getMBeanServerConnection() - throws IOException { - connect(); - // Synchro here is not strictly correct: two threads could make - // an MBSC at the same time. OK for a test but beware for real - // code. - MBeanServerConnection mbsc = mbscRef.get(); - if (mbsc != null) - return mbsc; - mbsc = (MBeanServerConnection) Proxy.newProxyInstance( - MBeanServerConnection.class.getClassLoader(), - new Class[] {MBeanServerConnection.class}, - new ReconnectIH()); - mbsc = EventClient.getEventClientConnection(mbsc); - mbscRef.set(mbsc); - return mbsc; - } - - public MBeanServerConnection getMBeanServerConnection( - Subject delegationSubject) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void close() throws IOException { - wrappedJMXC.get().close(); - } - - public void addConnectionNotificationListener( - NotificationListener l, NotificationFilter f, Object h) { - broadcaster.addNotificationListener(l, f, h); - } - - public void removeConnectionNotificationListener(NotificationListener l) - throws ListenerNotFoundException { - broadcaster.removeNotificationListener(l); - } - - public void removeConnectionNotificationListener( - NotificationListener l, NotificationFilter f, Object h) - throws ListenerNotFoundException { - broadcaster.removeNotificationListener(l, f, h); - } - - public String getConnectionId() throws IOException { - return wrappedJMXC.get().getConnectionId(); - } - } - - // InvocationHandler that allows us to perform a two-phase "break" of - // an object. The first phase suspends the object, so that calls to - // it are blocked just before they return. The second phase unblocks - // suspended threads and causes them to throw IOException. - private static class BreakableIH implements InvocationHandler { - private final Object wrapped; - private final Holder state = new Holder("running"); - - BreakableIH(Object wrapped) { - this.wrapped = wrapped; - } - - void suspend() { - state.set("suspended"); - } - - void kill() { - state.set("killed"); - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - Object result; - try { - result = method.invoke(wrapped, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - String s = state.get(); - if (s.equals("suspended")) - state.waitUntilEqual("killed", 3, TimeUnit.SECONDS); - else if (s.equals("killed")) - throw new IOException("Broken"); - return result; - } - } - - private static class Holder { - private T held; - private Lock lock = new ReentrantLock(); - private Condition changed = lock.newCondition(); - - Holder(T value) { - lock.lock(); - this.held = value; - lock.unlock(); - } - - void waitUntilEqual(T value, long timeout, TimeUnit units) - throws InterruptedException { - long millis = units.toMillis(timeout); - long stop = System.currentTimeMillis() + millis; - Date stopDate = new Date(stop); - lock.lock(); - try { - while (!value.equals(held)) { - boolean ok = changed.awaitUntil(stopDate); - if (!ok) - throw new InterruptedException("Timed out"); - } - } finally { - lock.unlock(); - } - } - - void set(T value) { - lock.lock(); - try { - held = value; - changed.signalAll(); - } finally { - lock.unlock(); - } - } - - T get() { - lock.lock(); - try { - return held; - } finally { - lock.unlock(); - } - } - } - - private static class StoreListener implements NotificationListener { - final BlockingQueue queue = - new ArrayBlockingQueue(100); - - public void handleNotification(Notification n, Object h) { - queue.add(n); - } - - Notification nextNotification(long time, TimeUnit units) - throws InterruptedException { - Notification n = queue.poll(time, units); - if (n == null) - throw new NoSuchElementException("Notification wait timed out"); - return n; - } - - int notifCount() { - return queue.size(); - } - } - - public static interface SenderMBean {} - public static class Sender - extends NotificationBroadcasterSupport implements SenderMBean { - private AtomicLong seqNo = new AtomicLong(0); - - void send() { - Notification n = - new Notification("type", this, seqNo.getAndIncrement()); - sendNotification(n); - } - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - Sender sender = new Sender(); - ObjectName name = new ObjectName("a:b=c"); - mbs.registerMBean(sender, name); - - System.out.println("Creating connector server"); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///"); - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( - url, null, mbs); - cs.start(); - - StoreListener csListener = new StoreListener(); - cs.addNotificationListener(csListener, null, null); - - System.out.println("Creating reconnectable client"); - JMXServiceURL addr = cs.getAddress(); - ReconnectableJMXConnector cc = new ReconnectableJMXConnector(addr); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - - System.out.println("Checking server has sent new-client notif"); - Notification csn = csListener.nextNotification(1, TimeUnit.SECONDS); - assertEquals("CS notif type", - JMXConnectionNotification.OPENED, csn.getType()); - - StoreListener listener = new StoreListener(); - mbsc.addNotificationListener(name, listener, null, null); - - System.out.println("Sending 10 notifs and checking they are received"); - for (int i = 0; i < 10; i++) - sender.send(); - checkNotifs(listener, 0, 10); - - System.out.println("Suspending the fetchNotifs operation"); - cc.suspend(); - System.out.println("Sending a notif while fetchNotifs is suspended"); - sender.send(); - System.out.println("Brief wait before checking no notif is received"); - Thread.sleep(2); - // dumpThreads(); - assertEquals("notif queue while connector suspended", - 0, listener.notifCount()); - assertEquals("connector server notif queue while connector suspended", - 0, csListener.notifCount()); - - System.out.println("Breaking the connection so fetchNotifs will fail over"); - cc.kill(); - - System.out.println("Checking that client has reconnected"); - csn = csListener.nextNotification(1, TimeUnit.SECONDS); - assertEquals("First CS notif type after kill", - JMXConnectionNotification.CLOSED, csn.getType()); - csn = csListener.nextNotification(1, TimeUnit.SECONDS); - assertEquals("Second CS notif type after kill", - JMXConnectionNotification.OPENED, csn.getType()); - - System.out.println("Checking that suspended notif has been received"); - checkNotifs(listener, 10, 11); - } - - private static void checkNotifs( - StoreListener sl, long start, long stop) - throws Exception { - for (long i = start; i < stop; i++) { - Notification n = sl.nextNotification(1, TimeUnit.SECONDS); - assertEquals("received sequence number", i, n.getSequenceNumber()); - } - } - - private static void assertEquals(String what, Object expect, Object actual) - throws Exception { - if (!expect.equals(actual)) { - fail(what + " should be " + expect + " but is " + actual); - } - } - - private static void fail(String why) throws Exception { - throw new Exception("TEST FAILED: " + why); - } - - private static void dumpThreads() { - System.out.println("Thread stack dump"); - Map traces = Thread.getAllStackTraces(); - for (Map.Entry entry : traces.entrySet()) { - Thread t = entry.getKey(); - System.out.println("===Thread " + t.getName() + "==="); - for (StackTraceElement ste : entry.getValue()) - System.out.println(" " + ste); - } - } -} diff --git a/test/javax/management/eventService/SharingThreadTest.java b/test/javax/management/eventService/SharingThreadTest.java deleted file mode 100644 index 32c9dd3cf..000000000 --- a/test/javax/management/eventService/SharingThreadTest.java +++ /dev/null @@ -1,365 +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. - * - * 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. - */ - -/* - * @test SharingThreadTest.java 1.3 08/01/22 - * @bug 5108776 - * @summary Basic test for EventClient to see internal thread management. - * @author Shanliang JIANG - * @run clean SharingThreadTest - * @run build SharingThreadTest - * @run main SharingThreadTest - */ - -import java.io.IOException; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventClient; -import javax.management.event.EventClientDelegate; -import javax.management.event.EventClientDelegateMBean; -import javax.management.event.FetchingEventRelay; -import javax.management.event.RMIPushEventRelay; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - - -public class SharingThreadTest { - - private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer(); - private static ObjectName emitter; - private static NotificationEmitter emitterImpl; - private static JMXServiceURL url; - private static JMXConnectorServer server; - - - private static int toSend = 10; - private static final long bigWaiting = 6000; - private static int counter = 0; - private static int jobs = 10; - private static int endedJobs = 0; - - private static volatile String failure; - - private static Executor sharedExecutor = new ThreadPoolExecutor(0, 1, 1000, - TimeUnit.MILLISECONDS, new ArrayBlockingQueue(jobs)); - //Executors.newFixedThreadPool(1); - - public static void main(String[] args) throws Exception { - System.out.println(">>> Test on sharing threads for multiple EventClient."); - - // for 1.5 - if (System.getProperty("java.version").startsWith("1.5") && - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) { - System.out.print("Working on "+System.getProperty("java.version")+ - " register "+EventClientDelegateMBean.OBJECT_NAME); - - mbeanServer.registerMBean(EventClientDelegate. - getEventClientDelegate(mbeanServer), - EventClientDelegateMBean.OBJECT_NAME); - - sharedExecutor = new ThreadPoolExecutor(1, 1, 1000, - TimeUnit.MILLISECONDS, new ArrayBlockingQueue(jobs)); - } - - emitter = new ObjectName("Default:name=NotificationEmitter"); - emitterImpl = new NotificationEmitter(); - mbeanServer.registerMBean(emitterImpl, emitter); - - String[] types = new String[]{"PushEventRelay", "FetchingEventRelay"}; - String[] protos = new String[]{"rmi", "iiop", "jmxmp"}; - for (String prot : protos) { - url = new JMXServiceURL(prot, null, 0); - - try { - server = - JMXConnectorServerFactory.newJMXConnectorServer(url, - null, mbeanServer); - server.start(); - } catch (Exception e) { - System.out.println(">>> Skip "+prot+", not support."); - continue; - } - - url = server.getAddress(); - - // noise - Thread noise = new Thread(new Runnable() { - public void run() { - while (true) { - emitterImpl.sendNotif(1, null); - try { - Thread.sleep(10); - } catch (Exception e) { - // OK - } - } - } - }); - noise.setDaemon(true); - noise.start(); - - try { - for (String type: types) { - System.out.println("\n\n>>> Testing "+type+" on "+url+" ..."); - JMXConnector conn = newConn(); - try { - testType(type, conn); - } finally { - conn.close(); - System.out.println(">>> Testing "+type+" on "+url+" ... done"); - } - } - } finally { - server.stop(); - } - } - } - - private static void testType(String type, JMXConnector conn) throws Exception { - Thread[] threads = new Thread[jobs]; - for (int i=0; i 0 && failure == null) { - SharingThreadTest.class.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - - if (endedJobs != jobs && failure == null) { - throw new RuntimeException("Need to set bigger waiting timeout?"); - } - - endedJobs = 0; - } - - public static class Job implements Runnable { - public Job(String type, JMXConnector conn) { - this.type = type; - this.conn = conn; - } - public void run() { - try { - test(type, conn); - - synchronized(SharingThreadTest.class) { - endedJobs++; - if (endedJobs>=jobs) { - SharingThreadTest.class.notify(); - } - } - } catch (RuntimeException re) { - re.printStackTrace(System.out); - throw re; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private final String type; - private final JMXConnector conn; - } - - private static void test(String type, JMXConnector conn) throws Exception { - String id = getId(); - - Listener listener = new Listener(id); - Filter filter = new Filter(id); - - //newConn(); - EventClient ec = newEventClient(type, conn); - - System.out.println(">>> ("+id+") To receive notifications "+toSend); - ec.addNotificationListener(emitter, - listener, filter, null); - - emitterImpl.sendNotif(toSend, id); - listener.waitNotifs(bigWaiting, toSend); - if (listener.received != toSend) { - throw new RuntimeException(">>> ("+id+") Expected to receive: " - +toSend+", but got: "+listener.received); - } - - ec.close(); - } - -//-------------------------- -// private classes -//-------------------------- - - private static class Listener implements NotificationListener { - public Listener(String id) { - this.id = id; - } - public void handleNotification(Notification notif, Object handback) { - if (!id.equals(notif.getUserData())) { - System.out.println("("+id+") Filter error, my id is: "+id+ - ", but got "+notif.getUserData()); - System.exit(1); - } - System.out.println("("+id+") received "+notif.getSequenceNumber()); - synchronized (this) { - received++; - - if (sequenceNB < 0) { - sequenceNB = notif.getSequenceNumber(); - } else if(++sequenceNB != notif.getSequenceNumber()) { - fail("(" + id + ") Wrong sequence number, expected: " - +sequenceNB+", but got: "+notif.getSequenceNumber()); - } - if (received >= toSend || failure != null) { - this.notify(); - } - } - } - - public void waitNotifs(long timeout, int nb) throws Exception { - long toWait = timeout; - long stopTime = System.currentTimeMillis() + timeout; - synchronized(this) { - while (received < nb && toWait > 0 && failure == null) { - this.wait(toWait); - toWait = stopTime - System.currentTimeMillis(); - } - } - } - - private String id; - private int received = 0; - - private long sequenceNB = -1; - } - - private static class Filter implements NotificationFilter { - public Filter(String id) { - this.id = id; - } - - public boolean isNotificationEnabled(Notification n) { - return id.equals(n.getUserData()); - } - private String id; - } - - public static class NotificationEmitter extends NotificationBroadcasterSupport - implements NotificationEmitterMBean { - - /** - * Send Notification objects. - * - * @param nb The number of notifications to send - */ - public void sendNotif(int nb, String userData) { - new Thread(new SendJob(nb, userData)).start(); - } - - private class SendJob implements Runnable { - public SendJob(int nb, String userData) { - this.nb = nb; - this.userData = userData; - } - - public void run() { - if (userData != null) { - System.out.println(">>> ("+userData+") sending "+nb); - } - long sequenceNumber = 0; - for (int i = 0; i>> ("+userData+") sending done"); - } - } - private int nb; - private String userData; - } - private final String myType = "notification.my_notification"; - } - - public interface NotificationEmitterMBean { - public void sendNotif(int nb, String userData); - } - - private static JMXConnector newConn() throws IOException { - return JMXConnectorFactory.connect(url); - } - - private static EventClient newEventClient(String type, JMXConnector conn) - throws Exception { - EventClientDelegateMBean proxy = - EventClientDelegate.getProxy(conn.getMBeanServerConnection()); - if (type.equals("PushEventRelay")) { - return new EventClient(proxy, - new RMIPushEventRelay(proxy), sharedExecutor, null, 600); - } else if (type.equals("FetchingEventRelay")) { - return new EventClient(proxy, - new FetchingEventRelay(proxy, - FetchingEventRelay.DEFAULT_BUFFER_SIZE, - 10, - FetchingEventRelay.DEFAULT_MAX_NOTIFICATIONS, - sharedExecutor), - null, null, 600); - } else { - throw new RuntimeException("Wrong event client type: "+type); - } - } - - private static String getId() { - synchronized(SharingThreadTest.class) { - return String.valueOf(counter++); - } - } - - private static void fail(String msg) { - System.out.println("FAIL: " + msg); - failure = msg; - } -} diff --git a/test/javax/management/eventService/SubUnsubTest.java b/test/javax/management/eventService/SubUnsubTest.java deleted file mode 100644 index f88898823..000000000 --- a/test/javax/management/eventService/SubUnsubTest.java +++ /dev/null @@ -1,125 +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. - * - * 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. - */ - -/* - * @test SubUnsubTest - * @bug 6736611 - * @summary Test not to remove other listeners when calling unsubscribe - * @author Shanliang JIANG - * @run clean SubUnsubTest - * @run build SubUnsubTest - * @run main SubUnsubTest - */ - -import java.lang.management.ManagementFactory; -import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventSubscriber; -import javax.management.event.EventClient; -public class SubUnsubTest { - private static class CountListener implements NotificationListener { - volatile int count; - - public void handleNotification(Notification n, Object h) { - count++; - } - } - - public static interface SenderMBean {} - - public static class Sender extends NotificationBroadcasterSupport - implements SenderMBean { - void send() { - Notification n = new Notification("type", this, 1L); - sendNotification(n); - } - } - - public static void main(String[] args) throws Exception { - System.out.println("Testing EventSubscriber-unsubscribe method."); - - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName name1 = new ObjectName("d:type=Sender,id=1"); - ObjectName name2 = new ObjectName("d:type=Sender,id=2"); - ObjectName pattern = new ObjectName("d:type=Sender,*"); - Sender sender1 = new Sender(); - Sender sender2 = new Sender(); - mbs.registerMBean(sender1, name1); - mbs.registerMBean(sender2, name2); - - EventSubscriber sub = EventSubscriber.getEventSubscriber(mbs); - - System.out.println("Single subscribe covering both MBeans"); - CountListener listener = new CountListener(); - - System.out.println("Subscribing and adding listeners ..."); - sub.subscribe(pattern, listener, null, null); - sub.subscribe(name2, listener, null, null); - mbs.addNotificationListener(name2, listener, null, null); - - sender1.send(); - sender2.send(); - if (listener.count != 4) { - throw new RuntimeException("Do not receive all notifications: "+ - "Expect 4, got "+listener.count); - } - - System.out.println("Unsubscribe the listener with the pattern."); - sub.unsubscribe(pattern, listener); - listener.count = 0; - sender1.send(); - sender2.send(); - if (listener.count != 2) { - throw new RuntimeException("The method unsubscribe removes wrong listeners."); - } - - System.out.println("Unsubscribe the listener with the ObjectName."); - sub.unsubscribe(name2, listener); - listener.count = 0; - sender1.send(); - sender2.send(); - if (listener.count != 1) { - throw new RuntimeException("The method unsubscribe removes wrong listeners."); - } - - System.out.println("Subscribe twice to same MBean with same listener " + - "but different handback."); - sub.subscribe(name1, listener, null, new Object()); - sub.subscribe(name1, listener, null, new Object()); - listener.count = 0; - - sub.unsubscribe(name1, listener); - sender1.send(); - if (listener.count > 0) { - throw new RuntimeException("EventSubscriber: the method unsubscribe" + - " does not remove a listener which was subscribed 2 times."); - } - - System.out.println("Bye bye!"); - return; - } -} \ No newline at end of file diff --git a/test/javax/management/eventService/SubscribeTest.java b/test/javax/management/eventService/SubscribeTest.java deleted file mode 100644 index fa2df8dad..000000000 --- a/test/javax/management/eventService/SubscribeTest.java +++ /dev/null @@ -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. - * - * 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. - */ - -/* - * @test - * @bug 5108776 - * @summary Test that EventSubscriber.subscribe works - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventSubscriber; - -public class SubscribeTest { - private static class CountListener implements NotificationListener { - volatile int count; - - public void handleNotification(Notification n, Object h) { - count++; - } - } - - private static class SwitchFilter implements NotificationFilter { - volatile boolean enabled; - - public boolean isNotificationEnabled(Notification n) { - return enabled; - } - } - - public static interface SenderMBean {} - - public static class Sender extends NotificationBroadcasterSupport - implements SenderMBean { - void send() { - Notification n = new Notification("type", this, 1L); - sendNotification(n); - } - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName name1 = new ObjectName("d:type=Sender,id=1"); - ObjectName name2 = new ObjectName("d:type=Sender,id=2"); - ObjectName pattern = new ObjectName("d:type=Sender,*"); - Sender sender1 = new Sender(); - Sender sender2 = new Sender(); - mbs.registerMBean(sender1, name1); - mbs.registerMBean(sender2, name2); - - EventSubscriber sub = EventSubscriber.getEventSubscriber(mbs); - - System.out.println("Single subscribe covering both MBeans"); - CountListener listen1 = new CountListener(); - sub.subscribe(pattern, listen1, null, null); - sender1.send(); - assertEquals("Notifs after sender1 send", 1, listen1.count); - sender2.send(); - assertEquals("Notifs after sender2 send", 2, listen1.count); - - System.out.println("Unsubscribe"); - sub.unsubscribe(pattern, listen1); - sender1.send(); - assertEquals("Notifs after sender1 send", 2, listen1.count); - - System.out.println("Subscribe twice to same MBean with same listener " + - "but different filters"); - SwitchFilter filter1 = new SwitchFilter(); - sub.subscribe(name1, listen1, null, null); - sub.subscribe(name1, listen1, filter1, null); - listen1.count = 0; - sender1.send(); - // switch is off, so only one notif expected - assertEquals("Notifs after sender1 send", 1, listen1.count); - filter1.enabled = true; - sender1.send(); - // switch is on, so two more notifs expected - assertEquals("Notifs after sender1 send", 3, listen1.count); - - System.out.println("Remove those subscriptions"); - sub.unsubscribe(name1, listen1); - sender1.send(); - assertEquals("Notifs after sender1 send", 3, listen1.count); - } - - private static void assertEquals(String what, Object expected, Object actual) - throws Exception { - if (!equal(expected, actual)) { - String msg = "Expected " + expected + "; got " + actual; - throw new Exception("TEST FAILED: " + what + ": " + msg); - } - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null) - return false; - return (x.equals(y)); - } -} diff --git a/test/javax/management/eventService/UsingEventService.java b/test/javax/management/eventService/UsingEventService.java deleted file mode 100644 index b46ffe3f6..000000000 --- a/test/javax/management/eventService/UsingEventService.java +++ /dev/null @@ -1,107 +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. - * - * 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. - */ - -/* - * @test UsingEventService.java 1.10 08/01/22 - * @bug 5108776 - * @summary Basic test for EventManager. - * @author Shanliang JIANG - * @run clean UsingEventService - * @run build UsingEventService - * @run main UsingEventService - */ - -import java.util.HashMap; -import java.util.Map; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.event.EventConsumer; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class UsingEventService { - private static JMXServiceURL url; - private static JMXConnectorServer server; - private static JMXConnector conn; - private static MBeanServerConnection client; - - public static void main(String[] args) throws Exception { - if (System.getProperty("java.version").startsWith("1.5")) { - System.out.println(">>> UsingEventService-main not available for JDK1.5, bye"); - return; - } - - ObjectName oname = new ObjectName("test:t=t"); - Notification n = new Notification("", oname, 0); - - System.out.println(">>> UsingEventService-main basic tests ..."); - MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer(); - - url = new JMXServiceURL("rmi", null, 0) ; - JMXConnectorServer server = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer); - server.start(); - url = server.getAddress(); - - System.out.println(">>> UsingEventService-main test to not use the event service..."); - conn = JMXConnectorFactory.connect(url, null); - client = conn.getMBeanServerConnection(); - - System.out.println(">>> UsingEventService-main test to use the event service..."); - Map env = new HashMap(1); - env.put("jmx.remote.use.event.service", "true"); - conn = JMXConnectorFactory.connect(url, env); - client = conn.getMBeanServerConnection(); - - ((EventConsumer)client).subscribe(oname, listener, null, null); - - System.out.println(">>> UsingEventService-main using event service as expected!"); - - System.out.println(">>> UsingEventService-main test to use" + - " the event service with system property..."); - - System.setProperty("jmx.remote.use.event.service", "true"); - conn = JMXConnectorFactory.connect(url, null); - client = conn.getMBeanServerConnection(); - - ((EventConsumer)client).subscribe(oname, listener, null, null); - - System.out.println("" + - ">>> UsingEventService-main using event service as expected!"); - - System.out.println(">>> Happy bye bye!"); - } - - private final static NotificationListener listener = new NotificationListener() { - public void handleNotification(Notification n, Object hk) { - // - } - }; -} diff --git a/test/javax/management/interop/MBeanExceptionInteropTest.java b/test/javax/management/interop/MBeanExceptionInteropTest.java deleted file mode 100644 index dff6d9639..000000000 --- a/test/javax/management/interop/MBeanExceptionInteropTest.java +++ /dev/null @@ -1,166 +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. - * - * 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. - */ - -/* - * @test - * @bug 6456269 - * @summary Test that an MBeanException serialized on JDK 6 deserializes - * correctly on JDK 7. - * @author Eamonn McManus - */ - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import javax.management.MBeanException; - -// In JDK 6, the Throwable.cause field was always null for an MBeanException, -// but it didn't matter because we overrode getCause() to return -// MBeanException.exception instead. In JDK 7, we no longer override getCause() -// because MBeanException doubles as the serial form of GenericMBeanException. -// So we need some care to make sure that objects deserialized from JDK 6 -// have the right getCause() behaviour. -public class MBeanExceptionInteropTest { - private static final byte[] SERIALIZED_MBEAN_EXCEPTION = { - -84,-19,0,5,115,114,0,31,106,97,118,97,120,46,109,97, - 110,97,103,101,109,101,110,116,46,77,66,101,97,110,69,120, - 99,101,112,116,105,111,110,56,110,-116,-27,110,87,49,-50,2, - 0,1,76,0,9,101,120,99,101,112,116,105,111,110,116,0, - 21,76,106,97,118,97,47,108,97,110,103,47,69,120,99,101, - 112,116,105,111,110,59,120,114,0,28,106,97,118,97,120,46, - 109,97,110,97,103,101,109,101,110,116,46,74,77,69,120,99, - 101,112,116,105,111,110,4,-35,76,-20,-109,-99,126,113,2,0, - 0,120,114,0,19,106,97,118,97,46,108,97,110,103,46,69, - 120,99,101,112,116,105,111,110,-48,-3,31,62,26,59,28,-60, - 2,0,0,120,114,0,19,106,97,118,97,46,108,97,110,103, - 46,84,104,114,111,119,97,98,108,101,-43,-58,53,39,57,119, - -72,-53,3,0,3,76,0,5,99,97,117,115,101,116,0,21, - 76,106,97,118,97,47,108,97,110,103,47,84,104,114,111,119, - 97,98,108,101,59,76,0,13,100,101,116,97,105,108,77,101, - 115,115,97,103,101,116,0,18,76,106,97,118,97,47,108,97, - 110,103,47,83,116,114,105,110,103,59,91,0,10,115,116,97, - 99,107,84,114,97,99,101,116,0,30,91,76,106,97,118,97, - 47,108,97,110,103,47,83,116,97,99,107,84,114,97,99,101, - 69,108,101,109,101,110,116,59,120,112,113,0,126,0,8,116, - 0,7,79,104,32,100,101,97,114,117,114,0,30,91,76,106, - 97,118,97,46,108,97,110,103,46,83,116,97,99,107,84,114, - 97,99,101,69,108,101,109,101,110,116,59,2,70,42,60,60, - -3,34,57,2,0,0,120,112,0,0,0,2,115,114,0,27, - 106,97,118,97,46,108,97,110,103,46,83,116,97,99,107,84, - 114,97,99,101,69,108,101,109,101,110,116,97,9,-59,-102,38, - 54,-35,-123,2,0,4,73,0,10,108,105,110,101,78,117,109, - 98,101,114,76,0,14,100,101,99,108,97,114,105,110,103,67, - 108,97,115,115,113,0,126,0,6,76,0,8,102,105,108,101, - 78,97,109,101,113,0,126,0,6,76,0,10,109,101,116,104, - 111,100,78,97,109,101,113,0,126,0,6,120,112,0,0,0, - 63,116,0,25,77,66,101,97,110,69,120,99,101,112,116,105, - 111,110,73,110,116,101,114,111,112,84,101,115,116,116,0,30, - 77,66,101,97,110,69,120,99,101,112,116,105,111,110,73,110, - 116,101,114,111,112,84,101,115,116,46,106,97,118,97,116,0, - 5,119,114,105,116,101,115,113,0,126,0,12,0,0,0,46, - 113,0,126,0,14,113,0,126,0,15,116,0,4,109,97,105, - 110,120,115,114,0,34,106,97,118,97,46,108,97,110,103,46, - 73,108,108,101,103,97,108,65,114,103,117,109,101,110,116,69, - 120,99,101,112,116,105,111,110,-75,-119,115,-45,125,102,-113,-68, - 2,0,0,120,114,0,26,106,97,118,97,46,108,97,110,103, - 46,82,117,110,116,105,109,101,69,120,99,101,112,116,105,111, - 110,-98,95,6,71,10,52,-125,-27,2,0,0,120,113,0,126, - 0,3,113,0,126,0,21,116,0,3,66,97,100,117,113,0, - 126,0,10,0,0,0,2,115,113,0,126,0,12,0,0,0, - 62,113,0,126,0,14,113,0,126,0,15,113,0,126,0,16, - 115,113,0,126,0,12,0,0,0,46,113,0,126,0,14,113, - 0,126,0,15,113,0,126,0,18,120, - }; - - private static volatile String failure; - - public static void main(String[] args) throws Exception { - if (args.length > 0) { - if (args[0].equals("write") && args.length == 1) { - write(); - return; - } else { - System.err.println( - "Usage: java MBeanExceptionInteropTest"); - System.err.println( - "or: java MBeanExceptionInteropTest write"); - System.exit(1); - } - } - - // Read the serialized object and check it is correct. - ByteArrayInputStream bin = - new ByteArrayInputStream(SERIALIZED_MBEAN_EXCEPTION); - ObjectInputStream oin = new ObjectInputStream(bin); - MBeanException mbeanEx = (MBeanException) oin.readObject(); - assertEquals("MBeanException message", "Oh dear", mbeanEx.getMessage()); - System.out.println("getCause(): " + mbeanEx.getCause() + "; " + - "getTargetException(): " + mbeanEx.getTargetException()); - for (Throwable t : - new Throwable[] {mbeanEx.getCause(), mbeanEx.getTargetException()}) { - if (!(t instanceof IllegalArgumentException)) - fail("Nested exception not an IllegalArgumentException: " + t); - else - assertEquals("Nested exception message", "Bad", t.getMessage()); - } - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - // Write a file that can be inserted into this source file as the - // contents of the SERIALIZED_MBEAN_EXCEPTION array. Run this program - // on JDK 6 to generate the array, then test on JDK 7. - private static void write() throws Exception { - Exception wrapped = new IllegalArgumentException("Bad"); - MBeanException mbeanEx = new MBeanException(wrapped, "Oh dear"); - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - ObjectOutputStream oout = new ObjectOutputStream(bout); - oout.writeObject(mbeanEx); - oout.close(); - byte[] bytes = bout.toByteArray(); - for (int i = 0; i < bytes.length; i++) { - System.out.printf("%d,", bytes[i]); - if (i % 16 == 15) - System.out.println(); - } - if (bytes.length % 16 != 0) - System.out.println(); - } - - private static void assertEquals(String what, Object expect, Object actual) { - boolean equal = (expect == null) ? (actual == null) : expect.equals(actual); - if (equal) - System.out.println("OK: " + what + ": " + expect); - else - fail(what + ": expected " + expect + ", got " + actual); - } - - private static void fail(String why) { - System.out.println("FAIL: " + why); - failure = why; - } -} diff --git a/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java b/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java deleted file mode 100644 index 52eedee7f..000000000 --- a/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * @test - * @bug 6252592 4967755 - * @summary Check that default fields are correctly added to Descriptors - * and that input Descriptors are never modified - * @author Lars Westergren - */ - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import javax.management.Descriptor; -import javax.management.IntrospectionException; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; -import javax.management.MBeanException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanOperationInfo; -import javax.management.RuntimeOperationsException; -import javax.management.modelmbean.DescriptorSupport; -import javax.management.modelmbean.ModelMBeanAttributeInfo; -import javax.management.modelmbean.ModelMBeanConstructorInfo; -import javax.management.modelmbean.ModelMBeanInfo; -import javax.management.modelmbean.ModelMBeanInfoSupport; -import javax.management.modelmbean.ModelMBeanNotificationInfo; -import javax.management.modelmbean.ModelMBeanOperationInfo; - -/** - * Junit tests for bugs: - * 6252592 Provide for the user mandatory fields missing in Descriptor given - * to Model*Info constructors - * 4967755 ModelMBeanAttributeInfo constructor modifies its Descriptor argument - * - * @author Lars Westergren - */ -public class DefaultDescriptorFieldTest /*extends TestCase*/ { - public static void main(String[] args) throws Exception { - boolean fail = false; - Object test = new DefaultDescriptorFieldTest("Test"); - for (Method m : DefaultDescriptorFieldTest.class.getMethods()) { - if (m.getName().startsWith("test") && - m.getParameterTypes().length == 0) { - System.out.println("Testing " + m.getName()); - try { - m.invoke(test); - } catch (InvocationTargetException e) { - fail = true; - Throwable t = e.getCause(); - System.out.println("FAILED: exception: " + t); - t.printStackTrace(System.out); - } - } - } - if (fail) - throw new Exception("TEST FAILED"); - } - - //No check WHICH constructor is reflected, at least when the classes tested are constructed, - //so I just use first one that came to mind. - final Constructor[] constArr = String.class.getConstructors(); - final Constructor dummyConstructor = constArr[0]; - - - Method getMethod = null; - - /** Creates a new instance of MBeanTest */ - public DefaultDescriptorFieldTest(final String name) { - try { - getMethod = String.class.getMethod("toString"); - } catch (SecurityException ex) { - ex.printStackTrace(); - } catch (NoSuchMethodException ex) { - ex.printStackTrace(); - } - } - - /** - * Test instantiating the 5 different classes with a null - * Descriptor, and also setting a null descriptor after. - * Expected: Default Descriptors created. - */ - public void testNullDescriptors() - throws IntrospectionException, MBeanException { - final ModelMBeanConstructorInfo constInfo = - new ModelMBeanConstructorInfo("Dummy", dummyConstructor, null); - constInfo.setDescriptor(null); - ModelMBeanAttributeInfo attInfo = - new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null); - attInfo.setDescriptor(null); - ModelMBeanNotificationInfo notInfo = - new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", null); - notInfo.setDescriptor(null); - ModelMBeanOperationInfo opInfo = - new ModelMBeanOperationInfo("test", getMethod, null); - opInfo.setDescriptor(null); - ModelMBeanInfoSupport infoSupport = - new ModelMBeanInfoSupport(new DummyModelMBeanInfo()); - infoSupport.setDescriptor(null,null); - infoSupport.setDescriptor(null, "mbean"); - } - - /** - * Test instantiating and setting a Descriptor without the "name", - * "descriptorType" or "role" fields. This also tests whether the - * Descriptor is cloned before default values are set, since - * default values for one class will be incorrect for the next. - * Expected: Descriptor should be cloned, missing default values should be - * set - */ - public void testFieldlessDescriptor() - throws IntrospectionException, MBeanException { - Descriptor theNamelessOne = new DescriptorSupport(); - final ModelMBeanConstructorInfo constInfo = - new ModelMBeanConstructorInfo("Dummy", dummyConstructor, theNamelessOne); - constInfo.setDescriptor(theNamelessOne); - ModelMBeanAttributeInfo attInfo = - new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, theNamelessOne); - attInfo.setDescriptor(theNamelessOne); - ModelMBeanNotificationInfo notInfo = - new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", theNamelessOne); - notInfo.setDescriptor(theNamelessOne); - ModelMBeanOperationInfo opInfo = - new ModelMBeanOperationInfo("test", getMethod, theNamelessOne); - opInfo.setDescriptor(theNamelessOne); - ModelMBeanInfoSupport infoSupport = new ModelMBeanInfoSupport(new DummyModelMBeanInfo()); - infoSupport.setDescriptor(theNamelessOne, null); - infoSupport.setDescriptor(theNamelessOne, "mbean"); - } - - - /** - * Creates an empty DescriptorSupport and then test that ModelMBeanConstructorInfo accepts - * the correct fields in validation one by one. - */ - public void testCorrectConstructorDescriptors() - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Descriptor cDesc = new DescriptorSupport(new String[0],new String[0]); - final ModelMBeanConstructorInfo constInfo = - new ModelMBeanConstructorInfo("Dummy", dummyConstructor, cDesc); - assertFalse(fieldRefuted(constInfo, cDesc, "name" , "java.lang.String")); - assertFalse(fieldRefuted(constInfo, cDesc, "role" , "constructor")); - assertFalse(fieldRefuted(constInfo, cDesc, "descriptorType" , "operation")); - } - - /** - * Test that ModelMBeanConstructorInfo refutes incorrect fields in validation one by one. - */ - public void testIncorrectConstructorDescriptors() - throws NoSuchMethodException, IllegalAccessException { - Descriptor cDesc = new DescriptorSupport( - new String[] {"getMethod", "setMethod", "role", "Class", "name", "descriptorType"}, - new String[] {"dummyGetMethod", "dummySetMethod", "constructor", "dummyClass", "java.lang.String", "operation"}); - final ModelMBeanConstructorInfo constInfo = new ModelMBeanConstructorInfo("Dummy", dummyConstructor, cDesc); - assertTrue(fieldRefuted(constInfo, cDesc, "name" , "blah")); - assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "mbean")); - assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "notification")); - assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "constructor")); - assertTrue(fieldRefuted(constInfo, cDesc, "role", "operation")); - } - - public void testCorrectAttributeDescriptors() - throws IntrospectionException, NoSuchMethodException, IllegalAccessException { - Descriptor aDesc = new DescriptorSupport(new String[0],new String[0]); - final ModelMBeanAttributeInfo attInfo = new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null); - assertFalse(fieldRefuted(attInfo, aDesc, "name" , "dummyAttInfoName")); - assertFalse(fieldRefuted(attInfo, aDesc, "descriptorType" , "attribute")); - } - - public void testIncorrectAttributeDescriptors() - throws IntrospectionException, NoSuchMethodException, IllegalAccessException { - Descriptor aDesc = new DescriptorSupport(); - final ModelMBeanAttributeInfo attInfo = new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null); - assertTrue(fieldRefuted(attInfo, aDesc, "name" , "blah")); - assertTrue(fieldRefuted(attInfo, aDesc, "descriptorType" , "constructor")); - assertTrue(fieldRefuted(attInfo, aDesc, "descriptorType" , "notification")); - } - - public void testCorrectNotificationDescriptors() - throws NoSuchMethodException, IllegalAccessException { - Descriptor nDesc = new DescriptorSupport(); - final ModelMBeanNotificationInfo nInfo = new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", nDesc); - assertFalse(fieldRefuted(nInfo, nDesc, "name" , "notificationClassName")); - assertFalse(fieldRefuted(nInfo, nDesc, "descriptorType" , "notification")); - } - - public void testIncorrectNotificationDescriptors() - throws NoSuchMethodException, IllegalAccessException { - Descriptor nDesc = new DescriptorSupport(); - final ModelMBeanNotificationInfo nInfo = new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", nDesc); - assertTrue(fieldRefuted(nInfo, nDesc, "name" , "blah")); - assertTrue(fieldRefuted(nInfo, nDesc, "descriptorType" , "constructor")); - assertTrue(fieldRefuted(nInfo, nDesc, "descriptorType" , "operation")); - } - - public void testCorrectOperationDescriptors() - throws NoSuchMethodException, IllegalAccessException { - Descriptor opDesc = new DescriptorSupport(); - final ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo("test", "readable description", null, "type", 1, opDesc); - assertFalse(fieldRefuted(opInfo, opDesc, "name" , "test")); - assertFalse(fieldRefuted(opInfo, opDesc, "descriptorType" , "operation")); - assertFalse(fieldRefuted(opInfo, opDesc, "role" , "operation")); - assertFalse(fieldRefuted(opInfo, opDesc, "role" , "getter")); - assertFalse(fieldRefuted(opInfo, opDesc, "role" , "setter")); - } - - public void testIncorrectOperationDescriptors() - throws NoSuchMethodException, IllegalAccessException { - Descriptor opDesc = new DescriptorSupport(); - final ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo("test", "readable description", null, "type", 1, opDesc); - assertTrue(fieldRefuted(opInfo, opDesc, "name" , "DENIED!!")); - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "constructor")); - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "attribute")); - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "notification")); - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "x")); - } - - //TODO also test ModelMBeanInfoSupport perhaps. Slightly more difficult to set up and test. - - /** - * Clones descriptor, sets a new value in the clone and tries to apply clone to - * reflected Model*Info object method. The new field should be refuted if it - * is a bad value. - */ - //I like java, but this is one case where duck typing would have been slightly easier I think. :) - private boolean fieldRefuted(Object mbeanInfo, Descriptor desc, String fieldName, String newValue) - throws NoSuchMethodException, IllegalAccessException { - Method setDescMethod = mbeanInfo.getClass().getMethod("setDescriptor", Descriptor.class); - Descriptor newDesc = (Descriptor)desc.clone(); - boolean refused = false; - newDesc.setField(fieldName, newValue); - try { - setDescMethod.invoke(mbeanInfo, newDesc); - } catch (InvocationTargetException ex) { - //If we get classcast exception, someone passed in a bad object to reflection. - //Perhaps an unnecessary check, this cast? - RuntimeOperationsException rex = (RuntimeOperationsException)ex.getTargetException(); - refused = true; - } - return refused; - } - - /** - * Dummy class used to create test objects. May not be needed. - */ - private class DummyModelMBeanInfo implements ModelMBeanInfo { - public Descriptor[] getDescriptors(String inDescriptorType) - throws MBeanException, RuntimeOperationsException { - return null; - } - - public void setDescriptors(Descriptor[] inDescriptors) - throws MBeanException, RuntimeOperationsException { - - } - - public Descriptor getDescriptor(String inDescriptorName, String inDescriptorType) - throws MBeanException, RuntimeOperationsException { - return null; - } - - public void setDescriptor(Descriptor inDescriptor, String inDescriptorType) - throws MBeanException, RuntimeOperationsException { - - } - - public Descriptor getMBeanDescriptor() - throws MBeanException, RuntimeOperationsException { - return null; - } - - public void setMBeanDescriptor(Descriptor inDescriptor) - throws MBeanException, RuntimeOperationsException { - - } - - public ModelMBeanAttributeInfo getAttribute(String inName) - throws MBeanException, RuntimeOperationsException { - return null; - } - - public ModelMBeanOperationInfo getOperation(String inName) - throws MBeanException, RuntimeOperationsException { - return null; - } - - public ModelMBeanNotificationInfo getNotification(String inName) - throws MBeanException, RuntimeOperationsException { - return null; - } - - public MBeanAttributeInfo[] getAttributes() { - return null; - } - - public String getClassName() { - return "AnonMBeanInfoImpl"; - } - - public MBeanConstructorInfo[] getConstructors() { - return null; - } - - public String getDescription() { - return null; - } - - public MBeanNotificationInfo[] getNotifications() { - return null; - } - - public MBeanOperationInfo[] getOperations() { - return null; - } - - public Object clone() { - return null; - - } - - } - - private static void assertFalse(boolean x) { - assertTrue(!x); - } - - private static void assertTrue(boolean x) { - if (!x) - throw new AssertionError("Assertion failed"); - } - -} diff --git a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java index ee52aee9a..02f42e41c 100644 --- a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java +++ b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java @@ -32,9 +32,13 @@ * @run main AttributeArbitraryDataTypeTest */ +import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; import java.beans.SimpleBeanInfo; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import javax.management.AttributeNotFoundException; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.Notification; @@ -723,12 +727,49 @@ public class AttributeArbitraryDataTypeTest implements NotificationListener { System.out.println(message); } + public static Object elementFromComplex(Object complex, String element) + throws AttributeNotFoundException { + try { + if (complex.getClass().isArray() && element.equals("length")) { + return Array.getLength(complex); + } else if (complex instanceof CompositeData) { + return ((CompositeData) complex).get(element); + } else { + // Java Beans introspection + // + BeanInfo bi = java.beans.Introspector.getBeanInfo(complex.getClass()); + PropertyDescriptor[] pds = bi.getPropertyDescriptors(); + System.out.println("PDs: " + pds.length); + for (PropertyDescriptor pd : pds) { + System.out.println("Property: " + pd.getName()); + if (pd.getName().equals(element)) + return pd.getReadMethod().invoke(complex); + } + throw new AttributeNotFoundException( + "Could not find the getter method for the property " + + element + " using the Java Beans introspector"); + } + } catch (InvocationTargetException e) { + throw new IllegalArgumentException(e); + } catch (AttributeNotFoundException e) { + throw e; + } catch (Exception e) { + AttributeNotFoundException anfe = + new AttributeNotFoundException(e.getMessage()); + anfe.initCause(e); + throw anfe; + } + } + /* * Standalone entry point. * * Run the test and report to stdout. */ public static void main (String args[]) throws Exception { + Match match = Match.do_match_now; + String name = (String) elementFromComplex(match, "name"); + System.out.println("name: " + name); AttributeArbitraryDataTypeTest test = new AttributeArbitraryDataTypeTest(); int error = test.monitorNotifications(); diff --git a/test/javax/management/monitor/InstantiateMonitorNotificationTest.java b/test/javax/management/monitor/InstantiateMonitorNotificationTest.java deleted file mode 100644 index ae16858d2..000000000 --- a/test/javax/management/monitor/InstantiateMonitorNotificationTest.java +++ /dev/null @@ -1,52 +0,0 @@ - -import javax.management.ObjectName; -import javax.management.monitor.MonitorNotification; - -/* - * 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. - * - * 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. - */ - -/* - * @test - * @bug 6373143 - * @summary Test MonitorNotification public constructor - * @author JFDenise - * @run clean InstantiateMonitorNotificationTest - * @run build InstantiateMonitorNotificationTest - * @run main InstantiateMonitorNotificationTest - */ - -public class InstantiateMonitorNotificationTest { - - public static void main(String[] args) throws Exception { - MonitorNotification notif = new MonitorNotification("com.foo.test", - ObjectName.valueOf(":type=Monitor"), - 999, - 999, - "A message", - ObjectName.valueOf(":type=Observed"), - "MyAttribute", - Integer.valueOf(14), - Integer.valueOf(15)); - System.out.println("Test passed"); - } -} diff --git a/test/javax/management/mxbean/CustomTypeTest.java b/test/javax/management/mxbean/CustomTypeTest.java deleted file mode 100644 index 6da91330c..000000000 --- a/test/javax/management/mxbean/CustomTypeTest.java +++ /dev/null @@ -1,642 +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. - * - * 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. - */ - -/* @test %M% %I% - * @bug 6562936 6750935 - * @run compile customtypes/package-info.java - * @run main CustomTypeTest - */ - -import java.io.InvalidObjectException; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import javax.management.Descriptor; -import javax.management.MBeanServerInvocationHandler; -import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingClass; -import javax.management.openmbean.MXBeanMappingFactory; -import javax.management.openmbean.MXBeanMappingFactoryClass; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularData; - -import static javax.management.JMX.MBeanOptions; - -import customtypes.*; - -public class CustomTypeTest { - @MXBeanMappingClass(LinkedListMapping.class) - public static class LinkedList { - private final String name; - private final LinkedList next; - - public LinkedList(String name, LinkedList next) { - this.name = name; - this.next = next; - } - - public String getName() { - return name; - } - - public LinkedList getNext() { - return next; - } - - public String toString() { - if (next == null) - return "(" + name + ")"; - else - return "(" + name + " " + next + ")"; - } - - public boolean equals(Object x) { - if (!(x instanceof LinkedList)) - return false; - LinkedList other = (LinkedList) x; - return (this.name.equals(other.name) && - (this.next == null ? other.next == null : - this.next.equals(other.next))); - } - } - - public static class LinkedListMapping extends MXBeanMapping { - public LinkedListMapping(Type type) throws OpenDataException { - super(LinkedList.class, ArrayType.getArrayType(SimpleType.STRING)); - if (type != LinkedList.class) { - throw new OpenDataException("Mapping only valid for " + - LinkedList.class); - } - } - - public Object fromOpenValue(Object openValue) throws InvalidObjectException { - String[] array = (String[]) openValue; - LinkedList list = null; - for (int i = array.length - 1; i >= 0; i--) - list = new LinkedList(array[i], list); - return list; - } - - public Object toOpenValue(Object javaValue) throws OpenDataException { - ArrayList array = new ArrayList(); - for (LinkedList list = (LinkedList) javaValue; list != null; - list = list.getNext()) - array.add(list.getName()); - return array.toArray(new String[0]); - } - } - - public static interface LinkedListMXBean { - public LinkedList getLinkedList(); - } - - public static class LinkedListImpl implements LinkedListMXBean { - public LinkedList getLinkedList() { - return new LinkedList("car", new LinkedList("cdr", null)); - } - } - - public static class ObjectMXBeanMapping extends MXBeanMapping { - private static final CompositeType wildcardType; - - static { - try { - wildcardType = - new CompositeType(Object.class.getName(), - "Wildcard type for Object", - new String[0], // itemNames - new String[0], // itemDescriptions - new OpenType[0]); // itemTypes - } catch (OpenDataException e) { - throw new RuntimeException(e); - } - } - - public ObjectMXBeanMapping() { - super(Object.class, wildcardType); - } - - public Object fromOpenValue(Object openValue) throws InvalidObjectException { - if (!(openValue instanceof CompositeData)) { - throw new InvalidObjectException("Not a CompositeData: " + - openValue.getClass()); - } - CompositeData cd = (CompositeData) openValue; - if (!cd.containsKey("value")) { - throw new InvalidObjectException("CompositeData does not " + - "contain a \"value\" item: " + cd); - } - Object x = cd.get("value"); - if (!(x instanceof CompositeData || x instanceof TabularData || - x instanceof Object[])) - return x; - - String typeName = (String) cd.get("type"); - if (typeName == null) { - throw new InvalidObjectException("CompositeData does not " + - "contain a \"type\" item: " + cd); - } - Class c; - try { - c = Class.forName(typeName); - } catch (ClassNotFoundException e) { - InvalidObjectException ioe = - new InvalidObjectException("Could not find type"); - ioe.initCause(e); - throw ioe; - } - MXBeanMapping mapping; - try { - mapping = objectMappingFactory.mappingForType(c, objectMappingFactory); - } catch (OpenDataException e) { - InvalidObjectException ioe = - new InvalidObjectException("Could not map object's " + - "type " + c.getName()); - ioe.initCause(e); - throw ioe; - } - return mapping.fromOpenValue(x); - } - - public Object toOpenValue(Object javaValue) throws OpenDataException { - OpenType openType; - Object openValue; - String typeName; - if (javaValue == null) { - openType = SimpleType.VOID; - openValue = null; - typeName = null; - } else { - Class c = javaValue.getClass(); - if (c.equals(Object.class)) - throw new OpenDataException("Cannot map Object to an open value"); - MXBeanMapping mapping = - objectMappingFactory.mappingForType(c, objectMappingFactory); - openType = mapping.getOpenType(); - openValue = mapping.toOpenValue(javaValue); - typeName = c.getName(); - } - CompositeType ct = new CompositeType( - (javaValue == null) ? "null" : openType.getClassName(), - "Open Mapping for Object", - new String[] {"type", "value"}, - new String[] {"type", "value"}, - new OpenType[] {SimpleType.STRING, openType}); - return new CompositeDataSupport( - ct, - new String[] {"type", "value"}, - new Object[] {typeName, openValue}); - } - } - - public static class ObjectMappingFactory extends MXBeanMappingFactory { - private static MXBeanMapping objectMapping = - new ObjectMXBeanMapping(); - - @Override - public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f) - throws OpenDataException { - if (t.equals(Object.class)) - return objectMapping; - else - return MXBeanMappingFactory.DEFAULT.mappingForType(t, f); - } - } - - private static MXBeanMappingFactory objectMappingFactory = - new ObjectMappingFactory(); - - public static interface ObjectMXBean { - public Object getObject(); - public Object[] getObjects(); - public List getObjectList(); - public Object[][] getMoreObjects(); - } - - public static class ObjectImpl implements ObjectMXBean { - public Object getObject() { - return 123; - } - - private static Object[] objects = { - "foo", 3, 3.14f, 3.14, 3L, new Date(), ObjectName.WILDCARD, - new byte[3], new char[3], new int[3][3], - new LinkedListImpl().getLinkedList(), - }; - - public Object[] getObjects() { - return objects; - } - - public List getObjectList() { - return Arrays.asList(getObjects()); - } - - public Object[][] getMoreObjects() { - return new Object[][] {{getObjects()}}; - } - } - - @MXBeanMappingFactoryClass(ObjectMappingFactory.class) - public static interface AnnotatedObjectMXBean extends ObjectMXBean {} - - public static class AnnotatedObjectImpl extends ObjectImpl - implements AnnotatedObjectMXBean {} - - public static class BrokenMappingFactory extends MXBeanMappingFactory { - public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f) - throws OpenDataException { - throw new OpenDataException(t.toString()); - } - } - - public static class ReallyBrokenMappingFactory extends BrokenMappingFactory { - public ReallyBrokenMappingFactory() { - throw new RuntimeException("Oops"); - } - } - - @MXBeanMappingFactoryClass(BrokenMappingFactory.class) - public static interface BrokenMXBean { - public int getX(); - } - - public static class BrokenImpl implements BrokenMXBean { - public int getX() {return 0;} - } - - @MXBeanMappingFactoryClass(ReallyBrokenMappingFactory.class) - public static interface ReallyBrokenMXBean { - public int getX(); - } - - public static class ReallyBrokenImpl implements ReallyBrokenMXBean { - public int getX() {return 0;} - } - - public static class BrokenMapping extends MXBeanMapping { - public BrokenMapping(Type t) { - super(t, SimpleType.STRING); - throw new RuntimeException("Oops"); - } - - public Object fromOpenValue(Object openValue) throws InvalidObjectException { - throw new AssertionError(); - } - - public Object toOpenValue(Object javaValue) throws OpenDataException { - throw new AssertionError(); - } - } - - @MXBeanMappingClass(BrokenMapping.class) - public static class BrokenType {} - - public static interface BrokenTypeMXBean { - BrokenType getBroken(); - } - - public static class BrokenTypeImpl implements BrokenTypeMXBean { - public BrokenType getBroken() { - throw new AssertionError(); - } - } - - public static class BadConstructorMXBeanMappingFactory1 extends - MXBeanMappingFactory { - private BadConstructorMXBeanMappingFactory1() {} - - @Override - public MXBeanMapping mappingForType(Type arg0, MXBeanMappingFactory arg1) - throws OpenDataException { - throw new UnsupportedOperationException("Should not be called"); - } - } - - public static class BadConstructorMXBeanMappingFactory2 extends - MXBeanMappingFactory { - public BadConstructorMXBeanMappingFactory2(boolean oops) {} - - @Override - public MXBeanMapping mappingForType(Type arg0, MXBeanMappingFactory arg1) - throws OpenDataException { - throw new UnsupportedOperationException("Should not be called"); - } - } - - @MXBeanMappingFactoryClass(BadConstructorMXBeanMappingFactory1.class) - public static interface BadConstructor1MXBean {} - - public static class BadConstructor1 implements BadConstructor1MXBean {} - - @MXBeanMappingFactoryClass(BadConstructorMXBeanMappingFactory2.class) - public static interface BadConstructor2MXBean {} - - public static class BadConstructor2 implements BadConstructor2MXBean {} - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - - System.out.println("Test @MXBeanMappingClass"); - ObjectName linkedName = new ObjectName("d:type=LinkedList"); - LinkedListMXBean linkedListMXBean = new LinkedListImpl(); - LinkedList list1 = linkedListMXBean.getLinkedList(); - mbs.registerMBean(linkedListMXBean, linkedName); - LinkedListMXBean linkedProxy = - JMX.newMXBeanProxy(mbs, linkedName, LinkedListMXBean.class); - MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler) - Proxy.getInvocationHandler(linkedProxy); - if (!mbsih.isMXBean()) - fail("not MXBean proxy"); - LinkedList list2 = linkedProxy.getLinkedList(); - if (list1 == list2) - fail("lists identical!"); - // They should have gone through the mapping and back, - // and the mapping doesn't do anything that would allow it - // to restore the identical object. - if (!list1.equals(list2)) - fail("lists different: " + list1 + " vs " + list2); - System.out.println("...success"); - - System.out.println("Test StandardMBean with MXBeanMappingFactory"); - ObjectMXBean wildcardMBean = new ObjectImpl(); - MBeanOptions options = new MBeanOptions(); - options.setMXBeanMappingFactory(objectMappingFactory); - if (!options.isMXBean()) - fail("Setting MXBeanMappingFactory should imply MXBean"); - StandardMBean wildcardStandardMBean = - new StandardMBean(wildcardMBean, ObjectMXBean.class, options); - testWildcardMBean(mbs, wildcardMBean, wildcardStandardMBean, - options, ObjectMXBean.class); - - System.out.println("Test @MXBeanMappingFactoryClass on interface"); - ObjectMXBean annotatedWildcardMBean = new AnnotatedObjectImpl(); - testWildcardMBean(mbs, annotatedWildcardMBean, annotatedWildcardMBean, - null, AnnotatedObjectMXBean.class); - - System.out.println("Test @MXBeanMappingFactoryClass on package"); - CustomMXBean custom = zeroProxy(CustomMXBean.class); - ObjectName customName = new ObjectName("d:type=Custom"); - mbs.registerMBean(custom, customName); - Object x = mbs.getAttribute(customName, "X"); - if (!(x instanceof String)) - fail("Should be String: " + x + " (a " + x.getClass().getName() + ")"); - CustomMXBean customProxy = - JMX.newMXBeanProxy(mbs, customName, CustomMXBean.class); - x = customProxy.getX(); - if (!(x instanceof Integer) || (Integer) x != 0) - fail("Wrong return from proxy: " + x + " (a " + x.getClass().getName() + ")"); - - System.out.println("Test MXBeanMappingFactory exception"); - try { - mbs.registerMBean(new BrokenImpl(), new ObjectName("d:type=Broken")); - fail("Register did not throw exception"); - } catch (NotCompliantMBeanException e) { - System.out.println("...OK: threw: " + e); - } - - System.out.println("Test MXBeanMappingFactory constructor exception"); - try { - mbs.registerMBean(new ReallyBrokenImpl(), new ObjectName("d:type=Broken")); - fail("Register did not throw exception"); - } catch (NotCompliantMBeanException e) { - System.out.println("...OK: threw: " + e); - } catch (Exception e) { - fail("Register threw wrong exception: " + e); - } - - System.out.println("Test MXBeanMappingFactory exception with StandardMBean"); - MXBeanMappingFactory brokenF = new BrokenMappingFactory(); - MBeanOptions brokenO = new MBeanOptions(); - brokenO.setMXBeanMappingFactory(brokenF); - try { - new StandardMBean(wildcardMBean, ObjectMXBean.class, brokenO); - fail("StandardMBean with broken factory did not throw exception"); - } catch (IllegalArgumentException e) { - if (!(e.getCause() instanceof NotCompliantMBeanException)) { - fail("StandardMBean with broken factory threw wrong exception: " - + e.getCause()); - } - } - - System.out.println("Test MXBeanMappingClass exception"); - try { - mbs.registerMBean(new BrokenTypeImpl(), new ObjectName("d:type=Broken")); - fail("Broken MXBeanMappingClass did not throw exception"); - } catch (NotCompliantMBeanException e) { - System.out.println("...OK: threw: " + e); - } - - System.out.println("Test MXBeanMappingFactoryClass constructor exception"); - for (Object mbean : new Object[] { - new BadConstructor1(), new BadConstructor2(), - }) { - String testName = mbean.getClass().getSimpleName(); - try { - ObjectName name = new ObjectName("d:type=" + testName); - mbs.registerMBean(mbean, name); - fail("Broken MXBeanMappingFactoryClass did not throw exception" + - " (" + testName + ")"); - } catch (NotCompliantMBeanException e) { - System.out.println("...OK: " + testName + " threw: " + e); - } catch (Exception e) { - fail("Broken MXBeanMappingFactoryClass " + testName + " threw " + - "wrong exception: " + e); - } - } - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static void testWildcardMBean(MBeanServer mbs, ObjectMXBean impl, - Object mbean, - MBeanOptions proxyOptions, - Class intf) - throws Exception { - ObjectName wildcardName = new ObjectName("d:type=Object"); - mbs.registerMBean(mbean, wildcardName); - try { - testWildcardMBean2(mbs, impl, wildcardName, proxyOptions, intf); - } finally { - mbs.unregisterMBean(wildcardName); - } - } - - private static void testWildcardMBean2(MBeanServer mbs, ObjectMXBean impl, - ObjectName wildcardName, - MBeanOptions proxyOptions, - Class intf) - throws Exception { - if (proxyOptions == null) { - proxyOptions = new MBeanOptions(); - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface(intf); - proxyOptions.setMXBeanMappingFactory(f); - } - Descriptor d = mbs.getMBeanInfo(wildcardName).getDescriptor(); - String factoryName = (String) - d.getFieldValue(JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD); - if (!ObjectMappingFactory.class.getName().equals(factoryName)) { - fail("Descriptor has wrong MXBeanMappingFactory: " + factoryName + - " should be " + ObjectMappingFactory.class.getName()); - } - ObjectMXBean wildcardProxy = - JMX.newMBeanProxy(mbs, wildcardName, intf, proxyOptions); - MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler) - Proxy.getInvocationHandler(wildcardProxy); - MBeanOptions opts = mbsih.getMBeanOptions(); - if (!opts.equals(proxyOptions)) { - fail("Proxy options differ from request: " + opts + " vs " + - proxyOptions); - } - Method[] wildcardMethods = ObjectMXBean.class.getMethods(); - for (Method m : wildcardMethods) { - System.out.println("..." + m.getName()); - Object orig = m.invoke(impl); - Object copy = m.invoke(wildcardProxy); - if (!deepEquals(orig, copy)) { - fail("objects differ: " + deepToString(orig) + " vs " + - deepToString(copy)); - } - } - } - - private static T zeroProxy(Class intf) { - return intf.cast(Proxy.newProxyInstance(intf.getClassLoader(), - new Class[] {intf}, - new ZeroInvocationHandler())); - } - - private static class ZeroInvocationHandler implements InvocationHandler { - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - return 0; - } - } - - private static boolean deepEquals(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - - if (x instanceof Collection) { - if (!(y instanceof Collection)) - return false; - Collection xcoll = (Collection) x; - Collection ycoll = (Collection) y; - if (xcoll.size() != ycoll.size()) - return false; - Iterator xit = xcoll.iterator(); - Iterator yit = ycoll.iterator(); - while (xit.hasNext()) { - if (!deepEquals(xit.next(), yit.next())) - return false; - } - return true; - } - - Class xclass = x.getClass(); - Class yclass = y.getClass(); - if (xclass.isArray()) { - if (!yclass.isArray()) - return false; - if (!xclass.getComponentType().equals(yclass.getComponentType())) - return false; - int len = Array.getLength(x); - if (Array.getLength(y) != len) - return false; - for (int i = 0; i < len; i++) { - if (!deepEquals(Array.get(x, i), Array.get(y, i))) - return false; - } - return true; - } - -// return x.equals(y); - if (x.equals(y)) - return true; - System.out.println("Not equal: <" + x + "> and <" + y + ">"); - return false; - } - - private static String deepToString(Object x) { - if (x == null) - return "null"; - - if (x instanceof Collection) { - Collection xcoll = (Collection) x; - StringBuilder sb = new StringBuilder("["); - for (Object e : xcoll) { - if (sb.length() > 1) - sb.append(", "); - sb.append(deepToString(e)); - } - sb.append("]"); - return sb.toString(); - } - - if (x instanceof Object[]) { - Object[] xarr = (Object[]) x; - return deepToString(Arrays.asList(xarr)); - } - - if (x.getClass().isArray()) { // primitive array - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - return x.toString(); - } - - private static void fail(String msg) { - System.out.println("TEST FAILED: " + msg); - if (msg.length() > 100) - msg = msg.substring(0, 100) + "..."; - failure = msg; - } - - private static String failure; -} diff --git a/test/javax/management/mxbean/ExceptionDiagnosisTest.java b/test/javax/management/mxbean/ExceptionDiagnosisTest.java index d44e289ef..8db45976e 100644 --- a/test/javax/management/mxbean/ExceptionDiagnosisTest.java +++ b/test/javax/management/mxbean/ExceptionDiagnosisTest.java @@ -1,3 +1,26 @@ +/* + * 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. + * + * 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. + */ + /* * @test * @bug 6713777 @@ -180,7 +203,6 @@ public class ExceptionDiagnosisTest { private static void testCaseProb() throws Exception { MBeanServer mbs = MBeanServerFactory.newMBeanServer(); ObjectName name = new ObjectName("a:b=c"); - Object mbean = new CaseProbImpl(); mbs.registerMBean(new CaseProbImpl(), name); CaseProbMXBean proxy = JMX.newMXBeanProxy(mbs, name, CaseProbMXBean.class); try { diff --git a/test/javax/management/mxbean/JMXServiceURLTest.java b/test/javax/management/mxbean/JMXServiceURLTest.java deleted file mode 100644 index a688ee701..000000000 --- a/test/javax/management/mxbean/JMXServiceURLTest.java +++ /dev/null @@ -1,216 +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. - * - * 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. - */ - -/* - * @test JMXServiceURLTest - * @bug 6607114 6670375 6731410 - * @summary Test that JMXServiceURL works correctly in MXBeans - * @author Eamonn McManus - */ - -import java.io.InvalidObjectException; -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.management.Attribute; -import javax.management.JMX; -import javax.management.MBeanException; -import javax.management.MBeanServer; -import javax.management.ObjectName; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.remote.JMXServiceURL; - -public class JMXServiceURLTest { - public static interface UrlMXBean { - public JMXServiceURL getUrl(); - public void setUrl(JMXServiceURL url); - } - - public static class UrlImpl implements UrlMXBean { - volatile JMXServiceURL url; - - public JMXServiceURL getUrl() { - return url; - } - - public void setUrl(JMXServiceURL url) { - this.url = url; - } - } - - private static enum Part { - PROTOCOL("protocol", SimpleType.STRING, "rmi", 25, "", "a:b", "/", "?", "#"), - HOST("host", SimpleType.STRING, "a.b.c", 25, "a..b", ".a.b", "a.b."), - PORT("port", SimpleType.INTEGER, 25, "25", -25), - PATH("URLPath", SimpleType.STRING, "/tiddly", 25, "tiddly"); - - Part(String name, OpenType openType, Object validValue, Object... bogusValues) { - this.name = name; - this.openType = openType; - this.validValue = validValue; - this.bogusValues = bogusValues; - } - - final String name; - final OpenType openType; - final Object validValue; - final Object[] bogusValues; - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName name = new ObjectName("a:b=c"); - UrlImpl urlImpl = new UrlImpl(); - mbs.registerMBean(urlImpl, name); - - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://host:8000/noddy"); - UrlMXBean proxy = JMX.newMXBeanProxy(mbs, name, UrlMXBean.class); - proxy.setUrl(url); - assertEquals(url, urlImpl.url); - JMXServiceURL url2 = proxy.getUrl(); - assertEquals(url, url2); - - CompositeData cd = (CompositeData) mbs.getAttribute(name, "Url"); - CompositeType ct = cd.getCompositeType(); - // Make sure it looks like what we expect. This will have to be - // changed if ever we add new properties to CompositeType. In that - // case this test should also check interoperability between the - // current version and the new version. - assertEquals(4, ct.keySet().size()); - Object[][] expectedItems = { - {"protocol", SimpleType.STRING, "rmi"}, - {"host", SimpleType.STRING, "host"}, - {"port", SimpleType.INTEGER, 8000}, - {"URLPath", SimpleType.STRING, "/noddy"}, - }; - for (Object[] expectedItem : expectedItems) { - String itemName = (String) expectedItem[0]; - OpenType expectedType = (OpenType) expectedItem[1]; - Object expectedValue = expectedItem[2]; - OpenType actualType = ct.getType(itemName); - assertEquals(expectedType, actualType); - Object actualValue = cd.get(itemName); - assertEquals(expectedValue, actualValue); - } - - // Now make sure we reject any bogus-looking CompositeData items. - // We first try every combination of omitted items (items can be - // null but cannot be omitted), then we try every combination of - // valid and bogus items. - final Part[] parts = Part.values(); - final int nParts = parts.length; - final int maxPartMask = (1 << nParts) - 1; - // Iterate over all possibilities of included and omitted, except - // 0, because a CompositeDataSupport must have at least one element, - // and maxPartMask, where all items are included and the result is valid. - for (int mask = 1; mask < maxPartMask; mask++) { - Map cdMap = new HashMap(); - List names = new ArrayList(); - List types = new ArrayList(); - for (int i = 0; i < nParts; i++) { - if ((mask & (1 << i)) != 0) { - Part part = parts[i]; - cdMap.put(part.name, part.validValue); - names.add(part.name); - types.add(openTypeForValue(part.validValue)); - } - } - String[] nameArray = names.toArray(new String[0]); - OpenType[] typeArray = types.toArray(new OpenType[0]); - CompositeType badct = new CompositeType( - "bad", "descr", nameArray, nameArray, typeArray); - CompositeData badcd = new CompositeDataSupport(badct, cdMap); - checkBad(mbs, name, badcd); - } - - int nBogus = 1; - for (Part part : parts) - nBogus *= (part.bogusValues.length + 1); - // Iterate over all combinations of bogus values. We are basically - // treating each Part as a digit while counting up from 1. A digit - // value of 0 stands for the valid value of that Part, and 1 on - // stand for the bogus values. Hence an integer where all the digits - // are 0 would represent a valid CompositeData, which is why we - // start from 1. - for (int bogusCount = 1; bogusCount < nBogus; bogusCount++) { - List names = new ArrayList(); - List types = new ArrayList(); - int x = bogusCount; - Map cdMap = new HashMap(); - for (Part part : parts) { - int digitMax = part.bogusValues.length + 1; - int digit = x % digitMax; - Object value = (digit == 0) ? - part.validValue : part.bogusValues[digit - 1]; - cdMap.put(part.name, value); - names.add(part.name); - types.add(openTypeForValue(value)); - x /= digitMax; - } - String[] nameArray = names.toArray(new String[0]); - OpenType[] typeArray = types.toArray(new OpenType[0]); - CompositeType badct = new CompositeType( - "bad", "descr", nameArray, nameArray, typeArray); - CompositeData badcd = new CompositeDataSupport(badct, cdMap); - checkBad(mbs, name, badcd); - } - } - - private static OpenType openTypeForValue(Object value) { - if (value instanceof String) - return SimpleType.STRING; - else if (value instanceof Integer) - return SimpleType.INTEGER; - else - throw new AssertionError("Value has invalid type: " + value); - } - - private static void checkBad( - MBeanServer mbs, ObjectName name, CompositeData badcd) - throws Exception { - try { - mbs.setAttribute(name, new Attribute("Url", badcd)); - throw new Exception("Expected exception for: " + badcd); - } catch (MBeanException e) { - if (!(e.getCause() instanceof InvalidObjectException)) { - throw new Exception( - "Wrapped exception should be InvalidObjectException", e); - } - System.out.println("OK: rejected " + badcd); - } - } - - private static void assertEquals(Object expect, Object actual) - throws Exception { - if (expect.equals(actual)) - System.out.println("Equal: " + expect); - else - throw new Exception("Expected " + expect + ", got " + actual); - } -} diff --git a/test/javax/management/mxbean/customtypes/CustomLongMXBean.java b/test/javax/management/mxbean/customtypes/CustomLongMXBean.java deleted file mode 100644 index 5c1e4aef6..000000000 --- a/test/javax/management/mxbean/customtypes/CustomLongMXBean.java +++ /dev/null @@ -1,31 +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. - * - * 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. - */ - -// CustomLongMXBean.java - see CustomTypeTest - -package customtypes; - -import javax.management.openmbean.MXBeanMappingFactoryClass; - -@MXBeanMappingFactoryClass(IntegerIsLongFactory.class) -public interface CustomLongMXBean extends CustomMXBean {} diff --git a/test/javax/management/mxbean/customtypes/CustomMXBean.java b/test/javax/management/mxbean/customtypes/CustomMXBean.java deleted file mode 100644 index 0664827ca..000000000 --- a/test/javax/management/mxbean/customtypes/CustomMXBean.java +++ /dev/null @@ -1,30 +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. - * - * 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. - */ - -// CustomMXBean.java - see CustomTypeTest - -package customtypes; - -public interface CustomMXBean { - public Integer getX(); -} diff --git a/test/javax/management/mxbean/customtypes/IntegerIsLongFactory.java b/test/javax/management/mxbean/customtypes/IntegerIsLongFactory.java deleted file mode 100644 index e05d0d7b6..000000000 --- a/test/javax/management/mxbean/customtypes/IntegerIsLongFactory.java +++ /dev/null @@ -1,74 +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. - * - * 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. - */ - -// IntegerIsLongFactory.java - see CustomTypeTest - -package customtypes; - -import java.io.InvalidObjectException; -import java.lang.reflect.Type; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.SimpleType; - -public class IntegerIsLongFactory implements MXBeanMappingFactory { - public MXBeanMapping forType(Type t, MXBeanMappingFactory f) - throws OpenDataException { - if (t == Integer.class) - return IntegerIsLongMapping; - else - return MXBeanMappingFactory.DEFAULT.forType(t, f); - } - - private static final MXBeanMapping IntegerIsLongMapping = - new IntegerIsLongMapping(); - - private static class IntegerIsLongMapping extends MXBeanMapping { - IntegerIsLongMapping() { - super(Integer.class, SimpleType.STRING); - } - - public Object fromOpenValue(Object openValue) - throws InvalidObjectException { - try { - return (Long) openValue; - } catch (Exception e) { - InvalidObjectException ioe = new InvalidObjectException("oops"); - ioe.initCause(e); - throw ioe; - } - } - - public Object toOpenValue(Object javaValue) throws OpenDataException { - try { - Integer i = (Integer) javaValue; - return new Long((int) i); - } catch (Exception e) { - OpenDataException ode = new OpenDataException("oops"); - ode.initCause(e); - throw ode; - } - } - } -} diff --git a/test/javax/management/mxbean/customtypes/IntegerIsStringFactory.java b/test/javax/management/mxbean/customtypes/IntegerIsStringFactory.java deleted file mode 100644 index c044bd3af..000000000 --- a/test/javax/management/mxbean/customtypes/IntegerIsStringFactory.java +++ /dev/null @@ -1,76 +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. - * - * 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. - */ - -// IntegerIsStringFactory.java - see CustomTypeTest - -package customtypes; - -import java.io.InvalidObjectException; -import java.lang.reflect.Type; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.SimpleType; - -public class IntegerIsStringFactory extends MXBeanMappingFactory { - @Override - public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f) - throws OpenDataException { - if (t == Integer.class) - return integerIsStringMapping; - else - return MXBeanMappingFactory.DEFAULT.mappingForType(t, f); - } - - private static final MXBeanMapping integerIsStringMapping = - new IntegerIsStringMapping(); - - private static class IntegerIsStringMapping extends MXBeanMapping { - IntegerIsStringMapping() { - super(Integer.class, SimpleType.STRING); - } - - public Object fromOpenValue(Object openValue) - throws InvalidObjectException { - try { - String s = (String) openValue; - return Integer.parseInt(s); - } catch (Exception e) { - InvalidObjectException ioe = new InvalidObjectException("oops"); - ioe.initCause(e); - throw ioe; - } - } - - public Object toOpenValue(Object javaValue) throws OpenDataException { - try { - Integer i = (Integer) javaValue; - return i.toString(); - } catch (Exception e) { - OpenDataException ode = new OpenDataException("oops"); - ode.initCause(e); - throw ode; - } - } - } -} diff --git a/test/javax/management/mxbean/customtypes/package-info.java b/test/javax/management/mxbean/customtypes/package-info.java deleted file mode 100644 index c9e213dcb..000000000 --- a/test/javax/management/mxbean/customtypes/package-info.java +++ /dev/null @@ -1,27 +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. - * - * 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-info.java - test package annotations for custom types - -@javax.management.openmbean.MXBeanMappingFactoryClass(IntegerIsStringFactory.class) -package customtypes; diff --git a/test/javax/management/namespace/DomainCreationTest.java b/test/javax/management/namespace/DomainCreationTest.java deleted file mode 100644 index 02a09868e..000000000 --- a/test/javax/management/namespace/DomainCreationTest.java +++ /dev/null @@ -1,330 +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. - * - * 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. - */ -/* - * - * @test DomainCreationTest.java - * @bug 5072476 - * @summary Test the creation and registration of JMXDomain instances. - * @author Daniel Fuchs - * @run clean DomainCreationTest Wombat WombatMBean - * @run build DomainCreationTest Wombat WombatMBean - * @run main DomainCreationTest - */ - - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.InvalidAttributeValueException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.NotificationEmitter; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.ReflectionException; -import javax.management.RuntimeMBeanException; -import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXDomain; -import javax.management.namespace.MBeanServerSupport; - -/** - * Test simple creation/registration of namespace. - * - */ -public class DomainCreationTest { - private static Map emptyEnvMap() { - return Collections.emptyMap(); - } - - - public static class LocalDomainRepository - extends MBeanServerSupport { - private final MBeanServer server; - private final String domain; - - - public class DynamicMBeanProxy implements DynamicMBean { - - private final MBeanServer server; - private final ObjectName name; - - public DynamicMBeanProxy(MBeanServer s, ObjectName n) { - this.server = s; - this.name = n; - } - - public Object getAttribute(String attribute) - throws AttributeNotFoundException, - MBeanException, ReflectionException { - try { - return server.getAttribute(name, attribute); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public void setAttribute(Attribute attribute) - throws AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - try { - server.setAttribute(name, attribute); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public AttributeList getAttributes(String[] attributes) { - try { - return server.getAttributes(name, attributes); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public AttributeList setAttributes(AttributeList attributes) { - try { - return server.setAttributes(name, attributes); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public Object invoke(String actionName, Object[] params, - String[] signature) throws MBeanException, - ReflectionException { - try { - return server.invoke(name, actionName, params, signature); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public MBeanInfo getMBeanInfo() { - try { - return server.getMBeanInfo(name); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - } - - public LocalDomainRepository(String domain) { - this.server = MBeanServerFactory.newMBeanServer(); - this.domain = domain; - } - - @Override - protected Set getNames() { - try { - final ObjectName name = - ObjectName.getInstance(domain+":*"); - return server.queryNames(name, null); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - return new DynamicMBeanProxy(server, name); - } - - @Override - public NotificationEmitter - getNotificationEmitterFor(ObjectName name) - throws InstanceNotFoundException { - DynamicMBean mbean = getDynamicMBeanFor(name); - if (mbean instanceof NotificationEmitter) - return (NotificationEmitter) mbean; - return null; - } - - } - - private static MBeanServer newMBeanServer() { - return MBeanServerFactory.newMBeanServer(); - } - - public static interface ThingMBean {} - public static class Thing implements ThingMBean, MBeanRegistration { - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - if (name == null) return new ObjectName(":type=Thing"); - else return name; - } - public void postRegister(Boolean registrationDone) { - } - - public void preDeregister() throws Exception { - } - public void postDeregister() { - } - } - - /** - * Test that it is possible to create a dummy MBean with a null - * ObjectName - this is just a sanity check - as there are already - * other JMX tests that check that. - * - * @throws java.lang.Exception - */ - public static void testCreateWithNull() throws Exception { - final MBeanServer server = newMBeanServer(); - final ObjectInstance oi = server.registerMBean(new Thing(),null); - server.unregisterMBean(oi.getObjectName()); - System.out.println("testCreateWithNull PASSED"); - } - - /** - * Check that we can register a JMXNamespace MBean, using its standard - * ObjectName. - * @throws java.lang.Exception - */ - public static void testGoodObjectName() throws Exception { - MBeanServer server = newMBeanServer(); - final ObjectName name = - JMXDomain.getDomainObjectName("gloups"); - final ObjectInstance oi = - server.registerMBean(new JMXDomain( - new LocalDomainRepository("gloups")),name); - System.out.println("Succesfully registered namespace: "+name); - try { - if (! name.equals(oi.getObjectName())) - throw new RuntimeException("testGoodObjectName: TEST failed: " + - "namespace registered as: "+ - oi.getObjectName()+" expected: "+name); - } finally { - server.unregisterMBean(oi.getObjectName()); - } - System.out.println("Succesfully unregistered namespace: "+name); - System.out.println("testGoodObjectName PASSED"); - } - - /** - * Check that we cannot register a JMXNamespace MBean, if we don't use - * its standard ObjectName. - * @throws java.lang.Exception - */ - public static void testBadObjectName() throws Exception { - MBeanServer server = newMBeanServer(); - Throwable exp = null; - final ObjectName name = new ObjectName("d:k=v"); - try { - server.registerMBean(new JMXDomain( - new LocalDomainRepository("d")),name); - System.out.println("testBadObjectName: " + - "Error: MBean registered, no exception thrown."); - } catch(RuntimeMBeanException x) { - exp = x.getCause(); - } catch(Exception x) { - throw new RuntimeException("testBadObjectName: TEST failed: " + - "expected RuntimeMBeanException - got "+ - x); - } - if (exp == null) server.unregisterMBean(name); - if (exp == null) - throw new RuntimeException("testBadObjectName: TEST failed: " + - "expected IllegalArgumentException - got none"); - if (!(exp instanceof IllegalArgumentException)) - throw new RuntimeException("testBadObjectName: TEST failed: " + - "expected IllegalArgumentException - got "+ - exp.toString(),exp); - System.out.println("Got expected exception: "+exp); - System.out.println("testBadObjectName PASSED"); - } - - /** - * Check that we cannot register a Domain MBean in a domain that already - * exists. - * - * @throws java.lang.Exception - */ - public static void testBadDomain() throws Exception { - MBeanServer server = newMBeanServer(); - Throwable exp = null; - final ObjectName name = new ObjectName("glips:k=v"); - server.registerMBean(new Wombat(),name); - - final ObjectName dname = - JMXDomain.getDomainObjectName("glips"); - - try { - server.registerMBean(new JMXDomain( - new LocalDomainRepository("glips")),dname); - System.out.println("testBadDomain: " + - "Error: MBean registered, no exception thrown."); - } catch(RuntimeOperationsException x) { - exp = x.getCause(); - } catch(Exception x) { - throw new RuntimeException("testBadDomain: TEST failed: " + - "expected RuntimeOperationsException - got "+ - x); - } finally { - server.unregisterMBean(name); - } - if (exp == null) { - server.unregisterMBean(dname); - } - if (exp == null) - throw new RuntimeException("testBadDomain: TEST failed: " + - "expected IllegalArgumentException - got none"); - if (!(exp instanceof IllegalArgumentException)) - throw new RuntimeException("testBadDomain: TEST failed: " + - "expected IllegalArgumentException - got "+ - exp.toString(),exp); - System.out.println("Got expected exception: "+exp); - System.out.println("testBadDomain PASSED"); - } - - - public static void main(String... args) throws Exception { - testCreateWithNull(); - testGoodObjectName(); - testBadObjectName(); - testBadDomain(); - } -} diff --git a/test/javax/management/namespace/EventWithNamespaceControlTest.java b/test/javax/management/namespace/EventWithNamespaceControlTest.java deleted file mode 100644 index 9bfa9866d..000000000 --- a/test/javax/management/namespace/EventWithNamespaceControlTest.java +++ /dev/null @@ -1,94 +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. - * - * 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. - */ - -/* - * - * @test EventWithNamespaceControlTest.java - * @summary Check -Djmx.remote.use.event.service=true and - * -Djmx.remote.delegate.event.service - * @author Daniel Fuchs - * @bug 5072476 5108776 - * @run clean EventWithNamespaceTest EventWithNamespaceControlTest - * Wombat WombatMBean JMXRemoteTargetNamespace - * NamespaceController NamespaceControllerMBean - * @compile -XDignore.symbol.file=true EventWithNamespaceTest.java - EventWithNamespaceControlTest.java - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java - * NamespaceController.java NamespaceControllerMBean.java - * @run main/othervm -Djmx.remote.use.event.service=true EventWithNamespaceControlTest - * @run main/othervm EventWithNamespaceControlTest - * @run main/othervm -Djmx.remote.delegate.event.service=false EventWithNamespaceControlTest java.lang.UnsupportedOperationException - */ - -import java.util.Collections; -import java.util.Map; -import java.util.logging.Logger; -import javax.management.RuntimeOperationsException; - -/** - * - * @author Sun Microsystems, Inc. - */ -public class EventWithNamespaceControlTest extends EventWithNamespaceTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(EventWithNamespaceControlTest.class.getName()); - - /** Creates a new instance of EventWithNamespaceTest */ - public EventWithNamespaceControlTest() { - } - - - - public static void main(String[] args) { - final EventWithNamespaceControlTest test = - new EventWithNamespaceControlTest(); - if (args.length == 0) { - test.run(args); - System.out.println("Test successfully passed"); - } else { - try { - test.run(args); - throw new RuntimeException("Test should have failed."); - } catch (RuntimeOperationsException x) { - if (! args[0].equals(x.getCause().getClass().getName())) { - System.err.println("Unexpected wrapped exception: "+ - x.getCause()); - throw x; - } else { - System.out.println("Got expected exception: "+x.getCause()); - } - } - } - } - - @Override - public Map getServerMap() { - Map retValue = Collections.emptyMap(); - return retValue; - } - -} diff --git a/test/javax/management/namespace/EventWithNamespaceTest.java b/test/javax/management/namespace/EventWithNamespaceTest.java deleted file mode 100644 index 748fdbeff..000000000 --- a/test/javax/management/namespace/EventWithNamespaceTest.java +++ /dev/null @@ -1,241 +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. - * - * 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. - */ - -/* - * - * @test EventWithNamespaceTest.java 1.8 - * @bug 6539857 5072476 5108776 - * @summary General Namespace & Notifications test. - * @author Daniel Fuchs - * @run clean EventWithNamespaceTest Wombat WombatMBean - * JMXRemoteTargetNamespace - * NamespaceController NamespaceControllerMBean - * @compile -XDignore.symbol.file=true EventWithNamespaceTest.java - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java - * NamespaceController.java NamespaceControllerMBean.java - * @run main EventWithNamespaceTest - */ - -import java.lang.management.ManagementFactory; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Logger; - -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * - * @author Sun Microsystems, Inc. - */ -public class EventWithNamespaceTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(EventWithNamespaceTest.class.getName()); - - /** Creates a new instance of EventWithNamespaceTest */ - public EventWithNamespaceTest() { - } - - private static Map singletonMap(String key, Object value) { - final Map map = new HashMap(); - map.put(key,value); - return map; - } - - public Map getServerMap() { - return singletonMap(JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE,"true"); - } - - public JMXServiceURL export(MBeanServer server) - throws Exception { - final JMXServiceURL in = new JMXServiceURL("rmi",null,0); - final Map env = getServerMap(); - - final JMXConnectorServer cs = - JMXConnectorServerFactory.newJMXConnectorServer(in,env,null); - final ObjectName csname = ObjectName. - getInstance(cs.getClass().getPackage().getName()+ - ":type="+cs.getClass().getSimpleName()); - server.registerMBean(cs,csname); - cs.start(); - return cs.getAddress(); - } - - public static class Counter { - int count; - public synchronized int count() { - count++; - notifyAll(); - return count; - } - public synchronized int peek() { - return count; - } - public synchronized int waitfor(int max, long timeout) - throws InterruptedException { - final long start = System.currentTimeMillis(); - while (count < max && timeout > 0) { - final long rest = timeout - - (System.currentTimeMillis() - start); - if (rest <= 0) break; - wait(rest); - } - return count; - } - } - - public static class CounterListener - implements NotificationListener { - final private Counter counter; - public CounterListener(Counter counter) { - this.counter = counter; - } - public void handleNotification(Notification notification, - Object handback) { - System.out.println("Received notif from " + handback + - ":\n\t" + notification); - if (!notification.getSource().equals(handback)) { - System.err.println("OhOh... Unexpected source: \n\t"+ - notification.getSource()+"\n\twas expecting:\n\t"+ - handback); - } - counter.count(); - } - } - - public void simpleTest(String[] args) { - try { - final MBeanServer server1 = - ManagementFactory.getPlatformMBeanServer(); - final JMXServiceURL url1 = export(server1); - - final MBeanServer server2 = - MBeanServerFactory.createMBeanServer("server2"); - final JMXServiceURL url2 = export(server2); - - final MBeanServer server3 = - MBeanServerFactory.createMBeanServer("server3"); - final JMXServiceURL url3 = export(server3); - - final ObjectInstance ncinst = - NamespaceController.createInstance(server1); - - final NamespaceControllerMBean nc = - JMX.newMBeanProxy(server1,ncinst.getObjectName(), - NamespaceControllerMBean.class); - - final String mount2 = nc.mount(url2,"server2",null); - final String mount3 = nc.mount(url3,"server2//server3", - null); - - final ObjectName deep = - new ObjectName("server2//server3//bush:type=Wombat,name=kanga"); - server1.createMBean(Wombat.class.getName(),deep); - - System.err.println("There's a wombat in the bush!"); - - final Counter counter = new Counter(); - - final NotificationListener listener = - new CounterListener(counter); - - final JMXConnector jc = JMXConnectorFactory.connect(url1); - final MBeanServerConnection conn1 = - jc.getMBeanServerConnection(); - final ObjectName shallow = - new ObjectName("bush:"+ - deep.getKeyPropertyListString()); - final MBeanServerConnection conn2 = - JMXNamespaces.narrowToNamespace(conn1,"server2//server3"); - - final WombatMBean proxy1 = - JMX.newMBeanProxy(conn1,deep,WombatMBean.class,true); - final WombatMBean proxy2 = - JMX.newMBeanProxy(conn2,shallow,WombatMBean.class,true); - - - System.err.println("Adding first Notification Listener"); - conn1.addNotificationListener(deep,listener,null,deep); - System.err.println("Adding second Notification Listener"); - ((NotificationEmitter)proxy2). - addNotificationListener(listener,null,shallow); - final JMXConnector c3 = JMXConnectorFactory.connect(url3, - singletonMap(JMXConnector.USE_EVENT_SERVICE,"false")); - System.err.println("Adding third Notification Listener"); - c3.getMBeanServerConnection(). - addNotificationListener(shallow,listener,null,shallow); - System.err.println("Set attribute to trigger notif"); - proxy1.setCaption("I am a new Wombat!"); - System.err.println("Get attribute"); - System.err.println("New caption: "+proxy2.getCaption()); - System.err.println("Wait for Notifs..."); - final int rcvcount = counter.waitfor(3,3000); - if (rcvcount != 3) - throw new RuntimeException("simpleTest failed: "+ - "received count is " +rcvcount); - System.err.println("simpleTest: got expected "+rcvcount+ - " notifs"); - - System.err.println("removing all listeners"); - conn1.removeNotificationListener(deep,listener,null,deep); - ((NotificationEmitter)proxy2) - .removeNotificationListener(listener,null,shallow); - c3.getMBeanServerConnection(). - removeNotificationListener(shallow,listener,null,shallow); - - System.err.println("simpleTest passed: got "+rcvcount+ - " notifs"); - - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException("simpleTest failed: " + x,x); - } - } - - public void run(String[] args) { - simpleTest(args); - } - - public static void main(String[] args) { - new EventWithNamespaceTest().run(args); - } - -} diff --git a/test/javax/management/namespace/ExportNamespaceTest.java b/test/javax/management/namespace/ExportNamespaceTest.java deleted file mode 100644 index ec49a4c0c..000000000 --- a/test/javax/management/namespace/ExportNamespaceTest.java +++ /dev/null @@ -1,100 +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. - * - * 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. - */ -/* - * - * @test ExportNamespaceTest.java - * @summary Test that you can export a single namespace through a - * JMXConnectorServer. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean ExportNamespaceTest Wombat WombatMBean - * @run build ExportNamespaceTest Wombat WombatMBean - * @run main ExportNamespaceTest - */ - -import javax.management.JMX; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - - -/** - * Test simple creation/registration of namespace. - * - */ -public class ExportNamespaceTest { - - public static void testExport() throws Exception { - final JMXNamespace my = - new JMXNamespace(MBeanServerFactory.newMBeanServer()); - final MBeanServer s = MBeanServerFactory.newMBeanServer(); - final ObjectName myname = JMXNamespaces.getNamespaceObjectName("my"); - final ObjectName wname = ObjectName.getInstance("backyard:type=Wombat"); - my.getSourceServer().registerMBean(new Wombat(),wname); - s.registerMBean(my,myname); - - if (!s.queryNames(new ObjectName("my//b*:*"),null).contains( - JMXNamespaces.insertPath("my", wname))) { - throw new RuntimeException("1: Wombat not found: "+wname); - } - - final MBeanServer cd = JMXNamespaces.narrowToNamespace(s, "my"); - if (!cd.queryNames(new ObjectName("b*:*"),null).contains(wname)) { - throw new RuntimeException("2: Wombat not found: "+wname); - } - - final JMXServiceURL url = new JMXServiceURL("rmi",null,0); - final JMXConnectorServer server = - JMXConnectorServerFactory.newJMXConnectorServer(url, null, cd); - server.start(); - - final JMXConnector jc = JMXConnectorFactory. - connect(server.getAddress(),null); - final MBeanServerConnection mbsc = jc.getMBeanServerConnection(); - - if (!mbsc.queryNames(new ObjectName("b*:*"),null).contains(wname)) { - throw new RuntimeException("3: Wombat not found: "+wname); - } - System.out.println("Found a Wombat in my backyard."); - - final String deepThoughts = "I want to leave this backyard!"; - final WombatMBean w = JMX.newMBeanProxy(mbsc, wname, WombatMBean.class); - w.setCaption(deepThoughts); - if (!deepThoughts.equals(w.getCaption())) - throw new RuntimeException("4: Wombat is not thinking right: "+ - w.getCaption()); - - } - - public static void main(String... args) throws Exception { - testExport(); - } -} diff --git a/test/javax/management/namespace/JMXDomainTest.java b/test/javax/management/namespace/JMXDomainTest.java deleted file mode 100644 index 258cead1a..000000000 --- a/test/javax/management/namespace/JMXDomainTest.java +++ /dev/null @@ -1,513 +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. - * - * 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. - */ -/* - * - * @test JMXDomainTest.java - * @bug 5072476 - * @summary Basic test for JMXDomain. - * @author Daniel Fuchs - * @run clean JMXDomainTest Wombat WombatMBean - * @run build JMXDomainTest Wombat WombatMBean - * @run main JMXDomainTest - */ - - -import java.util.Collections; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.Map; -import java.util.Set; -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.InvalidAttributeValueException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; -import javax.management.MBeanServerNotification; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.ReflectionException; -import javax.management.namespace.JMXDomain; -import javax.management.namespace.MBeanServerSupport; - -/** - * Test simple creation/registration of namespace. - * - */ -public class JMXDomainTest { - private static Map emptyEnvMap() { - return Collections.emptyMap(); - } - - - public static class LocalDomainRepository - extends MBeanServerSupport { - private final MBeanServer server; - private final String domain; - - public class DynamicMBeanProxy implements DynamicMBean { - - private final MBeanServer server; - private final ObjectName name; - - public DynamicMBeanProxy(MBeanServer s, ObjectName n) { - this.server = s; - this.name = n; - } - - public Object getAttribute(String attribute) - throws AttributeNotFoundException, - MBeanException, ReflectionException { - try { - return server.getAttribute(name, attribute); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public void setAttribute(Attribute attribute) - throws AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, - ReflectionException { - try { - server.setAttribute(name, attribute); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public AttributeList getAttributes(String[] attributes) { - try { - return server.getAttributes(name, attributes); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public AttributeList setAttributes(AttributeList attributes) { - try { - return server.setAttributes(name, attributes); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public Object invoke(String actionName, Object[] params, - String[] signature) throws MBeanException, - ReflectionException { - try { - return server.invoke(name, actionName, params, signature); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - public MBeanInfo getMBeanInfo() { - try { - return server.getMBeanInfo(name); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - } - - public LocalDomainRepository(String domain) { - this.server = MBeanServerFactory.newMBeanServer(); - this.domain = domain; - } - - @Override - protected Set getNames() { - try { - final ObjectName name = - ObjectName.getInstance(domain+":*"); - return server.queryNames(name, null); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException(x); - } - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (server.isRegistered(name)) - return new DynamicMBeanProxy(server, name); - throw new InstanceNotFoundException(name); - } - - - @Override - public NotificationEmitter - getNotificationEmitterFor(final ObjectName name) - throws InstanceNotFoundException { - if (server.isInstanceOf(name, NotificationEmitter.class.getName())) { - return new NotificationEmitter() { - - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { - try { - server.removeNotificationListener(name, listener, filter, handback); - } catch (InstanceNotFoundException x) { - throw new IllegalArgumentException(String.valueOf(name), x); - } - } - - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { - try { - server.addNotificationListener(name, listener, filter, handback); - } catch (InstanceNotFoundException x) { - throw new IllegalArgumentException(String.valueOf(name), x); - } - } - - public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { - try { - server.removeNotificationListener(name, listener); - } catch (InstanceNotFoundException x) { - throw new IllegalArgumentException(String.valueOf(name), x); - } - } - - public MBeanNotificationInfo[] getNotificationInfo() { - try { - return server.getMBeanInfo(name).getNotifications(); - } catch (Exception x) { - throw new IllegalArgumentException(String.valueOf(name), x); - } - } - }; - } - return null; - } - - @Override - public ObjectInstance registerMBean(Object object, ObjectName name) - throws InstanceAlreadyExistsException, - MBeanRegistrationException, NotCompliantMBeanException { - return server.registerMBean(object, name); - } - - @Override - public void unregisterMBean(ObjectName name) - throws InstanceNotFoundException, - MBeanRegistrationException { - server.unregisterMBean(name); - } - - @Override - public ObjectInstance createMBean(String className, - ObjectName name, ObjectName loaderName, Object[] params, - String[] signature, boolean useCLR) - throws ReflectionException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException, - NotCompliantMBeanException, InstanceNotFoundException { - if (useCLR && loaderName == null) { - return server.createMBean(className, name, params, signature); - } - return server.createMBean(className, name, loaderName, - params, signature); - } - - - } - - private static MBeanServer newMBeanServer() { - return MBeanServerFactory.newMBeanServer(); - } - - public static interface ThingMBean {} - public static class Thing implements ThingMBean, MBeanRegistration { - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - if (name == null) return new ObjectName(":type=Thing"); - else return name; - } - public void postRegister(Boolean registrationDone) { - } - - public void preDeregister() throws Exception { - } - public void postDeregister() { - } - } - - /** - * Test that it is possible to create a dummy MBean with a null - * ObjectName - this is just a sanity check - as there are already - * other JMX tests that check that. - * - * @throws java.lang.Exception - */ - public static void testCreateWithNull() throws Exception { - final MBeanServer server = newMBeanServer(); - final ObjectInstance oi = server.registerMBean(new Thing(),null); - server.unregisterMBean(oi.getObjectName()); - System.out.println("testCreateWithNull PASSED"); - } - - public static void testRegisterSimple() throws Exception { - final ObjectName name = - JMXDomain.getDomainObjectName("gloups"); - final JMXDomain jmxDomain = new JMXDomain( - MBeanServerFactory.newMBeanServer()); - testRegister("testRegisterSimple: ",name,jmxDomain); - } - - public static void testRegisterPseudoVirtual() - throws Exception { - final ObjectName name = - JMXDomain.getDomainObjectName("gloups"); - final JMXDomain jmxDomain = new JMXDomain( - new LocalDomainRepository("gloups")); - testRegister("testRegisterPseudoVirtual: ",name,jmxDomain); - } - - public static void testRegister(final String test, - final ObjectName name, - final JMXDomain jmxDomain) throws Exception { - System.out.println(test+" START"); - MBeanServer server = newMBeanServer(); - final ObjectInstance oi = - server.registerMBean(jmxDomain,name); - System.out.println(test+"Succesfully registered namespace: "+name); - if (!server.isRegistered(name)) - fail(test+name+" is not registered!"); - if (!server.queryNames(new ObjectName(name.getDomain()+":*"), null). - contains(name)) - fail(test+name+" not in queryNames"); - - final Thing thing = new Thing(); - final ObjectName thingName = new ObjectName("gloups:type=Thing"); - server.registerMBean(thing,thingName); - if (!server.isRegistered(thingName)) - fail(test+thingName+" is not registered!"); - if (!jmxDomain.getSourceServer().isRegistered(thingName)) - fail(test+thingName+" is not registered in domain!"); - if (!server.queryNames(new ObjectName(name.getDomain()+":*"), null). - contains(thingName)) - fail(test+thingName+" not in queryNames"); - - server.unregisterMBean(name); - if (server.isRegistered(thingName)) - fail(test+thingName+" is still registered!"); - if (server.queryNames(new ObjectName(name.getDomain()+":*"), null). - contains(thingName)) - fail(test+thingName+" still in queryNames"); - - server.registerMBean(jmxDomain, name); - if (!server.isRegistered(thingName)) - fail(test+thingName+" is not registered again!"); - - System.out.println(test+" PASSED"); - } - - private static MBeanServerNotification pop( - BlockingQueue queue, - String type, - ObjectName mbean, - String test) - throws InterruptedException { - final Notification n = queue.poll(1, TimeUnit.SECONDS); - if (!(n instanceof MBeanServerNotification)) - fail(test+"expected MBeanServerNotification, got "+n); - final MBeanServerNotification msn = (MBeanServerNotification)n; - if (!type.equals(msn.getType())) - fail(test+"expected "+type+", got "+msn.getType()); - if (!mbean.apply(msn.getMBeanName())) - fail(test+"expected "+mbean+", got "+msn.getMBeanName()); - System.out.println(test+" got: "+msn); - return msn; - } - private static MBeanServerNotification popADD( - BlockingQueue queue, - ObjectName mbean, - String test) - throws InterruptedException { - return pop(queue, MBeanServerNotification.REGISTRATION_NOTIFICATION, - mbean, test); - } - - private static MBeanServerNotification popREM( - BlockingQueue queue, - ObjectName mbean, - String test) - throws InterruptedException { - return pop(queue, MBeanServerNotification.UNREGISTRATION_NOTIFICATION, - mbean, test); - } - - - public static void testRegisterNotifSimple() throws Exception { - final ObjectName name = - JMXDomain.getDomainObjectName("gloups"); - final JMXDomain jmxDomain = new JMXDomain( - MBeanServerFactory.newMBeanServer()); - testRegisterNotif("testRegisterNotifSimple: ",name,jmxDomain); - } - - public static void testRegisterNotifPseudoVirtual() - throws Exception { - final ObjectName name = - JMXDomain.getDomainObjectName("gloups"); - final JMXDomain jmxDomain = new JMXDomain( - new LocalDomainRepository("gloups")); - testRegisterNotif("testRegisterNotifPseudoVirtual: ",name,jmxDomain); - } - - public static void testRegisterNotif(final String test, - final ObjectName name, - final JMXDomain jmxDomain) throws Exception { - System.out.println(test+" START"); - MBeanServer server = newMBeanServer(); - final ObjectInstance oi = - server.registerMBean(jmxDomain,name); - System.out.println(test+"Succesfully registered namespace: "+name); - if (!server.isRegistered(name)) - fail(test+name+" is not registered!"); - - final BlockingQueue queue = - new ArrayBlockingQueue(10); - - final NotificationListener l = new NotificationListener() { - - public void handleNotification(Notification notification, - Object handback) { - try { - if (!queue.offer(notification,5,TimeUnit.SECONDS)) - throw new RuntimeException("timeout exceeded"); - } catch (Exception x) { - fail(test+"failed to handle notif", x); - } - } - }; - - server.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, l, - null, null); - - final Thing thing = new Thing(); - final ObjectName thingName = new ObjectName("gloups:type=Thing"); - - server.registerMBean(thing,thingName); - if (!jmxDomain.getSourceServer().isRegistered(thingName)) - fail(test+thingName+" is not registered in domain!"); - popADD(queue, thingName, test); - server.unregisterMBean(thingName); - if (jmxDomain.getSourceServer().isRegistered(thingName)) - fail(test+thingName+" is still registered in domain!"); - popREM(queue, thingName, test); - if (queue.size() != 0) - fail(test+queue.size()+" notifs remain in queue "+queue); - - server.unregisterMBean(name); - popREM(queue, name, test); - - jmxDomain.getSourceServer().registerMBean(thing,thingName); - if (server.isRegistered(thingName)) - fail(test+thingName+" is still registered in domain!"); - jmxDomain.getSourceServer().unregisterMBean(thingName); - if (queue.size() != 0) - fail(test+queue.size()+" notifs remain in queue "+queue); - - server.registerMBean(jmxDomain, name); - if (!server.isRegistered(name)) - fail(test+name+" is not registered again!"); - popADD(queue, name, test); - if (queue.size() != 0) - fail(test+queue.size()+" notifs remain in queue "+queue); - - server.registerMBean(thing,thingName); - if (!jmxDomain.getSourceServer().isRegistered(thingName)) - fail(test+thingName+" is not registered in domain!"); - popADD(queue, thingName, test); - server.unregisterMBean(thingName); - if (jmxDomain.getSourceServer().isRegistered(thingName)) - fail(test+thingName+" is still registered in domain!"); - popREM(queue, thingName, test); - if (queue.size() != 0) - fail(test+queue.size()+" notifs remain in queue "+queue); - - System.out.println(test+" PASSED"); - } - - - - private static void fail(String msg) { - raise(new RuntimeException(msg)); - } - - private static void fail(String msg, Throwable cause) { - raise(new RuntimeException(msg,cause)); - } - - private static void raise(RuntimeException x) { - lastException = x; - exceptionCount++; - throw x; - } - - private static volatile Exception lastException = null; - private static volatile int exceptionCount = 0; - - public static void main(String... args) throws Exception { - testCreateWithNull(); - - testRegisterSimple(); - testRegisterNotifSimple(); - - testRegisterPseudoVirtual(); - testRegisterNotifPseudoVirtual(); - - if (lastException != null) - throw lastException; - } -} diff --git a/test/javax/management/namespace/JMXNamespaceSecurityTest.java b/test/javax/management/namespace/JMXNamespaceSecurityTest.java deleted file mode 100644 index ec201dbda..000000000 --- a/test/javax/management/namespace/JMXNamespaceSecurityTest.java +++ /dev/null @@ -1,274 +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. - * - * 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. - */ - -/* - * - * @test JMXNamespaceSecurityTest.java - * @summary General JMXNamespaceSecurityTest test. - * @author Daniel Fuchs - * @bug 5072476 6299231 - * @run clean JMXNamespaceViewTest JMXNamespaceSecurityTest Wombat WombatMBean - * LazyDomainTest - * @run build JMXNamespaceSecurityTest JMXNamespaceViewTest Wombat WombatMBean - * LazyDomainTest - * @run main/othervm JMXNamespaceSecurityTest namespace.policy - */ -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; -import java.util.TreeSet; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; -import javax.management.namespace.JMXDomain; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.remote.JMXConnectorServer; -import javax.management.ClientContext; - -/** - * - * @author Sun Microsystems, Inc. - */ -public class JMXNamespaceSecurityTest extends JMXNamespaceViewTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(JMXNamespaceSecurityTest.class.getName()); - - public static class NamedMBeanServerCreator - extends JMXNamespaceViewTest.MBeanServerConfigCreator { - public MBeanServer createMBeanServerFor(NamespaceConfig config) { - return MBeanServerFactory. - createNamedMBeanServer(config.name,config.name); - } - } - /** - * Creates a config for a hierarchy of namespaces, mixing local namespaces - * and remote namespaces using the given protocol. - * @param protocol The protocol that should be used for remote namespaces. - * @return A namespace config hierarchy. - * @throws java.lang.Exception - */ - public static NamespaceConfig[] makeConfig(String protocol) - throws Exception { - final NamespaceConfig[] config = { - // Top level namespace "top1" (local) - config("top1",wombats("wchief","w1","w2","w3"), - // top1//local1 - config("local1",wombats("wchief","ww1","ww2")), - // top1//local2 - config("local2",wombats("wchief","ww4","ww5","ww6"), - // top1//local2//local3 - config("local3",wombats("wchief","www1","www2")), - // top1//local2//rmi1 - config("rmi1",url(protocol),wombats("wchief","www3","www4","www5"))), - // top1//rmi2 - config("rmi2",url(protocol),wombats("wchief","ww7","ww8","ww9"), - // top1//rmi2//local4 - config("local4",wombats("wchief","www6","www7")), - // top1//rmi2//rmi3 - config("rmi3",url(protocol),wombats("wchief","www3","www4","www5"), - // top1//rmi2//rmi3//local5 - config("local5",wombats("wchief","wwww1"))))), - // Top level namespace "top2" (local) - config("top2",wombats("wchief","w21","w22","w23"), - // top2//local21 - config("local21",wombats("wchief","ww21","ww22")), - // top2//rmi22 - config("rmi22",url(protocol),wombats("wchief","ww27","ww28","ww29"), - // top2//rmi22//local24 - config("local24",wombats("wchief","www26","www27")), - // top2//rmi22//rmi23 - config("rmi23",url(protocol),wombats("wchief","www23","www24","www25"), - // top2//rmi22//rmi23//local25 - config("local25",wombats("wchief","wwww21"))))), - // Top level namespace "top3" (remote) - config("top3",url(protocol),wombats("wchief","w31","w32","w33"), - // top3//local31 - config("local31",wombats("wchief","ww31","ww32")), - // top3//rmi32 - config("rmi32",url(protocol),wombats("wchief","ww37","ww38","ww39"), - // top3//rmi32//local34 - config("local34",wombats("wchief","www36","www37")), - // top3//rmi32//rmi33 - config("rmi33",url(protocol),wombats("wchief","www33","www34","www35"), - // top3//rmi32//local35 - config("local35",wombats("wchief","wwww31"))))), - }; - return config; - } - - public static void test(MBeanServer server, NamespaceConfig[] namespaces) - throws Exception { - System.out.println("Launching test..."); - List cslist = load(server, - new NamedMBeanServerCreator(), namespaces); - Map inputMap = - new HashMap(); - - for (NamespaceConfig cfg : namespaces) { - fillMap(inputMap,"",cfg); - } - final MBeanServer platform = ManagementFactory.getPlatformMBeanServer(); - //if (System.getProperty("jmx.wait")!=null) { - /* - // if we wanted to lazy load the platform MBeanServer: - final LazyDomainTest.MBeanServerLoader loader = - new LazyDomainTest.MBeanServerLoader() { - public MBeanServer loadMBeanServer() { - return ManagementFactory.getPlatformMBeanServer(); - } - }; - final LazyDomainTest.MBeanServerProxy proxy = - new LazyDomainTest.MBeanServerProxy(loader); - final LazyDomainTest.LazyDomain domain = - new LazyDomainTest.LazyDomain(proxy); - server.registerMBean(domain, - JMXDomain.getDomainObjectName("java.lang")); - */ - // Mount java.lang MBeans into our private server so that - // visualvm can connect. - server.registerMBean( - new JMXDomain(platform), - JMXDomain.getDomainObjectName("java.lang")); - //} - if (System.getProperty("jmx.wait")!=null) { - platform.registerMBean(new JMXNamespace(server), - JMXNamespaces.getNamespaceObjectName("test")); - } - - System.setSecurityManager(new SecurityManager()); - - // Some sanity checks... The policy file should allow access - // to java.lang MBeans. - final ObjectName platnames = new ObjectName("java.lang:*"); - for (ObjectName o : platform.queryNames(platnames,null)) { - server.getMBeanInfo(o); - } - final Set lang = - new HashSet(server.queryNames(platnames, null)); - lang.remove(JMXDomain.getDomainObjectName("java.lang")); - if (!lang.equals(platform. - queryNames(platnames, null))) - throw new Exception("Wrong list of platform names: "+lang); - System.out.println("Got all java.lang MBeans: "+lang); - - // The policy file should allow to see all namespaces. - // check this... - final List patterns = new ArrayList(); - final Set paths = new TreeSet(); - final Set uuids = new HashSet(); - patterns.add(new ObjectName("*//:*")); - while (patterns.size()>0) { - System.out.println("server.queryNames("+patterns.get(0)+",null)"); - Set names = server.queryNames(patterns.remove(0),null); - System.out.println("found: "+names); - - for (ObjectName no : names) { - final String uuid = (String) server.getAttribute(no, "UUID"); - if (uuids.contains(uuid)) { - System.out.print("namespace "+no+", uuid="+uuid+ - " already parsed. Skipping"); - continue; - } - uuids.add(uuid); - patterns.add(new ObjectName(no.getDomain()+"*//:*")); - System.out.println("added pattern: "+ - new ObjectName(no.getDomain()+"*//:*")); - if (no.getDomain().endsWith(ClientContext.NAMESPACE+ - JMXNamespaces.NAMESPACE_SEPARATOR)) continue; - paths.add(no.getDomain().substring(0, - no.getDomain().length()- - JMXNamespaces.NAMESPACE_SEPARATOR.length())); - } - } - final TreeSet expected = new TreeSet(inputMap.keySet()); - if (!expected.equals(paths)) { - throw new Exception("wrong set of namespaces, expected "+ - expected+", got "+paths); - } - - System.out.println("Got all namespaces: "+paths); - - // Check that we can see all wombats. - // - ObjectName wchief = - new ObjectName("top1//rmi2//wombat:name=wchief,type=Wombat"); - String caption = (String) server.getAttribute(wchief,"Caption"); - System.out.println("wchief says "+caption); - Object mood = server.getAttribute(wchief,"Mood"); - System.out.println("wchief's mood on a scale of 100 is "+mood); - - ObjectName wchief2 = - new ObjectName("top1//wombat:name=wchief,type=Wombat"); - String caption2 = (String) server.getAttribute(wchief2,"Caption"); - System.out.println("wchief2 says "+caption2); - try { - Object mood2 = server.getAttribute(wchief2,"Mood"); - System.out.println("wchief2's mood on a scale of 100 is "+mood2); - throw new Exception("Expected security exception for "+ - "getAttribute("+wchief2+", \"Mood\""); - } catch (SecurityException x) { - System.out.println("wchief2's mood is unavailable: "+x); - } - try { - exportAndWaitIfNeeded(server); - } finally { - closeAll(cslist); - } - - } - /** Creates a new instance of JMXNamespaceTest */ - public JMXNamespaceSecurityTest() { - } - - public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - System.out.println("os.name = " + osName); - if (!osName.equals("SunOS")) { - System.out.println("This test runs on Solaris only."); - System.out.println("Bye! Bye!"); - return; - } - final String policy = System.getProperty("test.src") + - File.separator + args[0]; - System.out.println("PolicyFile = " + policy); - System.setProperty("java.security.policy", policy); - if (!new File(System.getProperty("java.security.policy")).canRead()) - throw new IOException("no such file: "+ - System.getProperty("java.security.policy")); - test(MBeanServerFactory.createNamedMBeanServer("root","root"), - makeConfig("rmi")); - } - -} diff --git a/test/javax/management/namespace/JMXNamespaceTest.java b/test/javax/management/namespace/JMXNamespaceTest.java deleted file mode 100644 index a35377112..000000000 --- a/test/javax/management/namespace/JMXNamespaceTest.java +++ /dev/null @@ -1,511 +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. - * - * 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. - */ - -/* - * - * @test JMXNamespaceTest.java - * @summary General JMXNamespace test. - * @bug 5072476 - * @author Daniel Fuchs - * @run clean JMXNamespaceTest - * Wombat WombatMBean JMXRemoteTargetNamespace - * NamespaceController NamespaceControllerMBean - * @compile -XDignore.symbol.file=true JMXNamespaceTest.java - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java - * NamespaceController.java NamespaceControllerMBean.java - * @run main/othervm JMXNamespaceTest - */ -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryMXBean; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.logging.Logger; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.InvalidAttributeValueException; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.NotificationEmitter; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaceMBean; -import javax.management.namespace.JMXRemoteNamespaceMBean; -import javax.management.namespace.MBeanServerConnectionWrapper; -import javax.management.namespace.MBeanServerSupport; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * - * @author Sun Microsystems, Inc. - */ -public class JMXNamespaceTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(JMXNamespaceTest.class.getName()); - - /** Creates a new instance of JMXNamespaceTest */ - public JMXNamespaceTest() { - } - - public static class WombatRepository extends MBeanServerSupport { - final Wombat wombat; - final StandardMBean mbean; - final ObjectName wombatName; - - public WombatRepository(ObjectName wombatName) { - try { - wombat = new Wombat(); - mbean = wombat; - this.wombatName = wombatName; - wombat.preRegister(null,wombatName); - } catch (Exception x) { - throw new IllegalArgumentException(x); - } - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (wombatName.equals(name)) return mbean; - else throw new InstanceNotFoundException(String.valueOf(name)); - } - - @Override - protected Set getNames() { - final Set res = Collections.singleton(wombatName); - return res; - } - - @Override - public NotificationEmitter - getNotificationEmitterFor(ObjectName name) - throws InstanceNotFoundException { - final DynamicMBean mb = getDynamicMBeanFor(name); - if (mb instanceof NotificationEmitter) - return (NotificationEmitter)mb; - return null; - } - } - - public static class SimpleTest { - public final String descr; - private final Class testClass; - private final Method method; - public SimpleTest(String descr) { - this.descr = descr; - this.testClass = JMXNamespaceTest.class; - try { - method = testClass. - getDeclaredMethod(descr,SimpleTestConf.class, - Object[].class); - } catch (NoSuchMethodException x) { - throw new IllegalArgumentException(descr+": test not found", - x); - } - } - - public void run(SimpleTestConf conf, Object... args) - throws Exception { - try { - method.invoke(null,conf,args); - } catch (InvocationTargetException x) { - final Throwable cause = x.getCause(); - if (cause instanceof Exception) throw (Exception)cause; - if (cause instanceof Error) throw (Error)cause; - throw x; - } - } - } - - public static class SimpleTestConf { - public final Wombat wombat; - public final StandardMBean mbean; - public final String dirname; - public final ObjectName handlerName; - public final ObjectName wombatNickName; - public final ObjectName wombatName; - public final JMXNamespace wombatNamespace; - public final MBeanServer server; - public final WombatMBean proxy; - public SimpleTestConf(String[] args) throws Exception { - wombat = new Wombat(); - mbean = wombat; - dirname = "wombat"; - handlerName = - new ObjectName(dirname+"//:type=JMXNamespace"); - - wombatNickName = - new ObjectName("burrow:type=Wombat"); - - wombatName = - new ObjectName(dirname+"//"+wombatNickName); - - wombatNamespace = - new JMXNamespace( - new WombatRepository(wombatNickName)); - - server = ManagementFactory.getPlatformMBeanServer(); - System.out.println(handlerName+" registered="+ - server.isRegistered(handlerName)); - server.registerMBean(wombatNamespace,handlerName); - - try { - proxy = JMX.newMBeanProxy(server,wombatName, - WombatMBean.class); - } catch (Exception x) { - server.unregisterMBean(handlerName); - throw x; - } - } - - public void close() { - try { - server.unregisterMBean(handlerName); - } catch (Exception x) { - System.out.println("Failed to close: " + x); - x.printStackTrace(); - } - } - - public void test(SimpleTest test,Object... args) - throws Exception { - try { - test.run(this,args); - passed++; - } catch (Exception x) { - failed++; - System.err.println(test.descr+" failed: " + x); - x.printStackTrace(); - } - } - - public volatile int failed = 0; - public volatile int passed = 0; - } - - static void checkValue(String name,Object expected, Object returned) - throws InvalidAttributeValueException { - if (Collections.singletonList(expected). - equals(Collections.singletonList(returned))) return; - - throw new InvalidAttributeValueException("Bad value for "+ - name+": ["+returned+"] - was expecting ["+expected+"]"); - } - - // --------------------------------------------------------------- - // SIMPLE TESTS BEGIN HERE - // --------------------------------------------------------------- - - static void getCaptionTest(SimpleTestConf env, Object... args) - throws Exception { - System.out.println(env.proxy.getCaption()); - } - - static void setCaptionTest(SimpleTestConf env, Object... args) - throws Exception { - env.proxy.setCaption((String)args[0]); - final String result = env.proxy.getCaption(); - System.out.println(result); - checkValue("Caption",args[0],result); - } - - static void queryNamesTest1(SimpleTestConf env, Object... args) - throws Exception { - final ObjectName pat = - new ObjectName(env.handlerName.getDomain()+"*:*"); - final Set res = - env.server.queryNames(pat,null); - System.out.println("queryNamesTest1: "+res); - checkValue("names",Collections.singleton(env.wombatName),res); - } - - static void queryNamesTest2(SimpleTestConf env, Object... args) - throws Exception { - final ObjectName pat = - new ObjectName("*:"+ - env.wombatName.getKeyPropertyListString()); - final Set res = - env.server.queryNames(pat,null); - System.out.println("queryNamesTest2: "+res); - checkValue("names",Collections.emptySet(),res); - } - - static void getDomainsTest(SimpleTestConf env, Object... args) - throws Exception { - final List domains = - Arrays.asList(env.server.getDomains()); - System.out.println("getDomainsTest: "+domains); - if (domains.contains(env.wombatName.getDomain())) - throw new InvalidAttributeValueException("domain: "+ - env.wombatName.getDomain()); - if (!domains.contains(env.handlerName.getDomain())) - throw new InvalidAttributeValueException("domain not found: "+ - env.handlerName.getDomain()); - } - - // --------------------------------------------------------------- - // SIMPLE TESTS END HERE - // --------------------------------------------------------------- - - private static void simpleTest(String[] args) { - final SimpleTestConf conf; - try { - conf = new SimpleTestConf(args); - try { - conf.test(new SimpleTest("getCaptionTest")); - conf.test(new SimpleTest("setCaptionTest"), - "I am a new Wombat!"); - conf.test(new SimpleTest("queryNamesTest1")); - conf.test(new SimpleTest("queryNamesTest2")); - conf.test(new SimpleTest("getDomainsTest")); - } finally { - conf.close(); - } - } catch (Exception x) { - System.err.println("simpleTest FAILED: " +x); - x.printStackTrace(); - throw new RuntimeException(x); - } - System.out.println("simpleTest: "+conf.passed+ - " PASSED, " + conf.failed + " FAILED."); - if (conf.failed>0) { - System.err.println("simpleTest FAILED ["+conf.failed+"]"); - throw new RuntimeException("simpleTest FAILED ["+conf.failed+"]"); - } else { - System.err.println("simpleTest PASSED ["+conf.passed+"]"); - } - } - - public static void recursiveTest(String[] args) { - final SimpleTestConf conf; - try { - conf = new SimpleTestConf(args); - try { - final JMXServiceURL url = - new JMXServiceURL("rmi","localHost",0); - final Map empty = Collections.emptyMap(); - final JMXConnectorServer server = - JMXConnectorServerFactory.newJMXConnectorServer(url, - empty,conf.server); - server.start(); - final JMXServiceURL address = server.getAddress(); - final JMXConnector client = - JMXConnectorFactory.connect(address, - empty); - final String[] signature = { - JMXServiceURL.class.getName(), - Map.class.getName(), - }; - final String[] signature2 = { - JMXServiceURL.class.getName(), - Map.class.getName(), - String.class.getName(), - }; - final Object[] params = { - address, - null, - }; - final MBeanServerConnection c = - client.getMBeanServerConnection(); - final ObjectName dirName1 = - new ObjectName("kanga//:type=JMXNamespace"); - c.createMBean(JMXRemoteTargetNamespace.class.getName(), - dirName1, params,signature); - c.invoke(dirName1, "connect", null, null); - try { - final MemoryMXBean memory = - JMX.newMXBeanProxy(c, - new ObjectName("kanga//"+ - ManagementFactory.MEMORY_MXBEAN_NAME), - MemoryMXBean.class); - System.out.println("HeapMemory #1: "+ - memory.getHeapMemoryUsage().toString()); - final MemoryMXBean memory2 = - JMX.newMXBeanProxy(c, - new ObjectName("kanga//kanga//"+ - ManagementFactory.MEMORY_MXBEAN_NAME), - MemoryMXBean.class); - System.out.println("HeapMemory #2: "+ - memory2.getHeapMemoryUsage().toString()); - final Object[] params2 = { - address, - null, - "kanga//kanga" - // "kanga//kanga//roo//kanga", <= cycle - }; - final ObjectName dirName2 = - new ObjectName("kanga//roo//:type=JMXNamespace"); - c.createMBean(JMXRemoteTargetNamespace.class.getName(), - dirName2, params2, signature2); - System.out.println(dirName2 + " created!"); - JMX.newMBeanProxy(c,dirName2, - JMXRemoteNamespaceMBean.class).connect(); - try { - final ObjectName wombatName1 = - new ObjectName("kanga//roo//"+conf.wombatName); - final ObjectName wombatName2 = - new ObjectName("kanga//roo//"+wombatName1); - final WombatMBean wombat1 = - JMX.newMBeanProxy(c,wombatName1,WombatMBean.class); - final WombatMBean wombat2 = - JMX.newMBeanProxy(c,wombatName2,WombatMBean.class); - final String newCaption="I am still the same old wombat"; - wombat1.setCaption(newCaption); - final String caps = conf.proxy.getCaption(); - System.out.println("Caption: "+caps); - checkValue("Caption",newCaption,caps); - final String caps1 = wombat1.getCaption(); - System.out.println("Caption #1: "+caps1); - checkValue("Caption #1",newCaption,caps1); - final String caps2 = wombat2.getCaption(); - System.out.println("Caption #2: "+caps2); - checkValue("Caption #2",newCaption,caps2); - final ObjectInstance instance = - NamespaceController.createInstance(conf.server); - final NamespaceControllerMBean controller = - JMX.newMBeanProxy(conf.server,instance.getObjectName(), - NamespaceControllerMBean.class); - final String[] dirs = controller.findNamespaces(); - System.out.println("directories: " + - Arrays.asList(dirs)); - final int depth = 4; - final String[] dirs2 = controller.findNamespaces(null,null,depth); - System.out.println("directories[depth="+depth+"]: " + - Arrays.asList(dirs2)); - for (String dir : dirs2) { - if (dir.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) - dir = dir.substring(0,dir.length()- - JMXNamespaces.NAMESPACE_SEPARATOR.length()); - if (dir.split(JMXNamespaces.NAMESPACE_SEPARATOR).length - > (depth+1)) { - throw new RuntimeException(dir+": depth exceeds "+depth); - } - final ObjectName handlerName = - JMXNamespaces.getNamespaceObjectName(dir); - final JMXNamespaceMBean handler = - JMX.newMBeanProxy(conf.server,handlerName, - JMXNamespaceMBean.class); - try { - System.err.println("Directory "+dir+" domains: "+ - Arrays.asList(handler.getDomains())); - System.err.println("Directory "+dir+" default domain: "+ - handler.getDefaultDomain()); - System.err.println("Directory "+dir+" MBean count: "+ - handler.getMBeanCount()); - } catch(Exception x) { - System.err.println("get info failed for " + - dir +", "+handlerName+": "+x); - x.getCause().printStackTrace(); - throw x; - } - } - - } finally { - c.unregisterMBean(dirName2); - } - } finally { - c.unregisterMBean(dirName1); - client.close(); - server.stop(); - } - } finally { - conf.close(); - } - System.err.println("recursiveTest PASSED"); - } catch (Exception x) { - System.err.println("recursiveTest FAILED: " +x); - x.printStackTrace(); - throw new RuntimeException(x); - } - } - - public static void verySimpleTest(String[] args) { - System.err.println("verySimpleTest: starting"); - try { - final MBeanServer srv = MBeanServerFactory.createMBeanServer(); - srv.registerMBean(new JMXNamespace( - JMXNamespaces.narrowToNamespace(srv, "foo")), - JMXNamespaces.getNamespaceObjectName("foo")); - throw new Exception("Excpected IllegalArgumentException not raised."); - } catch (IllegalArgumentException x) { - System.err.println("verySimpleTest: got expected exception: "+x); - } catch (Exception x) { - System.err.println("verySimpleTest FAILED: " +x); - x.printStackTrace(); - throw new RuntimeException(x); - } - System.err.println("verySimpleTest: PASSED"); - } - - public static void verySimpleTest2(String[] args) { - System.err.println("verySimpleTest2: starting"); - try { - final MBeanServer srv = MBeanServerFactory.createMBeanServer(); - final JMXConnectorServer cs = JMXConnectorServerFactory. - newJMXConnectorServer(new JMXServiceURL("rmi",null,0), - null, srv); - cs.start(); - final JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress()); - - srv.registerMBean(new JMXNamespace( - new MBeanServerConnectionWrapper( - JMXNamespaces.narrowToNamespace( - cc.getMBeanServerConnection(), - "foo"))), - JMXNamespaces.getNamespaceObjectName("foo")); - throw new Exception("Excpected IllegalArgumentException not raised."); - } catch (IllegalArgumentException x) { - System.err.println("verySimpleTest2: got expected exception: "+x); - } catch (Exception x) { - System.err.println("verySimpleTest2 FAILED: " +x); - x.printStackTrace(); - throw new RuntimeException(x); - } - System.err.println("verySimpleTest2: PASSED"); - } - - public static void main(String[] args) { - simpleTest(args); - recursiveTest(args); - verySimpleTest(args); - verySimpleTest2(args); - } - -} diff --git a/test/javax/management/namespace/JMXNamespaceViewTest.java b/test/javax/management/namespace/JMXNamespaceViewTest.java deleted file mode 100644 index 4764f531f..000000000 --- a/test/javax/management/namespace/JMXNamespaceViewTest.java +++ /dev/null @@ -1,546 +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. - * - * 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. - */ -/* - * - * @test JMXNamespaceViewTest.java - * @summary Test the JMXNamespaceView class. - * @bug 5072476 - * @author Daniel Fuchs - * @run clean JMXNamespaceViewTest Wombat WombatMBean - * @run build JMXNamespaceViewTest Wombat WombatMBean - * @run main JMXNamespaceViewTest - */ - - -import java.lang.management.ManagementFactory; -import java.net.ServerSocket; -import java.rmi.registry.LocateRegistry; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.management.ClientContext; -import javax.management.JMException; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaceView; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * A simple test to test the JMXNamespaceViewTest... - * @author dfuchs - */ -public class JMXNamespaceViewTest { - - /** - * Describe the configuration of a namespace - */ - public static class NamespaceConfig { - /** name of the namespace - no // allowed **/ - public String name; - /** - * JMXServiceURL through which the namespace is exported, if it - * is a remote namespace. {@code null} if the namespace is local. - * This is an inpur URL - eg: new JMXServiceURL("rmi",null,0).toString() - * is acceptable here. - */ - public String jmxurl; - /** - * Values of the name= key for each WombatMBean contained in the - * namespace. - */ - public String[] wombats; - /** list of child namespace **/ - public NamespaceConfig[] children; - } - - /** - * Creates a NamespaceConfig record for a local namespace. - * @param name name of the namespace - * @param wombats names of WombatMBean it should contain. - * @return a NamespaceConfig. - */ - public static NamespaceConfig config(String name, String[] wombats) { - return config(name,null,wombats); - } - - /** - * Creates a NamespaceConfig record for a remote namespace. - * @param name name of the namespace - * @param jmxurl input JMXServiceURL for creating the JMXConnectorServer - * @param wombats names of WombatMBean it should contain. - * @return a NamespaceConfig. - */ - public static NamespaceConfig config(String name, String jmxurl, - String[] wombats) { - return config(name,jmxurl,wombats,(NamespaceConfig[])null); - } - - /** - * Creates a NamespaceConfig record for a local namespace. - * @param name name of the namespace - * @param wombats names of WombatMBean it should contain. - * @param children list of sub namespaces. - * @return a NamespaceConfig. - */ - public static NamespaceConfig config(String name, String[] wombats, - NamespaceConfig... children) { - return config(name,null,wombats,children); - } - - /** - * Creates a NamespaceConfig record for a remote namespace. - * @param name name of the namespace - * @param jmxurl input JMXServiceURL for creating the JMXConnectorServer - * @param wombats names of WombatMBean it should contain. - * @param children list of sub namespaces. - * @return a NamespaceConfig. - */ - static NamespaceConfig config(String name, String jmxurl, String[] wombats, - NamespaceConfig... children) { - final NamespaceConfig cfg = new NamespaceConfig(); - cfg.name=name; cfg.jmxurl=jmxurl; cfg.wombats=wombats; - cfg.children=children; - return cfg; - } - - /** - * Returns the given names. This is a utility method to ease code - * reading. - * @param names names of Wombat MBeans. - * @return the given names. - */ - static String[] wombats(String... names) { - return names; - } - - /** - * Creates a JMXServiceURL string for the given protocol. - * This is also a utility method to ease code reading. - * @param protocol The protocol name (e.g. "rmi") - * @return A JMXServiceURL string. - * @throws Exception if creation of the JMXServiceURL fails. - */ - static String url(String protocol) throws Exception { - return new JMXServiceURL(protocol,null,0).toString(); - } - - /** - * Creates a config for a hierarchy of namespaces, mixing local namespaces - * and remote namespaces using the given protocol. - * @param protocol The protocol that should be used for remote namespaces. - * @return A namespace config hierarchy. - * @throws java.lang.Exception - */ - public static NamespaceConfig[] makeConfig(String protocol) - throws Exception { - final NamespaceConfig[] config = { - // Top level namespace "top1" (local) - config("top1",wombats("wchief","w1","w2","w3"), - // top1//local1 - config("local1",wombats("wchief","ww1","ww2")), - // top1//local2 - config("local2",wombats("wchief","ww4","ww5","ww6"), - // top1//local2//local3 - config("local3",wombats("wchief","www1","www2")), - // top1//local2//rmi1 - config("rmi1",url(protocol),wombats("wchief","www3","www4","www5"))), - // top1//rmi2 - config("rmi2",url(protocol),wombats("wchief","ww7","ww8","ww9"), - // top1//rmi2//local4 - config("local4",wombats("wchief","www6","www7")), - // top1//rmi2//rmi3 - config("rmi3",url(protocol),wombats("wchief","www3","www4","www5"), - // top1//rmi2//rmi3//local5 - config("local5",wombats("wchief","wwww1"))))), - // Top level namespace "top2" (local) - config("top2",wombats("wchief","w21","w22","w23"), - // top2//local21 - config("local21",wombats("wchief","ww21","ww22")), - // top2//rmi22 - config("rmi22",url(protocol),wombats("wchief","ww27","ww28","ww29"), - // top2//rmi22//local24 - config("local24",wombats("wchief","www26","www27")), - // top2//rmi22//rmi23 - config("rmi23",url(protocol),wombats("wchief","www23","www24","www25"), - // top2//rmi22//rmi23//local25 - config("local25",wombats("wchief","wwww21"))))), - // Top level namespace "top3" (remote) - config("top3",url(protocol),wombats("wchief","w31","w32","w33"), - // top3//local31 - config("local31",wombats("wchief","ww31","ww32")), - // top3//rmi32 - config("rmi32",url(protocol),wombats("wchief","ww37","ww38","ww39"), - // top3//rmi32//local34 - config("local34",wombats("wchief","www36","www37")), - // top3//rmi32//rmi33 - config("rmi33",url(protocol),wombats("wchief","www33","www34","www35"), - // top3//rmi32//local35 - config("local35",wombats("wchief","wwww31"))))), - }; - return config; - } - - /** - * Close all connector servers in the list. - * @param cslist List of connector servers to close. - */ - public static void closeAll(List cslist) { - for (JMXConnectorServer cs : cslist) { - try { - cs.stop(); - } catch (Exception xx) { - System.err.println("Failed to stop connector: " + xx); - } - } - } - - public static class MBeanServerConfigCreator { - public MBeanServer createMBeanServerFor(NamespaceConfig config) { - return MBeanServerFactory.newMBeanServer(); - } - } - - /** - * Load the given namespace configuration inside the given MBeanServer. - * Return a list of connector servers created in the process. - * @param server The MBeanServer in which the namespaces must - * be created. - * @param namespaces The list of namespaces to create. - * @return a list of started connector servers. - * @throws java.lang.Exception failed to create the specified namespaces. - */ - public static List load(MBeanServer server, - MBeanServerConfigCreator factory, - NamespaceConfig... namespaces) throws Exception { - final List cslist = - new ArrayList(); - try { - final ObjectName creator = - new ObjectName("jmx.creator:type=JMXNamespaceCreator"); - if (System.getProperty("jmx.wait")!=null - && !server.isRegistered(creator)) { - server.registerMBean(new JMXNamespaceCreator(),creator); - } - for (NamespaceConfig cfg : namespaces) { - final MBeanServer srv = factory.createMBeanServerFor(cfg); - if (System.getProperty("jmx.wait")!=null - && !srv.isRegistered(creator)) { - srv.registerMBean(new JMXNamespaceCreator(),creator); - } - if (cfg.wombats != null) { - for (String w : cfg.wombats) { - final ObjectName n = - new ObjectName("wombat:type=Wombat,name=" + w); - final WombatMBean ww = new Wombat(); - srv.registerMBean(ww, n); - } - } - if (cfg.children != null) { - cslist.addAll(load(srv, factory, cfg.children)); - } - JMXNamespace nm; - if (cfg.jmxurl == null) { - nm = new JMXNamespace(srv); - } else { - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(new JMXServiceURL(cfg.jmxurl), - null, srv); - srv.registerMBean(cs, - new ObjectName("jmx.remote:type=JMXConnectorServer")); - cs.start(); - cslist.add(cs); - nm = JMXRemoteNamespace. - newJMXRemoteNamespace(cs.getAddress(), - null); - } - server.registerMBean(nm, - JMXNamespaces.getNamespaceObjectName(cfg.name)); - if (nm instanceof JMXRemoteNamespace) { - server.invoke( - JMXNamespaces.getNamespaceObjectName(cfg.name), - "connect", null, null); - } - } - } catch (Exception x) { - closeAll(cslist); - throw x; - } - return cslist; - } - - /** - * Add an entry {@code } in the map for the given - * namespace and its subnamespaces. - * @param map A {@code Map}. - * @param parent The path of the parent workspace. - * @param cfg The NamespaceConfig hierarchy to index in the map. - */ - public static void fillMap(Map map, String parent, - NamespaceConfig cfg) { - - final String where; - if (parent == null || parent.equals("")) - where=cfg.name; - else - where=parent+JMXNamespaces.NAMESPACE_SEPARATOR+cfg.name; - map.put(where,cfg); - if (cfg.children==null) return; - for(NamespaceConfig child:cfg.children) { - fillMap(map,where,child); - } - } - - /** - * Compare a list of namespace names obtained from JMXNamespaceView.list() - * with the expected clildren list of the corresponding NamespaceConfig. - * @param list A list of namespace names - * @param children A list of NamespaceConfig correspondng to expected - * namespace. - * @param fail If true and the comparison yields false, throws an - * exception instead of simply returning false. - * @return true if OK, false if NOK. - */ - private static boolean compare(String[] list, NamespaceConfig[] children, - boolean fail) { - final List found = new ArrayList(Arrays.asList(list)); - if (found.contains(ClientContext.NAMESPACE)) - found.remove(ClientContext.NAMESPACE); - - if (children == null && found.size()==0) return true; - if (children == null && fail == false) return false; - if (children == null) throw new RuntimeException( - "No child expected. Found "+Arrays.toString(list)); - final Set names = new HashSet(); - for (NamespaceConfig cfg : children) { - names.add(cfg.name); - if (found.contains(cfg.name)) continue; - if (!fail) return false; - throw new RuntimeException(cfg.name+" not found in "+ - found); - } - found.removeAll(names); - if (found.size()==0) return true; - if (fail==false) return false; - throw new RuntimeException("found additional namespaces: "+ - found); - } - - /** - * Compares the result of queryNames(null,null) with a set of expected - * wombats. - * @param where The path of the namespace that was queried. - * @param list The set of ObjectNames found. - * @param wombats The expected list of wombats. - * @param fail If true and the comparison yields false, throws an - * exception instead of simply returning false. - * @return true if OK, false if NOK. - * @throws java.lang.Exception something went wrong. - */ - private static boolean compare(String where, - Setlist, String[] wombats, - boolean fail) throws Exception { - final Set found = new HashSet(); - final Set expected = new HashSet(); - for (ObjectName n : list) { - if ("Wombat".equals(n.getKeyProperty("type"))) - found.add(n); - } - for(String w : wombats) { - final ObjectName n = - new ObjectName("wombat:type=Wombat,name=" + w); - expected.add(n); - if (found.contains(n)) continue; - if (fail == false) return false; - throw new RuntimeException(where+ - ": Wombat "+w+" not found in "+found); - } - found.removeAll(expected); - if (found.size()==0) { - System.out.println(where+": found all expected: "+expected); - return true; - } - if (fail==false) return false; - throw new RuntimeException(where+": found additional MBeans: "+ - found); - } - - /** - * A generic test to test JMXNamespaceView over a namespace configuration. - * @param server The MBeanServer in which to load the namespace - * config. - * @param namespaces The namespace config to run the test over... - * @throws java.lang.Exception - */ - public static void doTest(MBeanServer server, NamespaceConfig... namespaces) - throws Exception { - List cslist = load(server, - new MBeanServerConfigCreator(), namespaces); - Map inputMap = - new HashMap(); - - for (NamespaceConfig cfg : namespaces) { - fillMap(inputMap,"",cfg); - } - try { - final JMXNamespaceView root = new JMXNamespaceView(server); - List vlist = new ArrayList(); - vlist.add(root); - - while (!vlist.isEmpty()) { - JMXNamespaceView v = vlist.remove(0); - final String where = v.isRoot()?"root":v.where(); - System.out.println(where+": "+ - v.getMBeanServerConnection().queryNames(null,null)); - for (String ns : v.list()) { - final JMXNamespaceView down = v.down(ns); - vlist.add(down); - if (!down.where().equals(v.isRoot()?ns:where+ - JMXNamespaces.NAMESPACE_SEPARATOR+ns)) { - throw new RuntimeException("path of "+down.where()+ - " should be "+(v.isRoot()?ns:where+ - JMXNamespaces.NAMESPACE_SEPARATOR+ns)); - } - if (down.up().equals(v)) continue; - throw new RuntimeException("parent of "+down.where()+ - " should be "+where); - } - final NamespaceConfig[] children; - final NamespaceConfig cfg; - if (v.isRoot()) { - children=namespaces; - cfg = null; - } else { - cfg = inputMap.get(where); - children = cfg==null?null:cfg.children; - } - compare(v.list(),children,true); - if (!v.isRoot()) { - if (where.endsWith(ClientContext.NAMESPACE)) { - System.out.println(where+": skipping queryNames analysis"); - continue; - } - //System.out.println(where+": cfg is: "+cfg); - compare(where,v.getMBeanServerConnection(). - queryNames(null, null),cfg.wombats,true); - } - } - - exportAndWaitIfNeeded(server); - } finally { - closeAll(cslist); - } - } - - public static interface JMXNamespaceCreatorMBean { - public ObjectInstance createLocalNamespace(String namespace) - throws JMException ; - public void removeLocalNamespace(String namespace) - throws JMException; - } - - public static class JMXNamespaceCreator - implements MBeanRegistration, - JMXNamespaceCreatorMBean { - - private volatile MBeanServer mbeanServer; - - public ObjectInstance createLocalNamespace(String namespace) - throws JMException { - return mbeanServer.registerMBean( - new JMXNamespace(MBeanServerFactory.newMBeanServer()), - JMXNamespaces.getNamespaceObjectName(namespace)); - } - - public void removeLocalNamespace(String namespace) - throws JMException { - mbeanServer.unregisterMBean( - JMXNamespaces.getNamespaceObjectName(namespace)); - } - - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - mbeanServer = server; - return name; - } - - public void postRegister(Boolean registrationDone) { - } - - public void preDeregister() throws Exception { - } - - public void postDeregister() { - } - - } - - public static void exportAndWaitIfNeeded(MBeanServer server) - throws Exception { - if (System.getProperty("jmx.wait")!=null) { - final int port = getPortFor("rmi"); - LocateRegistry.createRegistry(port); - final JMXServiceURL url = - new JMXServiceURL("rmi",null,port, - "/jndi/rmi://localhost:"+port+"/jmxrmi"); - final JMXConnectorServer cs = - JMXConnectorServerFactory. - newJMXConnectorServer(url, null, server); - cs.start(); - try { - System.out.println("RMI Server waiting at: "+cs.getAddress()); - System.in.read(); - } finally { - cs.stop(); - } - } - } - - public static int getPortFor(String protocol) throws Exception { - final int aport = - Integer.valueOf(System.getProperty("jmx."+protocol+".port","0")); - if (aport > 0) return aport; - final ServerSocket s = new ServerSocket(0); - try { - final int port = s.getLocalPort(); - return port; - } finally { - s.close(); - } - } - - public static void main(String[] args) throws Exception { - doTest(ManagementFactory.getPlatformMBeanServer(),makeConfig("rmi")); - } - -} diff --git a/test/javax/management/namespace/JMXNamespacesTest.java b/test/javax/management/namespace/JMXNamespacesTest.java deleted file mode 100644 index 4dc7c518a..000000000 --- a/test/javax/management/namespace/JMXNamespacesTest.java +++ /dev/null @@ -1,648 +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. - * - * 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. - */ -/* - * @test JMXNamespacesTest.java - * @summary Test the static method that rewrite ObjectNames in JMXNamespacesTest - * @author Daniel Fuchs - * @bug 5072476 - * @run clean JMXNamespacesTest - * @compile -XDignore.symbol.file=true JMXNamespacesTest.java - * @run main JMXNamespacesTest - */ - -import com.sun.jmx.namespace.ObjectNameRouter; -import java.io.Serializable; -import java.util.Arrays; -import java.util.logging.Logger; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; - -/** - * Class JMXNamespacesTest - * @author Sun Microsystems, 2005 - All rights reserved. - */ -public class JMXNamespacesTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(JMXNamespacesTest.class.getName()); - - /** Creates a new instance of JMXNamespacesTest */ - public JMXNamespacesTest() { - } - - public static class CustomObject implements Serializable { - ObjectName toto; - String titi; - CustomObject(String toto, String titi) { - try { - this.toto = new ObjectName(toto); - } catch (MalformedObjectNameException m) { - throw new IllegalArgumentException(m); - } - this.titi = titi; - } - private Object[] data() { - return new Object[] {toto, titi}; - } - @Override - public boolean equals(Object other) { - if (! (other instanceof CustomObject)) return false; - return Arrays.deepEquals(data(),((CustomObject)other).data()); - } - @Override - public int hashCode() { - return Arrays.deepHashCode(data()); - } - } - - public static CustomObject obj(String toto, String titi) { - return new CustomObject(toto,titi); - } - - private static String failure; - - public static void testDeepRewrite() throws Exception { - failure = null; - String s1 = "x//y//d:k=v"; - String s2 = "v//w//x//y//d:k=v"; - String p1 = "v//w"; - String p3 = "a//b"; - - System.out.println("inserting "+p1); - final CustomObject foo1 = - JMXNamespaces.deepReplaceHeadNamespace(obj(s1,s1),"",p1); - assertEquals(foo1.toto.toString(),p1+"//"+s1); - assertEquals(foo1.titi,s1); - - System.out.println("removing "+p1); - final CustomObject foo2 = - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),p1,""); - assertEquals(foo2.toto.toString(),s1); - assertEquals(foo2.titi,s2); - - System.out.println("removing "+p1); - final CustomObject foo3 = - JMXNamespaces.deepReplaceHeadNamespace(obj(p1+"//"+s2,s2),p1,""); - assertEquals(foo3.toto.toString(),s2); - assertEquals(foo3.titi,s2); - - System.out.println("replacing "+p1+" with "+p3); - final CustomObject foo4 = - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),p1,p3); - assertEquals(foo4.toto.toString(),p3+"//"+s1); - assertEquals(foo4.titi,s2); - - System.out.println("replacing "+p1+" with "+p1); - final CustomObject foo5 = - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),p1,p1); - assertEquals(foo5.toto.toString(),s2); - assertEquals(foo5.titi,s2); - - System.out.println("removing x//y in "+s2); - try { - final CustomObject foo7 = - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),"x//y",""); - failed("Remove x//y in "+s2+" should have failed!"); - } catch (IllegalArgumentException x) { - System.out.println("Received expected exception: "+x); - } - - System.out.println("replacing x//y with "+p3+" in "+s2); - try { - final CustomObject foo7 = - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),"x//y",p3); - failed("Replace x//y in "+s2+" should have failed!"); - } catch (IllegalArgumentException x) { - System.out.println("Received expected exception: "+x); - } - - if (failure != null) throw new Exception(failure); - } - - private static String[][] wildcards = { - { "", "*:*" }, - { "//", "//*:*" }, - { "foo", "foo//*:*" }, - { "//foo", "//foo//*:*" }, - { "////foo", "//foo//*:*" }, - { "foo//", "foo//*:*" }, - { "foo////", "foo//*:*" }, - { "//foo//", "//foo//*:*" }, - { "////foo//", "//foo//*:*" }, - { "////foo////", "//foo//*:*" }, - { "foo//bar", "foo//bar//*:*" }, - { "//foo//bar", "//foo//bar//*:*" }, - { "////foo//bar", "//foo//bar//*:*" }, - { "foo//bar//", "foo//bar//*:*" }, - { "foo//bar////", "foo//bar//*:*" }, - { "//foo//bar//", "//foo//bar//*:*" }, - { "////foo//bar//", "//foo//bar//*:*" }, - { "////foo//bar////", "//foo//bar//*:*" }, - { "foo////bar", "foo//bar//*:*" }, - { "//foo////bar", "//foo//bar//*:*" }, - { "////foo////bar", "//foo//bar//*:*" }, - { "foo////bar//", "foo//bar//*:*" }, - { "foo////bar////", "foo//bar//*:*" }, - { "//foo////bar//", "//foo//bar//*:*" }, - { "////foo////bar//", "//foo//bar//*:*" }, - { "////foo////bar////", "//foo//bar//*:*" }, - { "fo/o", "fo/o//*:*" }, - { "//f/oo", "//f/oo//*:*" }, - { "////f/o/o", "//f/o/o//*:*" }, - { "fo/o//", "fo/o//*:*" }, - { "f/oo////", "f/oo//*:*" }, - { "//fo/o//", "//fo/o//*:*" }, - { "////f/oo//", "//f/oo//*:*" }, - { "////f/o/o////", "//f/o/o//*:*" }, - { "foo//b/a/r", "foo//b/a/r//*:*" }, - { "//fo/o//bar", "//fo/o//bar//*:*" }, - { "////foo//b/ar", "//foo//b/ar//*:*" }, - { "foo//ba/r//", "foo//ba/r//*:*" }, - { "f/oo//bar////", "f/oo//bar//*:*" }, - { "//f/o/o//bar//", "//f/o/o//bar//*:*" }, - { "////foo//b/a/r//", "//foo//b/a/r//*:*" }, - { "////f/o/o//b/a/r////", "//f/o/o//b/a/r//*:*" }, - { "foo////ba/r", "foo//ba/r//*:*" }, - { "//foo////b/ar", "//foo//b/ar//*:*" }, - { "////f/oo////bar", "//f/oo//bar//*:*" }, - { "fo/o////bar//", "fo/o//bar//*:*" }, - { "foo////ba/r////", "foo//ba/r//*:*" }, - { "//fo/o////ba/r//", "//fo/o//ba/r//*:*" }, - { "////f/oo////b/ar//", "//f/oo//b/ar//*:*" }, - { "////f/o/o////b/a/r////", "//f/o/o//b/a/r//*:*" }, - }; - private final static String[] badguys = { - null, - "/", "/*:*", - "///", "///*:*" , - "/foo", "/foo//*:*", - "//foo/", "//foo///*:*" , - "/////foo", "///foo//*:*", - "/foo//", "/foo//*:*", - "foo/////", "foo///*:*", - "///foo//", "///foo//*:*", - "////foo///", "//foo///*:*" , - "/////foo/////", "///foo///*:*", - "/foo//bar", "/foo//bar//*:*", - "//foo///bar", "//foo///bar//*:*", - "/////foo////bar/", "///foo//bar///*:*", - "foo///bar//", "foo//bar///*:*", - "foo//bar/////", "foo///bar//*:*", - "///foo//bar//", "//foo///bar//*:*" , - }; - public static void testWildcard() throws Exception { - int i = 0; - for (String[] pair : wildcards) { - i++; - final String msg = "testWildcard[good,"+i+"] "+Arrays.asList(pair)+": "; - assertEquals(msg, new ObjectName(pair[1]), - JMXNamespaces.getWildcardFor(pair[0])); - } - i=0; - for (String bad : badguys) { - i++; - try { - JMXNamespaces.getWildcardFor(bad); - failed("testWildcard[bad,"+i+"] "+bad+" incorrectly accepted. " + - "IllegalArgumentException was expected"); - } catch (IllegalArgumentException x) { - // OK - } - } - if (failure != null) throw new Exception(failure); - } - - private static String[][] goodinsert = { - {"","d:k=v","d:k=v"}, - {"","//d:k=v","//d:k=v"}, - {"//","d:k=v","//d:k=v"}, - {"//","//d:k=v","//d:k=v"}, - {"//","a//d:k=v","//a//d:k=v"}, - {"//","//a//d:k=v","//a//d:k=v"}, - {"//","////a////d:k=v","//a//d:k=v"}, - {"//b","////a////d:k=v","//b//a//d:k=v"}, - {"b","////a////d:k=v","b//a//d:k=v"}, - {"b","d:k=v","b//d:k=v"}, - {"b//","d:k=v","b//d:k=v"}, - {"//b//","d:k=v","//b//d:k=v"}, - {"//b","////a////d:k=v","//b//a//d:k=v"}, - {"b//c","////a////d:k=v","b//c//a//d:k=v"}, - {"b//c","d:k=v","b//c//d:k=v"}, - {"b//c//","d:k=v","b//c//d:k=v"}, - {"//b//c//","d:k=v","//b//c//d:k=v"}, - {"","/d:k=v","/d:k=v"}, - {"","///d:k=v","///d:k=v"}, - {"//","/d:k=v","///d:k=v"}, - {"//","///d:k=v","///d:k=v"}, - {"//","a///d:k=v","//a///d:k=v"}, - {"//","//a///d:k=v","//a///d:k=v"}, - {"//","////a////d/:k=v","//a//d/:k=v"}, - {"//b","////a/////d:k=v","//b//a///d:k=v"}, - {"b","////a////d/:k=v","b//a//d/:k=v"}, - {"b","/d:k=v","b///d:k=v"}, - {"b//","/d:k=v","b///d:k=v"}, - {"//b//","/d:k=v","//b///d:k=v"}, - {"//b","////a/////d:k=v","//b//a///d:k=v"}, - {"b//c","////a/////d:k=v","b//c//a///d:k=v"}, - {"b//c","/d:k=v","b//c///d:k=v"}, - {"b//c//","/d:k=v","b//c///d:k=v"}, - {"//b//c//","d/:k=v","//b//c//d/:k=v"}, - }; - - private static String[][] badinsert = { - {"/","d:k=v"}, - {"/","//d:k=v"}, - {"///","d:k=v"}, - {"///","//d:k=v"}, - {"///","/a//d:k=v"}, - {"///","///a//d:k=v"}, - {"///","/////a////d:k=v"}, - {"//b","/////a////d:k=v"}, - {"b/","////a////d:k=v"}, - {"b/","d:k=v"}, - {"b///","d:k=v"}, - {"//b///","d:k=v"}, - {"//b/","////a////d:k=v"}, - {"b///c","////a////d:k=v"}, - {"b//c/","d:k=v"}, - {"b///c//","d:k=v"}, - {"//b///c//","d:k=v"}, - - }; - - public static void testInsertPath() throws Exception { - int i = 0; - for (String[] pair : goodinsert) { - i++; - final String msg = "testInsertPath[good,"+i+"] "+Arrays.asList(pair)+": "; - assertEquals(msg,new ObjectName(pair[2]), - JMXNamespaces.insertPath(pair[0], - new ObjectName(pair[1]))); - } - i=0; - for (String[] bad : badinsert) { - i++; - try { - JMXNamespaces.insertPath(bad[0], - new ObjectName(bad[1])); - failed("testInsertPath[bad,"+i+"] "+ - Arrays.asList(bad)+" incorrectly accepted. " + - "IllegalArgumentException was expected"); - } catch (IllegalArgumentException x) { - // OK - } - } - if (failure != null) throw new Exception(failure); - } - - private static String[][] testpath = { - {"/a/a/:k=v",""}, - {"/:k=v",""}, - {"bli:k=v",""}, - {"///a/a/:k=v",""}, - {"///:k=v",""}, - {"//bli:k=v",""}, - {"/////a/a/:k=v",""}, - {"/////:k=v",""}, - {"////bli:k=v",""}, - {"y///a/a/:k=v","y"}, - {"y///:k=v","y"}, - {"y//bli:k=v","y"}, - {"y/////a/a/:k=v","y"}, - {"y/////:k=v","y"}, - {"y////bli:k=v","y"}, - {"//y///a/a/:k=v","y"}, - {"//y///:k=v","y"}, - {"//y//bli:k=v","y"}, - {"//y/////a/a/:k=v","y"}, - {"//y/////:k=v","y"}, - {"//y////bli:k=v","y"}, - {"////y///a/a/:k=v","y"}, - {"////y///:k=v","y"}, - {"////y//bli:k=v","y"}, - {"////y/////a/a/:k=v","y"}, - {"////y/////:k=v","y"}, - {"////y////bli:k=v","y"}, - - {"z//y///a/a/:k=v","z//y"}, - {"z//y///:k=v","z//y"}, - {"z//y//bli:k=v","z//y"}, - {"z//y/////a/a/:k=v","z//y"}, - {"z//y/////:k=v","z//y"}, - {"z//y////bli:k=v","z//y"}, - {"//z//y///a/a/:k=v","z//y"}, - {"//z//y///:k=v","z//y"}, - {"//z//y//bli:k=v","z//y"}, - {"//z//y/////a/a/:k=v","z//y"}, - {"//z//y/////:k=v","z//y"}, - {"//z//y////bli:k=v","z//y"}, - {"z////y///a/a/:k=v","z//y"}, - {"z////y///:k=v","z//y"}, - {"z////y//bli:k=v","z//y"}, - {"z////y/////a/a/:k=v","z//y"}, - {"z////y/////:k=v","z//y"}, - {"z////y////bli:k=v","z//y"}, - {"//z////y///a/a/:k=v","z//y"}, - {"//z////y///:k=v","z//y"}, - {"//z////y//bli:k=v","z//y"}, - {"//z////y/////a/a/:k=v","z//y"}, - {"//z////y/////:k=v","z//y"}, - {"//z////y////bli:k=v","z//y"}, - {"////z////y///a/a/:k=v","z//y"}, - {"////z////y///:k=v","z//y"}, - {"////z////y//bli:k=v","z//y"}, - {"////z////y/////a/a/:k=v","z//y"}, - {"////z////y/////:k=v","z//y"}, - {"////z////y////bli:k=v","z//y"}, - - }; - - public static void testGetNormalizedPath() throws Exception { - int i = 0; - for (String[] pair : testpath) { - i++; - final String msg = "testGetNormalizedPath["+i+"] "+Arrays.asList(pair)+": "; - assertEquals(msg,pair[1], - JMXNamespaces.getContainingNamespace(new ObjectName(pair[0]))); - } - if (failure != null) throw new Exception(failure); - } - - private static String[][] testdomain = { - {"/a/a/","/a/a/"}, - {"/","/"}, - {"bli","bli"}, - {"///a/a/","///a/a/"}, - {"///","///"}, - {"//bli","//bli"}, - {"/////a/a/","///a/a/"}, - {"/////","///"}, - {"////bli","//bli"}, - {"y///a/a/","y///a/a/"}, - {"y///","y///"}, - {"y//bli","y//bli"}, - {"y/////a/a/","y///a/a/"}, - {"y/////","y///"}, - {"y////bli","y//bli"}, - {"//y///a/a/","//y///a/a/"}, - {"//y///","//y///"}, - {"//y//bli","//y//bli"}, - {"//y/////a/a/","//y///a/a/"}, - {"//y/////","//y///"}, - {"//y////bli","//y//bli"}, - {"////y///a/a/","//y///a/a/"}, - {"////y///","//y///"}, - {"////y//bli","//y//bli"}, - {"////y/////a/a/","//y///a/a/"}, - {"////y/////","//y///"}, - {"////y////bli","//y//bli"}, - - {"z//y///a/a/","z//y///a/a/"}, - {"z//y///","z//y///"}, - {"z//y//bli","z//y//bli"}, - {"z//y/////a/a/","z//y///a/a/"}, - {"z//y/////","z//y///"}, - {"z//y////bli","z//y//bli"}, - {"//z//y///a/a/","//z//y///a/a/"}, - {"//z//y///","//z//y///"}, - {"//z//y//bli","//z//y//bli"}, - {"//z//y/////a/a/","//z//y///a/a/"}, - {"//z//y/////","//z//y///"}, - {"//z//y////bli","//z//y//bli"}, - {"z////y///a/a/","z//y///a/a/"}, - {"z////y///","z//y///"}, - {"z////y//bli","z//y//bli"}, - {"z////y/////a/a/","z//y///a/a/"}, - {"z////y/////","z//y///"}, - {"z////y////bli","z//y//bli"}, - {"//z////y///a/a/","//z//y///a/a/"}, - {"//z////y///","//z//y///"}, - {"//z////y//bli","//z//y//bli"}, - {"//z////y/////a/a/","//z//y///a/a/"}, - {"//z////y/////","//z//y///"}, - {"//z////y////bli","//z//y//bli"}, - {"////z////y///a/a/","//z//y///a/a/"}, - {"////z////y///","//z//y///"}, - {"////z////y//bli","//z//y//bli"}, - {"////z////y/////a/a/","//z//y///a/a/"}, - {"////z////y/////","//z//y///"}, - {"////z////y////bli","//z//y//bli"}, - - {"bli//","bli//"}, - {"//bli//","//bli//"}, - {"////bli//","//bli//"}, - {"y////","y//"}, - {"y//bli//","y//bli//"}, - {"y////","y//"}, - {"y////bli//","y//bli//"}, - {"//y////","//y//"}, - {"//y//bli//","//y//bli//"}, - {"//y//////","//y//"}, - {"//y////bli//","//y//bli//"}, - {"////y////","//y//"}, - {"////y//bli////","//y//bli//"}, - {"////y//////","//y//"}, - {"////y////bli////","//y//bli//"}, - {"z//y////","z//y//"}, - {"z//y//bli//","z//y//bli//"}, - {"z//y//////","z//y//"}, - {"z//y////bli//","z//y//bli//"}, - {"//z//y////","//z//y//"}, - {"//z//y//bli//","//z//y//bli//"}, - {"//z//y//////","//z//y//"}, - {"//z//y////bli//","//z//y//bli//"}, - {"z////y////","z//y//"}, - {"z////y//bli//","z//y//bli//"}, - {"z////y//////","z//y//"}, - {"z////y////bli//","z//y//bli//"}, - {"//z////y////","//z//y//"}, - {"//z////y//bli//","//z//y//bli//"}, - {"//z////y//////","//z//y//"}, - {"//z////y////bli//","//z//y//bli//"}, - {"////z////y////","//z//y//"}, - {"////z////y//bli//","//z//y//bli//"}, - {"////z////y//////","//z//y//"}, - {"////z////y////bli//","//z//y//bli//"}, - - }; - private static String[][] testnolead = { - {"/a/a/","/a/a/"}, - {"/","/"}, - {"bli","bli"}, - {"///a/a/","/a/a/"}, - {"///","/"}, - {"//bli","bli"}, - {"/////a/a/","/a/a/"}, - {"/////","/"}, - {"////bli","bli"}, - {"y///a/a/","y///a/a/"}, - {"y///","y///"}, - {"y//bli","y//bli"}, - {"y/////a/a/","y///a/a/"}, - {"y/////","y///"}, - {"y////bli","y//bli"}, - {"//y///a/a/","y///a/a/"}, - {"//y///","y///"}, - {"//y//bli","y//bli"}, - {"//y/////a/a/","y///a/a/"}, - {"//y/////","y///"}, - {"//y////bli","y//bli"}, - {"////y///a/a/","y///a/a/"}, - {"////y///","y///"}, - {"////y//bli","y//bli"}, - {"////y/////a/a/","y///a/a/"}, - {"////y/////","y///"}, - {"////y////bli","y//bli"}, - - {"z//y///a/a/","z//y///a/a/"}, - {"z//y///","z//y///"}, - {"z//y//bli","z//y//bli"}, - {"z//y/////a/a/","z//y///a/a/"}, - {"z//y/////","z//y///"}, - {"z//y////bli","z//y//bli"}, - {"//z//y///a/a/","z//y///a/a/"}, - {"//z//y///","z//y///"}, - {"//z//y//bli","z//y//bli"}, - {"//z//y/////a/a/","z//y///a/a/"}, - {"//z//y/////","z//y///"}, - {"//z//y////bli","z//y//bli"}, - {"z////y///a/a/","z//y///a/a/"}, - {"z////y///","z//y///"}, - {"z////y//bli","z//y//bli"}, - {"z////y/////a/a/","z//y///a/a/"}, - {"z////y/////","z//y///"}, - {"z////y////bli","z//y//bli"}, - {"//z////y///a/a/","z//y///a/a/"}, - {"//z////y///","z//y///"}, - {"//z////y//bli","z//y//bli"}, - {"//z////y/////a/a/","z//y///a/a/"}, - {"//z////y/////","z//y///"}, - {"//z////y////bli","z//y//bli"}, - {"////z////y///a/a/","z//y///a/a/"}, - {"////z////y///","z//y///"}, - {"////z////y//bli","z//y//bli"}, - {"////z////y/////a/a/","z//y///a/a/"}, - {"////z////y/////","z//y///"}, - {"////z////y////bli","z//y//bli"}, - - {"bli//","bli//"}, - {"//bli//","bli//"}, - {"////bli//","bli//"}, - {"y////","y//"}, - {"y//bli//","y//bli//"}, - {"y////","y//"}, - {"y////bli//","y//bli//"}, - {"//y////","y//"}, - {"//y//bli//","y//bli//"}, - {"//y//////","y//"}, - {"//y////bli//","y//bli//"}, - {"////y////","y//"}, - {"////y//bli////","y//bli//"}, - {"////y//////","y//"}, - {"////y////bli////","y//bli//"}, - {"z//y////","z//y//"}, - {"z//y//bli//","z//y//bli//"}, - {"z//y//////","z//y//"}, - {"z//y////bli//","z//y//bli//"}, - {"//z//y////","z//y//"}, - {"//z//y//bli//","z//y//bli//"}, - {"//z//y//////","z//y//"}, - {"//z//y////bli//","z//y//bli//"}, - {"z////y////","z//y//"}, - {"z////y//bli//","z//y//bli//"}, - {"z////y//////","z//y//"}, - {"z////y////bli//","z//y//bli//"}, - {"//z////y////","z//y//"}, - {"//z////y//bli//","z//y//bli//"}, - {"//z////y//////","z//y//"}, - {"//z////y////bli//","z//y//bli//"}, - {"////z////y////","z//y//"}, - {"////z////y//bli//","z//y//bli//"}, - {"////z////y//////","z//y//"}, - {"////z////y////bli//","z//y//bli//"}, - - }; - - public static void testNormalizeDomain() throws Exception { - int i = 0; - for (String[] pair : testdomain) { - i++; - final String msg = "testNormalizeDomain["+i+", false] "+Arrays.asList(pair)+": "; - assertEquals(msg,pair[1], - ObjectNameRouter.normalizeDomain(pair[0],false)); - } - if (failure != null) throw new Exception(failure); - i = 0; - for (String[] pair : testnolead) { - i++; - final String msg = "testNormalizeDomain["+i+", true] "+Arrays.asList(pair)+": "; - assertEquals(msg,pair[1], - ObjectNameRouter.normalizeDomain(pair[0],true)); - } - if (failure != null) throw new Exception(failure); - } - - public static void main(String[] args) throws Exception { - testDeepRewrite(); - testNormalizeDomain(); - testInsertPath(); - testWildcard(); - testGetNormalizedPath(); - } - - private static void assertEquals(Object x, Object y) { - assertEquals("",x,y); - } - - private static void assertEquals(String msg, Object x, Object y) { - if (msg == null) msg=""; - if (!equal(x, y)) - failed(msg+"expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } - -} diff --git a/test/javax/management/namespace/JMXRemoteNamespaceTest.java b/test/javax/management/namespace/JMXRemoteNamespaceTest.java deleted file mode 100644 index 8e5f795a6..000000000 --- a/test/javax/management/namespace/JMXRemoteNamespaceTest.java +++ /dev/null @@ -1,190 +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. - * - * 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. - */ -/* - * - * @test JMXRemoteNamespaceTest.java - * @summary Basic tests on a JMXRemoteNamespace. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean JMXRemoteNamespaceTest Wombat WombatMBean - * @run build JMXRemoteNamespaceTest Wombat WombatMBean - * @run main JMXRemoteNamespaceTest - */ - -import javax.management.JMX; -import javax.management.Notification; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.NotificationListener; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; -import java.util.List; -import java.util.ArrayList; -import java.util.Collections; -import java.io.IOException; -import javax.management.AttributeChangeNotification; - -/** - * Test simple creation/registration of namespace. - * - */ -public class JMXRemoteNamespaceTest { - - static class MyConnect implements NotificationListener { - private final JMXRemoteNamespace my; - private final List list; - private volatile int connectCount=0; - private int closeCount=0; - private final ObjectName myname; - public MyConnect(JMXRemoteNamespace my, ObjectName myname) { - this.my=my; - this.myname = myname; - list = Collections.synchronizedList(new ArrayList()); - my.addNotificationListener(this, null, null); - } - - public synchronized void connect() throws IOException { - my.connect(); - if (!my.isConnected()) - throw new IOException(myname+" should be connected"); - connectCount++; - } - - public void close() throws IOException { - my.close(); - if (my.isConnected()) - throw new IOException(myname+" shouldn't be connected"); - closeCount++; - } - - public synchronized int getConnectCount() { - return connectCount; - } - public synchronized int getClosedCount() { - return closeCount; - } - - public synchronized void handleNotification(Notification notification, - Object handback) { - list.add(notification); - } - - public synchronized void checkNotifs(int externalConnect, - int externalClosed) throws Exception { - System.err.println("Connected: "+connectCount+" time"+ - ((connectCount>1)?"s":"")); - System.err.println("Closed: "+closeCount+" time"+ - ((closeCount>1)?"s":"")); - System.err.println("Received:"); - int cl=0; - int co=0; - for (Notification n : list) { - System.err.println("\t"+n); - if (!(n instanceof AttributeChangeNotification)) - throw new Exception("Unexpected notif: "+n.getClass()); - final AttributeChangeNotification acn = - (AttributeChangeNotification)n; - if (((Boolean)acn.getNewValue()).booleanValue()) - co++; - else cl++; - if ((((Boolean)acn.getNewValue()).booleanValue()) - == (((Boolean)acn.getOldValue()).booleanValue())) { - throw new Exception("Bad values: old=new"); - } - } - if (! (list.size()==(closeCount+connectCount+ - externalClosed+externalConnect))) { - throw new Exception("Bad notif count - got "+list.size()); - } - if (cl!=(closeCount+externalClosed)) { - throw new Exception("Bad count of close notif: expected " - +(closeCount+externalClosed)+", got"+cl); - } - if (co!=(connectCount+externalConnect)) { - throw new Exception("Bad count of connect notif: expected " - +(connectCount+externalConnect)+", got"+co); - } - } - } - - public static void testConnectClose() throws Exception { - final MBeanServer myServer = MBeanServerFactory.newMBeanServer(); - final JMXConnectorServer myRMI = - JMXConnectorServerFactory.newJMXConnectorServer( - new JMXServiceURL("rmi",null,0), null, myServer); - myRMI.start(); - try { - final JMXRemoteNamespace my = - JMXRemoteNamespace.newJMXRemoteNamespace( - myRMI.getAddress(),null); - final MBeanServer s = MBeanServerFactory.newMBeanServer(); - final ObjectName myname = JMXNamespaces.getNamespaceObjectName("my"); - final ObjectName wname = ObjectName.getInstance("backyard:type=Wombat"); - myServer.registerMBean(new Wombat(),wname); - final MyConnect myc = new MyConnect(my,myname); - myc.connect(); - myc.close(); - myc.connect(); - s.registerMBean(my,myname); - myc.close(); - myc.connect(); - if (!s.queryNames(new ObjectName("my//b*:*"),null).contains( - JMXNamespaces.insertPath("my", wname))) { - throw new RuntimeException("1: Wombat not found: "+wname); - } - myc.close(); - myc.connect(); - final MBeanServer cd = JMXNamespaces.narrowToNamespace(s, "my"); - if (!cd.queryNames(new ObjectName("b*:*"),null).contains(wname)) { - throw new RuntimeException("2: Wombat not found: "+wname); - } - myc.close(); - myc.connect(); - System.out.println("Found a Wombat in my backyard."); - - final String deepThoughts = "I want to leave this backyard!"; - final WombatMBean w = JMX.newMBeanProxy(cd, wname, WombatMBean.class); - w.setCaption(deepThoughts); - if (!deepThoughts.equals(w.getCaption())) - throw new RuntimeException("4: Wombat is not thinking right: "+ - w.getCaption()); - s.unregisterMBean(myname); - if (my.isConnected()) - throw new Exception(myname+" shouldn't be connected"); - myc.connect(); - myc.close(); - myc.checkNotifs(0,1); - } finally { - myRMI.stop(); - } - - } - - public static void main(String... args) throws Exception { - testConnectClose(); - } -} diff --git a/test/javax/management/namespace/JMXRemoteTargetNamespace.java b/test/javax/management/namespace/JMXRemoteTargetNamespace.java deleted file mode 100644 index 633e93021..000000000 --- a/test/javax/management/namespace/JMXRemoteTargetNamespace.java +++ /dev/null @@ -1,216 +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. - */ - - -import java.io.IOException; -import java.util.Map; -import java.util.logging.Logger; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.MBeanException; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServerConnection; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.ReflectionException; -import javax.management.event.EventClient; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.namespace.JMXRemoteNamespaceMBean; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXServiceURL; - -// These options originally in the draft of javax/management/namespaces -// but we decided to retire them - since they could be implemented -// by subclasses. The JMXRemoteTargetNamespace is such a subclass. -// -public class JMXRemoteTargetNamespace extends JMXRemoteNamespace { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(JMXRemoteTargetNamespace.class.getName()); - public static final String CREATE_EVENT_CLIENT = - "jmx.test.create.event.client"; - - private final String sourceNamespace; - private final boolean createEventClient; - - public JMXRemoteTargetNamespace(JMXServiceURL sourceURL, - Map optionsMap) { - this(sourceURL,optionsMap,null); - } - - public JMXRemoteTargetNamespace(JMXServiceURL sourceURL, - Map optionsMap, String sourceNamespace) { - super(sourceURL, optionsMap); - this.sourceNamespace = sourceNamespace; - this.createEventClient = createEventClient(optionsMap); - } - - private boolean createEventClient(Map options) { - if (options == null) return false; - final Object createValue = options.get(CREATE_EVENT_CLIENT); - if (createValue == null) return false; - if (createValue instanceof Boolean) - return ((Boolean)createValue).booleanValue(); - if (createValue instanceof String) - return Boolean.valueOf((String)createValue); - throw new IllegalArgumentException("Bad type for value of property " + - CREATE_EVENT_CLIENT+": "+createValue.getClass().getName()); - } - - @Override - protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc) - throws IOException { - MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc); - if (sourceNamespace != null && sourceNamespace.length() > 0) - mbsc = JMXNamespaces.narrowToNamespace(mbsc, sourceNamespace); - if (createEventClient) - mbsc = EventClient.getEventClientConnection(mbsc); - return mbsc; - } - - - /** - * Creates a target name space to mirror a remote source name space in - * the target server. - * @param targetServer A connection to the target MBean server in which - * the new name space should be created. - * @param targetPath the name space to create in the target server. Note - * that if the target name space is a path - that is if - * {@code targetPath} contains '//', then the parent name space - * must be pre-existing in the target server. Attempting to create - * {code targetPath="a//b//c"} in {@code targetServer} - * will fail if name space {@code "a//b"} doesn't already exists - * in {@code targetServer}. - * @param sourceURL a JMX service URL that can be used to connect to the - * source MBean server. - * @param options the set of options to use when creating the - * {@link #JMXRemoteNamespace JMXRemoteNamespace} that will - * handle the new name space. - * @return An {@code ObjectInstance} representing the - * {@link JMXRemoteNamespaceMBean} which handles the - * new name space. - * - **/ - public static ObjectInstance createNamespace( - MBeanServerConnection targetServer, - String targetPath, - JMXServiceURL sourceURL, - Map options) - throws IOException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException { - final ObjectName name = - JMXNamespaces.getNamespaceObjectName(targetPath); - return createInstance(targetServer, name, sourceURL, options, null); - } - - /** - * Creates a target name space to mirror a remote source name space in - * the target server. - * @param targetServer A connection to the target MBean server in which - * the new name space should be created. - * @param targetPath the name space to create in the target server. Note - * that if the target name space is a path - that is if - * {@code targetPath} contains '//', then the parent name space - * must be pre-existing in the target server. Attempting to create - * {code targetPath="a//b//c"} in {@code targetServer} - * will fail if name space {@code "a//b"} doesn't already exists - * in {@code targetServer}. - * @param sourceURL a JMX service URL that can be used to connect to the - * source MBean server. - * @param sourcePath the source namespace path insode the source server. - * @param options the set of options to use when creating the - * {@link #JMXRemoteNamespace JMXRemoteNamespace} that will - * handle the new name space. - * @return An {@code ObjectInstance} representing the - * {@link JMXRemoteNamespaceMBean} which handles the - * new name space. - * - **/ - public static ObjectInstance createNamespace( - MBeanServerConnection targetServer, - String targetPath, - JMXServiceURL sourceURL, - Map options, - String sourcePath) - throws IOException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException { - final ObjectName name = - JMXNamespaces.getNamespaceObjectName(targetPath); - return createInstance(targetServer, name, sourceURL, options, sourcePath); - } - - /** - * Creates and registers a {@link JMXRemoteNamespaceMBean} in a target - * server, to mirror a remote source name space. - * - * @param server A connection to the target MBean server in which - * the new name space should be created. - * @param handlerName the name of the JMXRemoteNamespace to create. - * This must be a compliant name space handler name as returned - * by {@link - * JMXNamespaces#getNamespaceObjectName JMXNamespaces.getNamespaceObjectName}. - * @param sourceURL a JMX service URL that can be used to connect to the - * source MBean server. - * @param sourcePath the path inside the source server - * @param options the set of options to use when creating the - * {@link #JMXRemoteNamespace JMXRemoteNamespace} that will - * handle the new name space. - * @return An {@code ObjectInstance} representing the new - * {@link JMXRemoteNamespaceMBean} created. - * @see #createNamespace createNamespace - */ - static ObjectInstance createInstance(MBeanServerConnection server, - ObjectName handlerName, - JMXServiceURL sourceURL, Map options, - String sourcePath) - throws IOException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException { - try { - final String[] signature = { - JMXServiceURL.class.getName(), - Map.class.getName(), - String.class.getName() - }; - final Object[] params = { - sourceURL,options,sourcePath - }; - final ObjectInstance instance = - server.createMBean(JMXRemoteTargetNamespace.class.getName(), - handlerName,params,signature); - return instance; - } catch (NotCompliantMBeanException ex) { - throw new RuntimeException("unexpected exception: " + ex, ex); - } catch (ReflectionException ex) { - throw new RuntimeException("unexpected exception: " + ex, ex); - } - } - -} diff --git a/test/javax/management/namespace/LazyDomainTest.java b/test/javax/management/namespace/LazyDomainTest.java deleted file mode 100644 index eda9b6669..000000000 --- a/test/javax/management/namespace/LazyDomainTest.java +++ /dev/null @@ -1,790 +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. - * - * 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. - */ -/* - * - * @test LazyDomainTest.java - * @bug 5072476 - * @summary Basic test for Lazy Domains. - * @author Daniel Fuchs - * @run clean LazyDomainTest Wombat WombatMBean - * @run build LazyDomainTest Wombat WombatMBean - * @run main LazyDomainTest - */ - - -import java.lang.management.ClassLoadingMXBean; -import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.Map; -import java.util.Set; -import javax.management.JMX; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerBuilder; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; -import javax.management.MBeanServerNotification; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.namespace.JMXDomain; -import javax.management.remote.MBeanServerForwarder; - -/** - * Test simple creation/registration of namespace. - * - */ -public class LazyDomainTest { - private static Map emptyEnvMap() { - return Collections.emptyMap(); - } - - - public static interface MBeanServerLoader { - public MBeanServer loadMBeanServer(); - } - - - public static class MBeanServerProxy implements InvocationHandler { - - private final static Map localMap; - static { - localMap = new HashMap(); - for (Method m : MBeanServerForwarder.class.getDeclaredMethods()) { - try { - final Method loc = MBeanServerProxy.class. - getMethod(m.getName(), m.getParameterTypes()); - localMap.put(m, loc); - } catch (Exception x) { - // not defined... - } - } - try { - localMap.put(MBeanServer.class. - getMethod("getMBeanCount", (Class[]) null), - MBeanServerProxy.class. - getMethod("getMBeanCount", (Class[]) null)); - } catch (NoSuchMethodException x) { - // OK. - } - } - - private final MBeanServerLoader loader; - private MBeanServer server; - private final Set domains; - - public MBeanServerProxy(MBeanServerLoader loader) { - if (loader == null) - throw new IllegalArgumentException("null loader"); - this.loader = loader; - this.server = null; - domains = new HashSet(); - } - - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (method.getDeclaringClass().equals(Object.class)) { - return invokeMethod(this,method,args); - } - final Method local = localMap.get(method); - if (local != null) { - return invokeMethod(this,local,args); - } - if (method.getDeclaringClass().equals(MBeanServer.class)) { - return invokeMethod(getMBeanServer(),method,args); - } - throw new NoSuchMethodException(method.getName()); - } - - private Object invokeMethod(Object on, Method method, Object[] args) - throws Throwable { - try { - return method.invoke(on, args); - } catch (InvocationTargetException ex) { - throw ex.getTargetException(); - } - } - - public synchronized MBeanServer getMBeanServer() { - if (server == null) setMBeanServer(loader.loadMBeanServer()); - return server; - } - - public synchronized void setMBeanServer(MBeanServer mbs) { - this.server = mbs; - if (mbs != null) { - for (LazyDomain dom : domains) dom.loaded(); - domains.clear(); - } - } - - public synchronized boolean isLoaded() { - return server != null; - } - - public synchronized void add(LazyDomain dom) { - if (isLoaded()) dom.loaded(); - else domains.add(dom); - } - - public synchronized boolean remove(LazyDomain dom) { - return domains.remove(dom); - } - - public Integer getMBeanCount() { - if (isLoaded()) return server.getMBeanCount(); - else return Integer.valueOf(0); - } - } - - public static class LazyDomain extends JMXDomain { - public static MBeanServer makeProxyFor(MBeanServerProxy proxy) { - return (MBeanServer) - Proxy.newProxyInstance(LazyDomain.class.getClassLoader(), - new Class[] {MBeanServer.class, MBeanServerForwarder.class}, - proxy); - } - - private final MBeanServerProxy proxy; - private volatile NotificationListener listener; - private volatile NotificationFilter filter; - - public LazyDomain(MBeanServerProxy proxy) { - super(makeProxyFor(proxy)); - this.proxy = proxy; - } - - @Override - public Integer getMBeanCount() { - if (proxy.isLoaded()) - return super.getMBeanCount(); - return 0; - } - - - @Override - public synchronized void addMBeanServerNotificationListener( - NotificationListener listener, - NotificationFilter filter) { - if (proxy.isLoaded()) { - super.addMBeanServerNotificationListener(listener, filter); - } else { - this.listener = listener; - this.filter = filter; - proxy.add(this); - } - } - - @Override - public synchronized void removeMBeanServerNotificationListener( - NotificationListener listener) - throws ListenerNotFoundException { - if (this.listener != listener) - throw new ListenerNotFoundException(); - this.listener = null; - this.filter = null; - if (proxy.isLoaded()) - super.removeMBeanServerNotificationListener(listener); - proxy.remove(this); - } - - public synchronized void loaded() { - if (listener != null) - addMBeanServerNotificationListener(listener, filter); - } - - } - - /** - * This is a use case for e.g GlassFish: the LazyStarterDomain MBean - * is a place holder that will unregister itself and autoload a set - * of MBeans in place of its own domain when that domain is - * accessed. - * This is an abstract class, where the only abstract method - * is loadMBeans(MBeanServer). - * Subclasses should implement that method to register whatever MBeans - * in the domain previously held by that LazyStarterDomain object. - * In other words: the LazyStarterDomain MBean is 'replaced' by the - * MBeans loaded by loadMBeans(); - */ - public static abstract class LazyStarterDomain extends LazyDomain { - - /** - * This is a loader that will unregister the JMXDomain that - * created it, and register a bunch of MBeans in its place - * by calling LazyStarterDomain.loadMBeans - * - * That one gave me "la migraine". - */ - private static class HalfGrainLoader implements MBeanServerLoader { - private volatile LazyStarterDomain domain; - public MBeanServer loadMBeanServer() { - if (domain == null) - throw new IllegalStateException( - "JMXDomain MBean not registered!"); - final MBeanServer server = domain.getMBeanServer(); - final ObjectName domainName = domain.getObjectName(); - try { - server.unregisterMBean(domainName); - } catch (Exception x) { - throw new IllegalStateException("Can't unregister " + - "JMXDomain: "+x,x); - } - domain.loadMBeans(server,domainName.getDomain()); - return server; - } - public void setDomain(LazyStarterDomain domain) { - this.domain = domain; - } - } - - /** - * This is an MBeanServerProxy which create a loader for the - * LazyStarterDomain MBean. - */ - private static class DomainStarter extends MBeanServerProxy { - - public DomainStarter() { - this(new HalfGrainLoader()); - } - - private final HalfGrainLoader loader; - private DomainStarter(HalfGrainLoader loader) { - super(loader); - this.loader = loader; - } - - public void setDomain(LazyStarterDomain domain) { - loader.setDomain(domain); - } - } - - /** - * A new LazyStarterDomain. When the domain monitored by this - * MBean is accessed, this MBean will unregister itself and call - * the abstract loadMBeans(MBeanServer) method. - * Subclasses need only to implement loadMBeans(). - */ - public LazyStarterDomain() { - this(new DomainStarter()); - } - - private LazyStarterDomain(DomainStarter starter) { - super(starter); - starter.setDomain(this); - } - - // Contrarily to its LazyDomain superclass, this LazyDomain - // doesn't wrapp another MBeanServer: it simply registers a bunch - // of MBeans in its own MBeanServer. - // Thus, there's no notifications to forward. - // - @Override - public void addMBeanServerNotificationListener( - NotificationListener listener, NotificationFilter filter) { - // nothing to do. - } - - // Contrarily to its LazyDomain superclass, this LazyDomain - // doesn't wrapp another MBeanServer: it simply registers a bunch - // of MBeans in its own MBeanServer. - // Thus, there's no notifications to forward. - // - @Override - public void removeMBeanServerNotificationListener( - NotificationListener listener) throws ListenerNotFoundException { - // nothing to do - } - - // If this domain is registered, it contains no MBean. - // If it is not registered, then it no longer contain any MBean. - // The MBeanCount is thus always 0. - @Override - public Integer getMBeanCount() { - return 0; - } - - /** - * Called when the domain is first accessed. - * {@code server} is the server in which this MBean was registered. - * A subclass must override this method in order to register - * the MBeans that should be contained in domain. - * - * @param server the server in which to load the MBeans. - * @param domain the domain in which the MBeans should be registered. - */ - protected abstract void loadMBeans(MBeanServer server, String domain); - - - } - - private static MBeanServerNotification pop( - BlockingQueue queue, - String type, - ObjectName mbean, - String test) - throws InterruptedException { - final Notification n = queue.poll(1, TimeUnit.SECONDS); - if (!(n instanceof MBeanServerNotification)) - fail(test+"expected MBeanServerNotification, got "+n); - final MBeanServerNotification msn = (MBeanServerNotification)n; - if (!type.equals(msn.getType())) - fail(test+"expected "+type+", got "+msn.getType()); - if (!mbean.apply(msn.getMBeanName())) - fail(test+"expected "+mbean+", got "+msn.getMBeanName()); - System.out.println(test+" got: "+msn); - return msn; - } - private static MBeanServerNotification popADD( - BlockingQueue queue, - ObjectName mbean, - String test) - throws InterruptedException { - return pop(queue, MBeanServerNotification.REGISTRATION_NOTIFICATION, - mbean, test); - } - - private static MBeanServerNotification popREM( - BlockingQueue queue, - ObjectName mbean, - String test) - throws InterruptedException { - return pop(queue, MBeanServerNotification.UNREGISTRATION_NOTIFICATION, - mbean, test); - } - - - private static void fail(String msg) { - raise(new RuntimeException(msg)); - } - - private static void fail(String msg, Throwable cause) { - raise(new RuntimeException(msg,cause)); - } - - private static void raise(RuntimeException x) { - lastException = x; - exceptionCount++; - throw x; - } - - private static volatile Exception lastException = null; - private static volatile int exceptionCount = 0; - - // ZZZ need to add a test case with several LazyDomains, and - // need to test that nothing is loaded until the lazy domains - // are accessed... - // - - private static void registerWombats(MBeanServer server, String domain, - int count) { - try { - for (int i=0;i queue = - new ArrayBlockingQueue(100); - - // A listener that puts notifs in the queue. - final NotificationListener l = new NotificationListener() { - - public void handleNotification(Notification notification, - Object handback) { - try { - if (!queue.offer(notification, 5, TimeUnit.SECONDS)) { - throw new RuntimeException("timeout exceeded"); - } - } catch (Exception x) { - fail(test + "failed to handle notif", x); - } - } - }; - - // Create a LazyDomain for each of the platform domain. - // All platform domain share the same MBeanServer proxy, which means - // that loading one domain will also load all the others. - // - Map domainsMap = new HashMap(); - for (String dom : platformDomains) { - domainsMap.put(dom, new LazyDomain(platform)); - } - domainsMap.put("custom.awomb", new LazyDomain(customa)); - domainsMap.put("custom.bwomb", new LazyDomain(customb)); - - for (Map.Entry e : domainsMap.entrySet()) { - server.registerMBean(e.getValue(), - JMXDomain.getDomainObjectName(e.getKey())); - } - - // check that lazy MBeans are not there... - checkSize(test,server,domainsMap.size()+1); - - System.out.println(test+" registering listener with delegate."); - server.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, l, - null, null); - - // check that lazy MBeans are not there... - checkSize(test,server,domainsMap.size()+1); - - // force loading of custom.awomb. - final ObjectName awombat = new ObjectName( - "custom.awomb:type=Wombat,name=wombat#"+customCount/2); - if (!server.isRegistered(awombat)) - fail(test+"Expected "+awombat+" to be reggistered!"); - - final int oldCount = domainsMap.size()+1+customCount; - checkSize(test,server,oldCount); - - if (queue.peek() != null) - fail(test+"Received unexpected notifications: "+queue); - - - System.out.println(test+"creating a proxy for ClassLoadingMXBean."); - final ClassLoadingMXBean cl = - JMX.newMXBeanProxy(server, - new ObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME), - ClassLoadingMXBean.class); - - checkSize(test,server,oldCount); - - System.out.println(test+"Loaded classes: "+cl.getLoadedClassCount()); - - final int newCount = server.getMBeanCount(); - if (newCount < oldCount+6) - fail(test+"Expected at least "+(oldCount+6)+ - " MBeans. Found "+newCount); - - final ObjectName jwombat = new ObjectName("java.lang:type=Wombat"); - server.createMBean("Wombat", jwombat); - System.out.println(test+"Created "+jwombat); - checkSize(test,server,newCount+1); - - popADD(queue, jwombat, test); - if (queue.peek() != null) - fail(test+"Received unexpected notifications: "+queue); - - - int platcount = 0; - for (String dom : platformDomains) { - final Set found = - server.queryNames(new ObjectName(dom+":*"),null); - final int jcount = found.size(); - System.out.println(test+"Found "+jcount+" MBeans in "+dom+ - ": "+found); - checkSize(test,server,newCount+1); - platcount += (jcount-1); - } - checkSize(test,server,oldCount+platcount); - - final ObjectName owombat = new ObjectName("custom:type=Wombat"); - server.createMBean("Wombat", owombat); - System.out.println(test+"Created "+owombat); - checkSize(test,server,newCount+2); - popADD(queue, owombat, test); - if (queue.peek() != null) - fail(test+"Received unexpected notifications: "+queue); - - final Set jwombatView = (Set) - server.invoke(jwombat, "listMatching", new Object[] {null}, - new String[] {ObjectName.class.getName()}); - System.out.println(test+jwombat+" sees: "+jwombatView); - checkSize(test, server, newCount+2); - if (jwombatView.size() != (platcount+1)) - fail(test+jwombat+" sees "+jwombatView.size()+" MBeans - should" + - " have seen "+(platcount+1)); - - final Set platformMBeans = - ManagementFactory.getPlatformMBeanServer(). - queryNames(null, null); - if (!platformMBeans.equals(jwombatView)) - fail(test+jwombat+" should have seen "+platformMBeans); - - // check that awombat triggers loading of bwombats - final Set awombatView = (Set) - server.invoke(awombat, "listMatching", new Object[] {null}, - new String[] {ObjectName.class.getName()}); - System.out.println(test+awombat+" sees: "+awombatView); - final int totalCount = newCount+2+customCount; - checkSize(test, server, totalCount); - if (awombatView.size() != totalCount) - fail(test+jwombat+" sees "+jwombatView.size()+" MBeans - should" + - " have seen "+totalCount); - - final Set allMBeans = server. - queryNames(null, null); - if (!allMBeans.equals(awombatView)) - fail(test+awombat+" should have seen "+allMBeans); - - System.out.println(test + " PASSED"); - - } - - - public static void lazyStarterTest() throws Exception { - final String test = "lazyStarterTest: "; - System.out.println("" + - "\nThis test checks that it is possible to perform lazy loading" + - "\nof MBeans in a given domain by using a transient JMXDomain" + - "\nsubclass for that domain. "); - - System.out.println(test + " START"); - - // The "global" MBeanServer... - final MBeanServer platform = - ManagementFactory.getPlatformMBeanServer(); - - // A notification queue. - final BlockingQueue queue = - new ArrayBlockingQueue(100); - - // A listener that puts notifs in the queue. - final NotificationListener l = new NotificationListener() { - - public void handleNotification(Notification notification, - Object handback) { - try { - if (!queue.offer(notification, 5, TimeUnit.SECONDS)) { - throw new RuntimeException("timeout exceeded"); - } - } catch (Exception x) { - fail(test + "failed to handle notif", x); - } - } - }; - - System.out.println(test+" registering listener with delegate."); - platform.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, l, - null, null); - - final String ld1 = "lazy1"; - final String ld2 = "lazy2"; - final int wCount = 5; - final LazyStarterDomain lazy1 = new LazyStarterDomain() { - @Override - protected void loadMBeans(MBeanServer server, String domain) { - registerWombats(server, ld1, wCount); - } - }; - final LazyStarterDomain lazy2 = new LazyStarterDomain() { - @Override - protected void loadMBeans(MBeanServer server, String domain) { - registerWombats(server, ld2, wCount); - } - }; - final ObjectName lo1 = JMXDomain.getDomainObjectName(ld1); - final ObjectName lo2 = JMXDomain.getDomainObjectName(ld2); - - final int initial = platform.getMBeanCount(); - - platform.registerMBean(lazy1, lo1); - System.out.println(test+"registered "+lo1); - checkSize(test, platform, initial+1); - popADD(queue, lo1, test); - - platform.registerMBean(lazy2, lo2); - System.out.println(test+"registered "+lo2); - checkSize(test, platform, initial+2); - popADD(queue, lo2, test); - - - final ObjectName awombat = new ObjectName( - ld1+":type=Wombat,name=wombat#"+wCount/2); - if (!platform.isRegistered(awombat)) - fail(test+"Expected "+awombat+" to be reggistered!"); - checkSize(test,platform,initial+wCount+1); - popREM(queue, lo1, test); - final ObjectName pat1 = - new ObjectName(ld1+":type=Wombat,name=wombat#*"); - for (int i=0;i all = platform.queryNames(null, null); - popREM(queue, lo2, test); - System.out.println(test+"Now found: "+all); - checkSize(test,platform,initial+wCount+wCount); - final ObjectName pat2 = - new ObjectName(ld2+":type=Wombat,name=wombat#*"); - for (int i=0;i testConcurrent = - new HashMap(); - for (int i=0;i<(100/wCount);i++) { - final String ld = "concurrent.lazy"+i; - final LazyStarterDomain lazy = new LazyStarterDomain() { - @Override - protected void loadMBeans(MBeanServer server, String domain) { - registerWombats(server, ld, wCount-1); - } - }; - testConcurrent.put(ld, lazy); - final ObjectName lo = JMXDomain.getDomainObjectName(ld); - platform.registerMBean(lazy, lo); - popADD(queue, lo, test); - } - - System.out.println(test+"Big autoload: "+ - platform.queryNames(null,null)); - System.out.println(test+"Big after load: "+ - platform.queryNames(null,null)); - if (!platform.queryNames(JMXDomain.getDomainObjectName("*"), null). - isEmpty()) { - fail(test+" some domains are still here: "+ - platform.queryNames( - JMXDomain.getDomainObjectName("*"), null)); - } - queue.clear(); - System.out.println(test+"PASSED: The DomainDispatcher appears to be " + - "resilient to concurrent modifications."); - } - - public static void main(String... args) throws Exception { - - lazyTest(); - lazyStarterTest(); - - if (lastException != null) - throw lastException; - } -} diff --git a/test/javax/management/namespace/LeadingSeparatorsTest.java b/test/javax/management/namespace/LeadingSeparatorsTest.java deleted file mode 100644 index 6f931ffd4..000000000 --- a/test/javax/management/namespace/LeadingSeparatorsTest.java +++ /dev/null @@ -1,238 +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. - * - * 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. - */ -/* - * @test LeadingSeparatorsTest.java - * @summary Test that the semantics of a leading // in ObjectName is respected. - * @author Daniel Fuchs - * @bug 5072476 6768935 - * @run clean LeadingSeparatorsTest Wombat WombatMBean - * @compile -XDignore.symbol.file=true LeadingSeparatorsTest.java - * @run build LeadingSeparatorsTest Wombat WombatMBean - * @run main LeadingSeparatorsTest - */ - -import java.lang.management.ManagementFactory; -import java.util.Arrays; -import java.util.Set; -import java.util.HashSet; -import java.util.logging.Logger; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.namespace.JMXNamespace; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * Class LeadingSeparatorsTest - * @author Sun Microsystems, 2005 - All rights reserved. - */ -public class LeadingSeparatorsTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(LeadingSeparatorsTest.class.getName()); - - /** Creates a new instance of NullObjectNameTest */ - public LeadingSeparatorsTest() { - } - - public static interface MyWombatMBean extends WombatMBean { - public Set untrue(ObjectName pat) throws Exception; - } - public static class MyWombat - extends Wombat implements MyWombatMBean { - public MyWombat() throws NotCompliantMBeanException { - super(MyWombatMBean.class); - } - - public Set untrue(ObjectName pat) throws Exception { - final Set res=listMatching(pat.withDomain("*")); - final Set untrue = new HashSet(); - for (ObjectName a:res) { - untrue.add(a.withDomain(pat.getDomain()+"//"+a.getDomain())); - } - return untrue; - } - } - - static String failure=null; - - public static void testRegister() throws Exception { - final MBeanServer top = ManagementFactory.getPlatformMBeanServer(); - final MBeanServer sub = MBeanServerFactory.createMBeanServer(); - final JMXServiceURL url = new JMXServiceURL("rmi",null,0); - final JMXConnectorServer srv = - JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub); - srv.start(); - - try { - - // Create a namespace rmi// that points to 'sub' and flows through - // a JMXRemoteNamespace connected to 'srv' - // The namespace rmi// will accept createMBean, but not registerMBean. - // - final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace. - newJMXRemoteNamespace(srv.getAddress(),null); - top.registerMBean(rmiHandler, - JMXNamespaces.getNamespaceObjectName("rmi")); - top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"), - "connect", null, null); - - // Create a namespace direct// that points to 'sub' and flows - // through a direct reference to 'sub'. - // The namespace direct// will accept createMBean, and registerMBean. - // - final JMXNamespace directHandler = new JMXNamespace(sub); - top.registerMBean(directHandler, - JMXNamespaces.getNamespaceObjectName("direct")); - - final ObjectName n1 = new ObjectName("//direct//w:type=Wombat"); - final ObjectName n2 = new ObjectName("direct//w:type=Wombat"); - final ObjectName n3 = new ObjectName("//rmi//w:type=Wombat"); - final ObjectName n4 = new ObjectName("rmi//w:type=Wombat"); - - // register wombat using an object name with a leading // - final Object obj = new MyWombat(); - // check that returned object name doesn't have the leading // - assertEquals(n2,top.registerMBean(obj, n2).getObjectName()); - System.out.println(n1+" registered"); - - // check that the registered Wombat can be accessed with all its - // names. - System.out.println(n2+" mood is: "+top.getAttribute(n2, "Mood")); - try { - System.out.println(n1+" mood is: "+top.getAttribute(n1, "Mood")); - throw new Exception("Excepected exception not thrown for "+n1); - } catch (InstanceNotFoundException x) { - System.out.println("OK: "+x); - } - System.out.println(n4+" mood is: "+top.getAttribute(n4, "Mood")); - try { - System.out.println(n3+" mood is: "+top.getAttribute(n3, "Mood")); - throw new Exception("Excepected exception not thrown for "+n3); - } catch (InstanceNotFoundException x) { - System.out.println("OK: "+x); - } - - // call listMatching. The result should not contain any prefix. - final Set res = (Set) - top.invoke(n4, "listMatching", - // remove rmi// from rmi//*:* - JMXNamespaces.deepReplaceHeadNamespace( - new Object[] {ObjectName.WILDCARD.withDomain("rmi//*")}, - "rmi", ""), new String[] {ObjectName.class.getName()}); - - // add rmi// prefix to all names in res. - final Set res1 = - JMXNamespaces.deepReplaceHeadNamespace(res, "", "rmi"); - System.out.println("got: "+res1); - - // compute expected result - final Set res2 = sub.queryNames(null,null); - final Set res3 = new HashSet(); - for (ObjectName o:res2) { - res3.add(o.withDomain("rmi//"+o.getDomain())); - } - System.out.println("expected: "+res3); - assertEquals(res1, res3); - - // invoke "untrue(//niark//niark:*)" - // should return a set were all ObjectNames begin with - // //niark//niark// - // - final Set res4 = (Set) - top.invoke(n4, "untrue", - // remove niark//niark : should remove nothing since - // our ObjectName begins with a leading // - JMXNamespaces.deepReplaceHeadNamespace( - new Object[] { - ObjectName.WILDCARD.withDomain("//niark//niark")}, - "niark//niark", ""), - new String[] {ObjectName.class.getName()}); - System.out.println("got: "+res4); - - // add rmi// should add nothing since the returned names have a - // leading // - // - final Set res5 = - JMXNamespaces.deepReplaceHeadNamespace(res4, "", "rmi"); - System.out.println("got#2: "+res5); - - // compute expected result - final Set res6 = new HashSet(); - for (ObjectName o:res2) { - res6.add(o.withDomain("//niark//niark//"+o.getDomain())); - } - System.out.println("expected: "+res6); - - // both res4 and res5 should be equals to the expected result. - assertEquals(res4, res6); - assertEquals(res5, res6); - - } finally { - srv.stop(); - } - - if (failure != null) - throw new Exception(failure); - - - } - private static void assertEquals(Object x, Object y) { - if (!equal(x, y)) - failed("expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } - - public static void main(String[] args) throws Exception { - testRegister(); - } -} diff --git a/test/javax/management/namespace/MXBeanRefTest.java b/test/javax/management/namespace/MXBeanRefTest.java deleted file mode 100644 index afdc0ae97..000000000 --- a/test/javax/management/namespace/MXBeanRefTest.java +++ /dev/null @@ -1,181 +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. - * - * 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. - */ -/* - * @test MXBeanRefTest.java - * @bug 5072476 - * @summary Test that MXBean proxy references work correctly in the presence - * of namespaces. - * @author Eamonn Mcmanus - */ - -/** - * The idea is that we will create a hierarchy like this: - * a// - * X - * b// - * Y - * Z - * and we will use MXBean references so we have links like this: - * a// - * X----+ - * b// | - * / - * Y - * \ - * / - * Z - * In other words, X.getY() will return a proxy for Y, which the MXBean - * framework will map to b//Y. A proxy for a//X should then map this - * into a proxy for a//b//Y. That's easy. But then if we call getZ() - * on this proxy, the MXBean framework will return just Z, and the proxy - * must map that into a proxy for a//b//Z. - */ - -import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Proxy; -import java.lang.reflect.UndeclaredThrowableException; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.MBeanServerInvocationHandler; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.openmbean.OpenDataException; - -public class MXBeanRefTest { - - public static interface ZMXBean { - public void success(); - } - public static class ZImpl implements ZMXBean { - public void success() {} - } - - public static interface YMXBean { - public ZMXBean getZ(); - public void setZ(ZMXBean z); - } - public static class YImpl implements YMXBean { - private ZMXBean z; - - public YImpl(ZMXBean z) { - this.z = z; - } - - public ZMXBean getZ() { - return z; - } - - public void setZ(ZMXBean z) { - this.z = z; - } - } - - public static interface XMXBean { - public YMXBean getY(); - } - public static class XImpl implements XMXBean { - private final YMXBean yProxy; - - public XImpl(YMXBean yProxy) { - this.yProxy = yProxy; - } - - public YMXBean getY() { - return yProxy; - } - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - - // Set up namespace hierarchy a//b// - MBeanServer ambs = MBeanServerFactory.newMBeanServer(); - MBeanServer bmbs = MBeanServerFactory.newMBeanServer(); - JMXNamespace bHandler = new JMXNamespace(bmbs); - ObjectName bHandlerName = JMXNamespaces.getNamespaceObjectName("b"); - System.out.println(bHandlerName); - ambs.registerMBean(bHandler, bHandlerName); - JMXNamespace aHandler = new JMXNamespace(ambs); - ObjectName aHandlerName = JMXNamespaces.getNamespaceObjectName("a"); - mbs.registerMBean(aHandler, aHandlerName); - - ZMXBean z = new ZImpl(); - ObjectName zName = new ObjectName("foo:type=Z"); - bmbs.registerMBean(z, zName); - - YMXBean y = new YImpl(z); - ObjectName yName = new ObjectName("foo:type=Y"); - bmbs.registerMBean(y, yName); - - ObjectName yNameInA = new ObjectName("b//" + yName); - System.out.println("MBeanInfo for Y as seen from a//:"); - System.out.println(ambs.getMBeanInfo(yNameInA)); - YMXBean yProxyInA = JMX.newMXBeanProxy(ambs, yNameInA, YMXBean.class); - XMXBean x = new XImpl(yProxyInA); - ObjectName xName = new ObjectName("foo:type=X"); - ambs.registerMBean(x, xName); - - ObjectName xNameFromTop = new ObjectName("a//" + xName); - XMXBean xProxy = JMX.newMXBeanProxy(mbs, xNameFromTop, XMXBean.class); - System.out.println("Name of X Proxy: " + proxyName(xProxy)); - YMXBean yProxy = xProxy.getY(); - System.out.println("Name of Y Proxy: " + proxyName(yProxy)); - ZMXBean zProxy = yProxy.getZ(); - System.out.println("Name of Z Proxy: " + proxyName(zProxy)); - - System.out.println("Operation through Z proxy..."); - zProxy.success(); - - System.out.println("Changing Y's ref to Z..."); - yProxy.setZ(zProxy); - zProxy = yProxy.getZ(); - System.out.println("Name of Z Proxy now: " + proxyName(zProxy)); - System.out.println("Operation through Z proxy again..."); - zProxy.success(); - - System.out.println("Changing Y's ref to a bogus one..."); - ZMXBean zProxyBad = JMX.newMXBeanProxy(mbs, zName, ZMXBean.class); - try { - yProxy.setZ(zProxyBad); - } catch (UndeclaredThrowableException e) { - Throwable cause = e.getCause(); - if (cause instanceof OpenDataException) { - System.out.println("...correctly got UndeclaredThrowableException"); - System.out.println("...wrapping: " + cause); - } else - throw new Exception("FAILED: wrong exception: " + cause); - } - - System.out.println("Test passed"); - } - - private static ObjectName proxyName(Object proxy) { - InvocationHandler ih = Proxy.getInvocationHandler(proxy); - MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler) ih; - return mbsih.getObjectName(); - } -} diff --git a/test/javax/management/namespace/NamespaceController.java b/test/javax/management/namespace/NamespaceController.java deleted file mode 100644 index f5a1c42e2..000000000 --- a/test/javax/management/namespace/NamespaceController.java +++ /dev/null @@ -1,405 +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. - */ - -import com.sun.jmx.namespace.ObjectNameRouter; -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.JMX; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -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.ReflectionException; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespaceMBean; -import javax.management.remote.JMXServiceURL; - -/** - * The {@code NamespaceController} MBean makes it possible to easily - * create mount points ({@linkplain JMXNamespace JMXNamespaces}) in an - * {@code MBeanServer}. - * There is at most one instance of NamespaceController in an - * MBeanServer - which can be created using the {@link #createInstance - * createInstance} method. The {@code NamespaceController} MBean will - * make it possible to remotely create name spaces by mounting remote - * MBeanServers into the MBeanServer in which it was registered. - */ -// This API was originally in the draft of javax/management/namespaces -// but we decided to retire it. Rather than removing all the associated -// tests I have moved the API to the test hierarchy - so it is now used as -// an additional (though somewhat complex) test case... -// -public class NamespaceController implements NamespaceControllerMBean, - NotificationEmitter, MBeanRegistration { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(NamespaceController.class.getName()); - - private static long seqNumber=0; - - private final NotificationBroadcasterSupport broadcaster = - new NotificationBroadcasterSupport(); - - private volatile MBeanServer mbeanServer = null; - - private volatile ObjectName objectName = null; - - //was: NamespaceController.class.getPackage().getName() - public static final String NAMESPACE_CONTROLLER_DOMAIN = "jmx.ns"; - - /** - * Creates a new NamespaceController. - * Using {@link #createInstance} should be preferred. - **/ - public NamespaceController() { - this(null); - } - - public NamespaceController(MBeanServer mbeanServer) { - this.mbeanServer = mbeanServer; - } - - /* - * MBeanNotification support - * You shouldn't update these methods - */ - public final void addNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) { - broadcaster.addNotificationListener(listener, filter, handback); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[] { - }; - } - - public final void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - broadcaster.removeNotificationListener(listener); - } - - public final void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, Object handback) - throws ListenerNotFoundException { - broadcaster.removeNotificationListener(listener, filter, handback); - } - - public static synchronized long getNextSeqNumber() { - return seqNumber++; - } - - protected final void sendNotification(Notification n) { - if (n.getSequenceNumber()<=0) - n.setSequenceNumber(getNextSeqNumber()); - if (n.getSource()==null) - n.setSource(objectName); - broadcaster.sendNotification(n); - } - - /** - * The ObjectName with which this MBean was registered. - *

    Unless changed by subclasses, this is - * {@code - * "javax.management.namespace:type="+this.getClass().getSimpleName()}. - * @return this MBean's ObjectName, or null if this MBean was never - * registered. - **/ - public final ObjectName getObjectName() { - return objectName; - } - - /** - * The MBeanServer served by this NamespaceController. - * @return the MBeanServer served by this NamespaceController. - **/ - public final MBeanServer getMBeanServer() { - return mbeanServer; - } - - /** - * Allows the MBean to perform any operations it needs before being - * registered in the MBean server. If the name of the MBean is not - * specified, the MBean can provide a name for its registration. If - * any exception is raised, the MBean will not be registered in the - * MBean server. Subclasses which override {@code preRegister} - * must call {@code super.preRegister(name,server)}; - * @param server The MBean server in which the MBean will be registered. - * @param name The object name of the MBean. - * The name must be either {@code null} - or equal to that - * described by {@link #getObjectName}. - * @return The name under which the MBean is to be registered. - * This will be the name described by {@link #getObjectName}. - * @throws MalformedObjectNameException if the supplied name does not - * meet expected requirements. - */ - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws MalformedObjectNameException { - objectName = name; - final ObjectName single = - ObjectName.getInstance(NAMESPACE_CONTROLLER_DOMAIN+ - ":type="+this.getClass().getSimpleName()); - if (name!=null && !single.equals(name)) - throw new MalformedObjectNameException(name.toString()); - if (mbeanServer == null) mbeanServer = server; - return single; - } - - /** - * Allows the MBean to perform any operations needed after having - * been registered in the MBean server or after the registration has - * failed. - * @param registrationDone Indicates whether or not the MBean has been - * successfully registered in the MBean server. The value false means - * that the registration has failed. - */ - public void postRegister(Boolean registrationDone) { - //TODO postRegister implementation; - } - - /** - * Allows the MBean to perform any operations it needs before being - * unregistered by the MBean server. - * @throws Exception This exception will be caught by the MBean server and - * re-thrown as an MBeanRegistrationException. - */ - public void preDeregister() throws Exception { - //TODO preDeregister implementation; - } - - /** - * Allows the MBean to perform any operations needed after having been - * unregistered in the MBean server. - */ - public void postDeregister() { - //TODO postDeregister implementation; - } - - public String mount(JMXServiceURL url, - String targetPath, - Map optionsMap) - throws IOException { - return mount(url, targetPath, "", optionsMap); - } - - // see NamespaceControllerMBean - public String mount(JMXServiceURL url, - String targetPath, - String sourcePath, - Map optionsMap) - throws IOException { - - // TODO: handle description. - final String dirName = - JMXNamespaces.normalizeNamespaceName(targetPath); - - try { - final ObjectInstance moi = - JMXRemoteTargetNamespace.createNamespace(mbeanServer, - dirName,url,optionsMap, - JMXNamespaces.normalizeNamespaceName(sourcePath) - ); - final ObjectName nsMBean = moi.getObjectName(); - try { - mbeanServer.invoke(nsMBean, "connect", null,null); - } catch (Throwable t) { - mbeanServer.unregisterMBean(nsMBean); - throw t; - } - return getMountPointID(nsMBean); - } catch (InstanceAlreadyExistsException x) { - throw new IllegalArgumentException(targetPath,x); - } catch (IOException x) { - throw x; - } catch (Throwable x) { - if (x instanceof Error) throw (Error)x; - Throwable cause = x.getCause(); - if (cause instanceof IOException) - throw ((IOException)cause); - if (cause == null) cause = x; - - final IOException io = - new IOException("connect failed: "+cause); - io.initCause(cause); - throw io; - } - } - - private String getMountPointID(ObjectName dirName) { - return dirName.toString(); - } - - private ObjectName getHandlerName(String mountPointID) { - try { - final ObjectName tryit = ObjectName.getInstance(mountPointID); - final ObjectName formatted = - JMXNamespaces.getNamespaceObjectName(tryit.getDomain()); - if (!formatted.equals(tryit)) - throw new IllegalArgumentException(mountPointID+ - ": invalid mountPointID"); - return formatted; - } catch (MalformedObjectNameException x) { - throw new IllegalArgumentException(mountPointID,x); - } - } - - public boolean unmount(String mountPointID) - throws IOException { - final ObjectName dirName = getHandlerName(mountPointID); - if (!mbeanServer.isRegistered(dirName)) - throw new IllegalArgumentException(mountPointID+ - ": no such name space"); - final JMXRemoteNamespaceMBean mbean = - JMX.newMBeanProxy(mbeanServer,dirName, - JMXRemoteNamespaceMBean.class); - try { - mbean.close(); - } catch (IOException io) { - LOG.fine("Failed to close properly - ignoring exception: "+io); - LOG.log(Level.FINEST, - "Failed to close properly - ignoring exception",io); - } finally { - try { - mbeanServer.unregisterMBean(dirName); - } catch (InstanceNotFoundException x) { - throw new IllegalArgumentException(mountPointID+ - ": no such name space", x); - } catch (MBeanRegistrationException x) { - final IOException io = - new IOException(mountPointID +": failed to unmount"); - io.initCause(x); - throw io; - } - } - return true; - } - - public boolean ismounted(String targetPath) { - return mbeanServer.isRegistered(JMXNamespaces.getNamespaceObjectName(targetPath)); - } - - public ObjectName getHandlerNameFor(String targetPath) { - return JMXNamespaces.getNamespaceObjectName(targetPath); - } - - public String[] findNamespaces() { - return findNamespaces(null,null,0); - } - - - private ObjectName getDirPattern(String from) { - try { - if (from == null) - return ObjectName.getInstance(ALL_NAMESPACES); - final String namespace = - ObjectNameRouter.normalizeNamespacePath(from,false,true,false); - if (namespace.equals("")) - return ObjectName.getInstance(ALL_NAMESPACES); - if (JMXNamespaces.getNamespaceObjectName(namespace).isDomainPattern()) - throw new IllegalArgumentException(from); - return ObjectName.getInstance(namespace+NAMESPACE_SEPARATOR+ALL_NAMESPACES); - } catch (MalformedObjectNameException x) { - throw new IllegalArgumentException(from,x); - } - } - - public String[] findNamespaces(String from, String regex, int depth) { - if (depth < 0) return new String[0]; - final Set res = new TreeSet(); - final ObjectName all = getDirPattern(from); - Set names = mbeanServer.queryNames(all,null); - for (ObjectName dirName : names) { - final String dir = dirName.getDomain(); - if (regex == null || dir.matches(regex)) - res.add(dir); - if (depth > 0) - res.addAll(Arrays.asList(findNamespaces(dir,regex,depth-1))); - } - return res.toArray(new String[res.size()]); - } - - /** - * Creates a {@link NamespaceController} MBean in the provided - * {@link MBeanServerConnection}. - *

    The name of the MBean is that returned by {@link #preRegister} - * as described by {@link #getObjectName}. - * @throws IOException if an {@code IOException} is raised when invoking - * the provided connection. - * @throws InstanceAlreadyExistsException if an MBean was already - * registered with the NamespaceController's name. - * @throws MBeanRegistrationException if thrown by {@link - * MBeanServerConnection#createMBean(java.lang.String,javax.management.ObjectName) - * server.createMBean} - * @throws MBeanException if thrown by {@link - * MBeanServerConnection#createMBean(java.lang.String,javax.management.ObjectName) - * server.createMBean} - * @return the {@link ObjectInstance}, as returned by {@link - * MBeanServerConnection#createMBean(java.lang.String,javax.management.ObjectName) - * server.createMBean} - **/ - public static ObjectInstance createInstance(MBeanServerConnection server) - throws IOException, InstanceAlreadyExistsException, - MBeanRegistrationException, MBeanException { - try { - final ObjectInstance instance = - server.createMBean(NamespaceController.class.getName(), null); - return instance; - } catch (NotCompliantMBeanException ex) { - throw new RuntimeException("unexpected exception: " + ex, ex); - } catch (ReflectionException ex) { - throw new RuntimeException("unexpected exception: " + ex, ex); - } - } - - private final static String ALL_NAMESPACES= - "*"+NAMESPACE_SEPARATOR+":"+ - JMXNamespace.TYPE_ASSIGNMENT; - -} diff --git a/test/javax/management/namespace/NamespaceControllerMBean.java b/test/javax/management/namespace/NamespaceControllerMBean.java deleted file mode 100644 index b7bc3457e..000000000 --- a/test/javax/management/namespace/NamespaceControllerMBean.java +++ /dev/null @@ -1,143 +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. - */ - -import java.io.IOException; -import java.util.Map; - -import javax.management.ObjectName; -import javax.management.remote.JMXServiceURL; - -/** - * The {@link NamespaceController} MBean makes it possible to easily - * create mount points ({@link JMXNamespace JMXNamespaces}) in an - * {@code MBeanServer}. - */ -// This API was originally in the draft of javax/management/namespaces -// but we decided to retire it. Rather than removing all the associated -// tests I have moved the API to the test hierarchy - so it is now used as -// an additional (though somewhat complex) test case... -// -public interface NamespaceControllerMBean { - /** - * Mount MBeans from the source path of the source URL into the specified - * target path of the target. - * @param url URL of the mounted source. - * @param targetPath Target path in which MBeans will be mounted. - * @param optionsMap connection map and options. See {@link - * javax.management.namespace.JMXRemoteNamespace.Options - * JMXRemoteNamespace.Options} - * @throws IOException Connection with the source failed - * @throws IllegalArgumentException Supplied parameters are - * illegal, or combination of supplied parameters is illegal. - * @return A mount point id. - */ - public String mount(JMXServiceURL url, - String targetPath, - Map optionsMap) - throws IOException, IllegalArgumentException; - - /** - * Mount MBeans from the source path of the source URL into the specified - * target path of the target. - * @param url URL of the mounted source. - * @param targetPath Target path in which MBeans will be mounted. - * @param sourcePath source namespace path. - * @param optionsMap connection map and options. See {@link - * javax.management.namespace.JMXRemoteNamespace.Options - * JMXRemoteNamespace.Options} - * @throws IOException Connection with the source failed - * @throws IllegalArgumentException Supplied parameters are - * illegal, or combination of supplied parameters is illegal. - * @return A mount point id. - */ - public String mount(JMXServiceURL url, - String targetPath, - String sourcePath, - Map optionsMap) - throws IOException, IllegalArgumentException; - - /** - * Unmount a previously mounted mount point. - * @param mountPointId A mount point id, as previously returned - * by mount. - * @throws IllegalArgumentException Supplied parameters are - * illegal, or combination of supplied parameters is illegal. - * @throws IOException thrown if the mount point {@link JMXNamespace} - * couldn't be unregistered. - */ - public boolean unmount(String mountPointId) - throws IOException, IllegalArgumentException; - - /** - * Tells whether there already exists a {@link JMXNamespace} for - * the given targetPath. - * @param targetPath a target name space path. - * @return true if a {@link JMXNamespace} is registered for that - * name space path. - **/ - public boolean ismounted(String targetPath); - - /** - * Returns the handler name for the provided target name space - * path. Can throw IllegalArgumentException if the provided - * targetPath contains invalid characters (like e.g. ':'). - * @param targetPath A target name space path. - * @return the handler name for the provided target name space - * path. - **/ - public ObjectName getHandlerNameFor(String targetPath); - - /** - * Return a sorted array of locally mounted name spaces. - * This is equivalent to calling {@link - * #findNamespaces(java.lang.String,java.lang.String,int) - * findNamespaces(null,null,0)}; - * @return a sorted array of locally mounted name spaces. - **/ - public String[] findNamespaces(); - - /** - * Return a sorted array of mounted name spaces, starting at - * from (if non null), and recursively searching up to - * provided depth. - * @param from A name spaces from which to start the search. If null, - * will start searching from the MBeanServer root. - * If not null, all returned names will start with from//. - * @param regex A regular expression that the returned names must match. - * If null - no matching is performed and all found names are - * returned. If not null, then all returned names satisfy - * {@link String#matches name.matches(regex)}; - * @param depth the maximum number of levels that the search algorithm - * will cross. 0 includes only top level name spaces, 1 top level - * and first level children etc... depth is evaluated - * with regard to where the search starts - if a non null - * from parameter is provided - then {@code depth=0} - * corresponds to all name spaces found right below - * from//. - * @return A sorted array of name spaces matching the provided criteria. - * All returned names end with "//". - **/ - public String[] findNamespaces(String from, String regex, int depth); -} diff --git a/test/javax/management/namespace/NamespaceCreationTest.java b/test/javax/management/namespace/NamespaceCreationTest.java deleted file mode 100644 index 871bf0220..000000000 --- a/test/javax/management/namespace/NamespaceCreationTest.java +++ /dev/null @@ -1,263 +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. - * - * 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. - */ -/* - * - * @test NamespaceCreationTest.java - * @summary General JMXNamespace test. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean NamespaceCreationTest Wombat WombatMBean - * @run build NamespaceCreationTest Wombat WombatMBean - * @run main NamespaceCreationTest - */ - - -import java.util.Collections; -import java.util.Map; -import javax.management.MBeanRegistration; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.RuntimeMBeanException; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; - -/** - * Test simple creation/registration of namespace. - * - */ -public class NamespaceCreationTest { - private static Map emptyEnvMap() { - return Collections.emptyMap(); - } - - - public static class LocalNamespace extends JMXNamespace { - - public LocalNamespace() { - super(MBeanServerFactory.newMBeanServer()); - } - - } - - private static MBeanServer newMBeanServer() { - return MBeanServerFactory.newMBeanServer(); - } - - public static interface ThingMBean {} - public static class Thing implements ThingMBean, MBeanRegistration { - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - if (name == null) return new ObjectName(":type=Thing"); - else return name; - } - public void postRegister(Boolean registrationDone) { - } - - public void preDeregister() throws Exception { - } - public void postDeregister() { - } - } - - /** - * Test that it is possible to create a dummy MBean with a null - * ObjectName - this is just a sanity check - as there are already - * other JMX tests that check that. - * - * @throws java.lang.Exception - */ - public static void testCreateWithNull() throws Exception { - final MBeanServer server = newMBeanServer(); - final ObjectInstance oi = server.registerMBean(new Thing(),null); - server.unregisterMBean(oi.getObjectName()); - System.out.println("testCreateWithNull PASSED"); - } - - /** - * Check that we can register a JMXNamespace MBean, using its standard - * ObjectName. - * @throws java.lang.Exception - */ - public static void testGoodObjectName() throws Exception { - MBeanServer server = newMBeanServer(); - final ObjectName name = - JMXNamespaces.getNamespaceObjectName("gloups"); - final ObjectInstance oi = - server.registerMBean(new LocalNamespace(),name); - System.out.println("Succesfully registered namespace: "+name); - try { - if (! name.equals(oi.getObjectName())) - throw new RuntimeException("testGoodObjectName: TEST failed: " + - "namespace registered as: "+ - oi.getObjectName()+" expected: "+name); - } finally { - server.unregisterMBean(oi.getObjectName()); - } - System.out.println("Succesfully unregistered namespace: "+name); - System.out.println("testGoodObjectName PASSED"); - } - - /** - * Check that we cannot register a JMXNamespace MBean, if we don't use - * its standard ObjectName. - * @throws java.lang.Exception - */ - public static void testBadObjectName() throws Exception { - MBeanServer server = newMBeanServer(); - Throwable exp = null; - final ObjectName name = new ObjectName("d:k=v"); - try { - server.registerMBean(new LocalNamespace(),name); - System.out.println("testBadObjectName: " + - "Error: MBean registered, no exception thrown."); - } catch(RuntimeMBeanException x) { - exp = x.getCause(); - } catch(Exception x) { - throw new RuntimeException("testBadObjectName: TEST failed: " + - "expected RuntimeMBeanException - got "+ - x); - } - if (exp == null) server.unregisterMBean(name); - if (exp == null) - throw new RuntimeException("testBadObjectName: TEST failed: " + - "expected IllegalArgumentException - got none"); - if (!(exp instanceof IllegalArgumentException)) - throw new RuntimeException("testBadObjectName: TEST failed: " + - "expected IllegalArgumentException - got "+ - exp.toString(),exp); - System.out.println("Got expected exception: "+exp); - System.out.println("testBadObjectName PASSED"); - } - - /** - * Check that we cannot register a Wombat MBean in a namespace that does - * not exists. - * - * @throws java.lang.Exception - */ - public static void testBadNamespace() throws Exception { - MBeanServer server = newMBeanServer(); - Throwable exp = null; - final ObjectName name = new ObjectName("glips//d:k=v"); - - try { - server.registerMBean(new Wombat(),name); - System.out.println("testBadNamespace: " + - "Error: MBean registered, no exception thrown."); - } catch(MBeanRegistrationException x) { - exp = x.getCause(); - } catch(Exception x) { - throw new RuntimeException("testBadNamespace: TEST failed: " + - "expected MBeanRegistrationException - got "+ - x); - } - if (exp == null) server.unregisterMBean(name); - if (exp == null) - throw new RuntimeException("testBadNamespace: TEST failed: " + - "expected IllegalArgumentException - got none"); - if (!(exp instanceof IllegalArgumentException)) - throw new RuntimeException("testBadNamespace: TEST failed: " + - "expected IllegalArgumentException - got "+ - exp.toString(),exp); - System.out.println("Got expected exception: "+exp); - System.out.println("testBadNamespace PASSED"); - } - - /** - * Check that we cannot register a Wombat MBean with a domain name - * that ends with //. This is reserved for namespaces. - * - * @throws java.lang.Exception - */ - public static void testBadDomain() throws Exception { - MBeanServer server = newMBeanServer(); - Throwable exp = null; - final ObjectName name = new ObjectName("glups//:k=v"); - - try { - server.registerMBean(new Wombat(),name); - System.out.println("testBadDomain: Error: MBean registered, no exception thrown."); - } catch(RuntimeMBeanException x) { - exp = x.getCause(); - } catch(Exception x) { - throw new RuntimeException("testBadDomain: TEST failed: " + - "expected RuntimeMBeanException - got "+ - x); - } - if (exp == null) server.unregisterMBean(name); - if (exp == null) - throw new RuntimeException("testBadDomain: TEST failed: " + - "expected IllegalArgumentException - got none"); - if (!(exp instanceof IllegalArgumentException)) - throw new RuntimeException("testBadDomain: TEST failed: " + - "expected IllegalArgumentException - got "+ - exp.toString(),exp); - System.out.println("Got expected exception: "+exp); - System.out.println("testBadDomain PASSED"); - } - - /** - * Check that we cannot register a Wombat MBean as if it were a - * JMXNamespace. Only JMXNamespace MBeans can have JMX Namespace names. - * @throws java.lang.Exception - */ - public static void testBadClassName() throws Exception { - MBeanServer server = newMBeanServer(); - Throwable exp = null; - final ObjectName name = - JMXNamespaces.getNamespaceObjectName("glops"); - try { - server.registerMBean(new Wombat(),name); - System.out.println("testBadClassName: " + - "Error: MBean registered, no exception thrown."); - } catch(RuntimeMBeanException x) { - exp = x.getCause(); - } catch(Exception x) { - throw new RuntimeException("testBadClassName: TEST failed: " + - "expected RuntimeMBeanException - got "+ - x); - } - if (exp == null) server.unregisterMBean(name); - if (exp == null) - throw new RuntimeException("testBadClassName: TEST failed: " + - "expected IllegalArgumentException - got none"); - if (!(exp instanceof IllegalArgumentException)) - throw new RuntimeException("testBadClassName: TEST failed: " + - "expected IllegalArgumentException - got "+ - exp.toString(),exp); - System.out.println("Got expected exception: "+exp); - System.out.println("testBadClassName PASSED"); - } - - public static void main(String... args) throws Exception { - testCreateWithNull(); - testGoodObjectName(); - testBadObjectName(); - testBadNamespace(); - testBadDomain(); - testBadClassName(); - } -} diff --git a/test/javax/management/namespace/NamespaceNotificationsTest.java b/test/javax/management/namespace/NamespaceNotificationsTest.java deleted file mode 100644 index 0545a36b2..000000000 --- a/test/javax/management/namespace/NamespaceNotificationsTest.java +++ /dev/null @@ -1,381 +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. - * - * 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. - */ - -/* - * - * @test NamespaceNotificationsTest.java 1.12 - * @summary General Namespace & Notifications test. - * @bug 5072476 - * @author Daniel Fuchs - * @run clean NamespaceNotificationsTest - * Wombat WombatMBean JMXRemoteTargetNamespace - * NamespaceController NamespaceControllerMBean - * @compile -XDignore.symbol.file=true NamespaceNotificationsTest.java - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java - * NamespaceController.java NamespaceControllerMBean.java - * @run main NamespaceNotificationsTest - */ -import com.sun.jmx.remote.util.EventClientConnection; -import java.lang.management.ManagementFactory; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; -import javax.management.MBeanServerNotification; -import javax.management.MalformedObjectNameException; -import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.loading.MLet; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.remote.JMXAddressable; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * - * @author Sun Microsystems, Inc. - */ -public class NamespaceNotificationsTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(NamespaceNotificationsTest.class.getName()); - - /** Creates a new instance of NamespaceNotificationsTest */ - public NamespaceNotificationsTest() { - } - - - public static JMXServiceURL export(MBeanServer server) - throws Exception { - final JMXServiceURL in = new JMXServiceURL("rmi",null,0); - final JMXConnectorServer cs = - JMXConnectorServerFactory.newJMXConnectorServer(in,null,null); - final ObjectName csname = ObjectName. - getInstance(cs.getClass().getPackage().getName()+ - ":type="+cs.getClass().getSimpleName()); - server.registerMBean(cs,csname); - cs.start(); - return cs.getAddress(); - } - - public static class Counter { - int count; - public synchronized int count() { - count++; - notifyAll(); - return count; - } - public synchronized int peek() { - return count; - } - public synchronized int waitfor(int max, long timeout) - throws InterruptedException { - final long start = System.currentTimeMillis(); - while (count < max && timeout > 0) { - final long rest = timeout - - (System.currentTimeMillis() - start); - if (rest <= 0) break; - wait(rest); - } - return count; - } - } - - public static class CounterListener - implements NotificationListener { - final private Counter counter; - public CounterListener(Counter counter) { - this.counter = counter; - } - public void handleNotification(Notification notification, - Object handback) { - System.out.println("Received notif from " + handback + - ":\n\t" + notification); - if (!notification.getSource().equals(handback)) { - System.err.println("OhOh... Unexpected source: \n\t"+ - notification.getSource()+"\n\twas expecting:\n\t"+ - handback); - } - counter.count(); - } - } - - public static void simpleTest(String[] args) { - try { - final MBeanServer server1 = - ManagementFactory.getPlatformMBeanServer(); - final JMXServiceURL url1 = export(server1); - - final MBeanServer server2 = - MBeanServerFactory.createMBeanServer("server2"); - final JMXServiceURL url2 = export(server2); - - final MBeanServer server3 = - MBeanServerFactory.createMBeanServer("server3"); - final JMXServiceURL url3 = export(server3); - - final ObjectInstance ncinst = - NamespaceController.createInstance(server1); - - final NamespaceControllerMBean nc = - JMX.newMBeanProxy(server1,ncinst.getObjectName(), - NamespaceControllerMBean.class); - - final Map options = new HashMap(); - options.put(JMXRemoteTargetNamespace.CREATE_EVENT_CLIENT,"true"); - - final String mount1 = - nc.mount(url1,"server1",options); - final String mount2 = nc.mount(url2,"server1//server2", - options); - final String mount3 = nc.mount(url3, - "server1//server2//server3", - options); - final String mount13 = nc.mount( - url1, - "server3", - "server2//server3", - options); - final String mount21 = nc.mount(url1,"server2//server1", - options); - final String mount31 = nc.mount( - url1, - "server3//server1", - "server1", - options); - final String mount32 = nc.mount( - url1, - "server3//server2", - "server2", - options); - - - final ObjectName deep = - new ObjectName("server1//server2//server3//bush:type=Wombat,name=kanga"); - server1.createMBean(Wombat.class.getName(),deep); - - System.err.println("There's a wombat in the bush!"); - - final Counter counter = new Counter(); - - final NotificationListener listener = - new CounterListener(counter); - - final JMXConnector jc = JMXConnectorFactory.connect(url1); - final MBeanServerConnection aconn = - EventClientConnection.getEventConnectionFor( - jc.getMBeanServerConnection(),null); - aconn.addNotificationListener(deep,listener,null,deep); - - - MBeanServerConnection iconn = - JMXNamespaces.narrowToNamespace(aconn, "server1//server1"); - MBeanServerConnection bconn = - JMXNamespaces.narrowToNamespace(aconn, "server3"); - final ObjectName shallow = - new ObjectName("bush:"+ - deep.getKeyPropertyListString()); - final WombatMBean proxy = - JMX.newMBeanProxy(EventClientConnection.getEventConnectionFor( - bconn,null),shallow,WombatMBean.class,true); - - ((NotificationEmitter)proxy). - addNotificationListener(listener,null,shallow); - proxy.setCaption("I am a new Wombat!"); - System.err.println("New caption: "+proxy.getCaption()); - final int rcvcount = counter.waitfor(2,3000); - if (rcvcount != 2) - throw new RuntimeException("simpleTest failed: "+ - "received count is " +rcvcount); - - System.err.println("simpleTest passed: got "+rcvcount+ - " notifs"); - - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new RuntimeException("simpleTest failed: " + x,x); - } - } - - public static class LocalNamespace extends - JMXNamespace { - LocalNamespace() { - super(MBeanServerFactory.newMBeanServer()); - } - - } - - public static class ContextObject { - public final K name; - public final V object; - public ContextObject(K name, V object) { - this.name = name; - this.object = object; - } - private Object[] data() { - return new Object[] {name,object}; - } - - @Override - public boolean equals(Object x) { - if (x instanceof ContextObject) - return Arrays.deepEquals(data(),((ContextObject)x).data()); - return false; - } - @Override - public int hashCode() { - return Arrays.deepHashCode(data()); - } - } - - private static ContextObject context(K k, V v) { - return new ContextObject(k,v); - } - - private static ObjectName name(String name) { - try { - return new ObjectName(name); - } catch(MalformedObjectNameException x) { - throw new IllegalArgumentException(name,x); - } - } - - public static void simpleTest2() { - try { - System.out.println("\nsimpleTest2: STARTING\n"); - final LocalNamespace foo = new LocalNamespace(); - final LocalNamespace joe = new LocalNamespace(); - final LocalNamespace bar = new LocalNamespace(); - final MBeanServer server = MBeanServerFactory.newMBeanServer(); - - server.registerMBean(foo,JMXNamespaces.getNamespaceObjectName("foo")); - server.registerMBean(joe,JMXNamespaces.getNamespaceObjectName("foo//joe")); - server.registerMBean(bar,JMXNamespaces.getNamespaceObjectName("foo//bar")); - final BlockingQueue> queue = - new ArrayBlockingQueue>(20); - - final NotificationListener listener = new NotificationListener() { - public void handleNotification(Notification n, Object handback) { - if (!(n instanceof MBeanServerNotification)) { - System.err.println("Error: expected MBeanServerNotification"); - return; - } - final MBeanServerNotification mbsn = - (MBeanServerNotification) n; - - // We will pass the namespace name in the handback. - // - final String namespace = (String) handback; - System.out.println("Received " + mbsn.getType() + - " for MBean " + mbsn.getMBeanName() + - " from name space " + namespace); - try { - queue.offer(context(namespace,mbsn),500,TimeUnit.MILLISECONDS); - } catch (Exception x) { - System.err.println("Failed to enqueue received notif: "+mbsn); - x.printStackTrace(); - } - } - }; - - server.addNotificationListener(JMXNamespaces.insertPath("foo//joe", - MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//joe"); - server.addNotificationListener(JMXNamespaces.insertPath("foo//bar", - MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//bar"); - server.createMBean(MLet.class.getName(), - name("foo//joe//domain:type=MLet")); - checkQueue(queue,"foo//joe", - MBeanServerNotification.REGISTRATION_NOTIFICATION); - server.createMBean(MLet.class.getName(), - name("foo//bar//domain:type=MLet")); - checkQueue(queue,"foo//bar", - MBeanServerNotification.REGISTRATION_NOTIFICATION); - server.unregisterMBean( - name("foo//joe//domain:type=MLet")); - checkQueue(queue,"foo//joe", - MBeanServerNotification.UNREGISTRATION_NOTIFICATION); - server.unregisterMBean( - name("foo//bar//domain:type=MLet")); - checkQueue(queue,"foo//bar", - MBeanServerNotification.UNREGISTRATION_NOTIFICATION); - } catch (RuntimeException x) { - System.err.println("FAILED: "+x); - throw x; - } catch(Exception x) { - System.err.println("FAILED: "+x); - throw new RuntimeException("Unexpected exception: "+x,x); - } - } - - - private static void checkQueue( - BlockingQueue> q, - String path, String type) { - try { - final ContextObject ctxt = - q.poll(500,TimeUnit.MILLISECONDS); - if (ctxt == null) - throw new RuntimeException("Timeout expired: expected notif from "+ - path +", type="+type); - if (!ctxt.name.equals(path)) - throw new RuntimeException("expected notif from "+ - path +", got "+ctxt.name); - if (!ctxt.object.getType().equals(type)) - throw new RuntimeException(ctxt.name+": expected type="+ - type +", got "+ctxt.object.getType()); - if (!ctxt.object.getType().equals(type)) - throw new RuntimeException(ctxt.name+": expected type="+ - type +", got "+ctxt.object.getType()); - if (!ctxt.object.getMBeanName().equals(name("domain:type=MLet"))) - throw new RuntimeException(ctxt.name+": expected MBean=domain:type=MLet"+ - ", got "+ctxt.object.getMBeanName()); - } catch(InterruptedException x) { - throw new RuntimeException("unexpected interruption: "+x,x); - } - } - - public static void main(String[] args) { - simpleTest(args); - simpleTest2(); - } - -} diff --git a/test/javax/management/namespace/NullDomainObjectNameTest.java b/test/javax/management/namespace/NullDomainObjectNameTest.java deleted file mode 100644 index fa8455e2a..000000000 --- a/test/javax/management/namespace/NullDomainObjectNameTest.java +++ /dev/null @@ -1,307 +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. - * - * 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. - */ -/* - * @test NullDomainObjectNameTest.java - * @summary Test that null domains are correctly handled in namespaces. - * @author Daniel Fuchs - * @run clean NullDomainObjectNameTest Wombat WombatMBean - * @compile -XDignore.symbol.file=true NullDomainObjectNameTest.java - * @run build NullDomainObjectNameTest Wombat WombatMBean - * @run main NullDomainObjectNameTest - */ - -import com.sun.jmx.namespace.RoutingServerProxy; -import java.lang.management.ManagementFactory; -import java.util.Arrays; -import java.util.logging.Logger; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.namespace.JMXNamespace; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * Class NullDomainObjectNameTest - * @author Sun Microsystems, 2005 - All rights reserved. - */ -public class NullDomainObjectNameTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(NullDomainObjectNameTest.class.getName()); - - /** Creates a new instance of NullDomainObjectNameTest */ - public NullDomainObjectNameTest() { - } - - public static class MyWombat - extends Wombat { - public MyWombat() throws NotCompliantMBeanException { - super(); - } - @Override - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - - if (name == null) - name = new ObjectName(":type=Wombat"); - - return super.preRegister(server, name); - } - - } - - static String failure=null; - - public static void testRegister() throws Exception { - final MBeanServer top = ManagementFactory.getPlatformMBeanServer(); - final MBeanServer sub = MBeanServerFactory.createMBeanServer(); - final JMXServiceURL url = new JMXServiceURL("rmi",null,0); - final JMXConnectorServer srv = - JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub); - srv.start(); - - try { - - // Create a namespace rmi// that points to 'sub' and flows through - // a JMXRemoteNamespace connected to 'srv' - // The namespace rmi// will accept createMBean, but not registerMBean. - // - final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace. - newJMXRemoteNamespace(srv.getAddress(), - null); - top.registerMBean(rmiHandler,JMXNamespaces.getNamespaceObjectName("rmi")); - top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"), - "connect", null, null); - - // Create a namespace direct// that points to 'sub' and flows - // through a direct reference to 'sub'. - // The namespace direct// will accept createMBean, and registerMBean. - // - final JMXNamespace directHandler = new JMXNamespace(sub); - top.registerMBean(directHandler, - JMXNamespaces.getNamespaceObjectName("direct")); - - // Now cd to each of the created namespace. - // - MBeanServer cdrmi = JMXNamespaces.narrowToNamespace(top,"rmi"); - MBeanServer cddirect = JMXNamespaces.narrowToNamespace(top,"direct"); - boolean ok = false; - - // Check that calling createMBean with a null domain works - // for namespace rmi// - // - try { - final ObjectInstance moi1 = - cdrmi.createMBean(MyWombat.class.getName(), - new ObjectName(":type=Wombat")); - System.out.println(moi1.getObjectName().toString()+ - ": created through rmi//"); - assertEquals(moi1.getObjectName().getDomain(), - cddirect.getDefaultDomain()); - cddirect.unregisterMBean(moi1.getObjectName()); - } catch (MBeanRegistrationException x) { - System.out.println("Received unexpected exception: " + x); - failed("Received unexpected exception: " + x); - } - - // Check that calling refgisterMBean with a null domain works - // for namespace direct// - // - try { - final ObjectInstance moi2 = - cddirect.registerMBean(new MyWombat(), - new ObjectName(":type=Wombat")); - System.out.println(moi2.getObjectName().toString()+ - ": created through direct//"); - assertEquals(moi2.getObjectName().getDomain(), - cdrmi.getDefaultDomain()); - cdrmi.unregisterMBean(moi2.getObjectName()); - } catch (MBeanRegistrationException x) { - System.out.println("Received unexpected exception: " + x); - failed("Received unexpected exception: " + x); - } - - // Now artificially pretend that 'sub' is contained in a faked// - // namespace. - // - RoutingServerProxy proxy = - new RoutingServerProxy(sub, "", "faked", true); - - // These should fail because the ObjectName doesn't start - // with "faked//" - try { - final ObjectInstance moi3 = - proxy.registerMBean(new MyWombat(), - new ObjectName(":type=Wombat")); - System.out.println(moi3.getObjectName().toString()+ - ": created through faked//"); - failed("expected MBeanRegistrationException"); - } catch (MBeanRegistrationException x) { - System.out.println("Received expected exception: " + x); - if (!(x.getCause() instanceof IllegalArgumentException)) { - System.err.println("Bad wrapped exception: "+ x.getCause()); - failed("expected IllegalArgumentException"); - } - } - - // null should work with "faked//" - final ObjectInstance moi3 = - proxy.registerMBean(new MyWombat(),null); - assertEquals(moi3.getObjectName().getDomain(), - "faked//"+sub.getDefaultDomain()); - - System.out.println(moi3.getObjectName().toString() + - ": created through faked//"); - - // Now check that null is correctly handled (accepted or rejected) - // in queries for each of the above configs. - // - ObjectName wombat = moi3.getObjectName().withDomain( - moi3.getObjectName().getDomain().substring("faked//".length())); - ObjectInstance moi = new ObjectInstance(wombat,moi3.getClassName()); - - System.out.println("Checking queryNames(" + - "new ObjectName(\":*\"),null) with rmi//"); - assertEquals(cdrmi.queryNames( - new ObjectName(":*"),null).contains(wombat),true); - System.out.println("Checking queryNames(" + - "new ObjectName(\":*\"),null) with direct//"); - assertEquals(cddirect.queryNames( - new ObjectName(":*"),null).contains(wombat),true); - System.out.println("Checking queryMBeans(" + - "new ObjectName(\":*\"),null) with rmi//"); - assertEquals(cdrmi.queryMBeans( - new ObjectName(":*"),null).contains(moi),true); - System.out.println("Checking queryMBeans(" + - "new ObjectName(\":*\"),null) with direct//"); - assertEquals(cddirect.queryMBeans( - new ObjectName(":*"),null).contains(moi),true); - - // These should fail because the ObjectName doesn't start - // with "faked//" - try { - System.out.println("Checking queryNames(" + - "new ObjectName(\":*\"),null) with faked//"); - assertEquals(proxy.queryNames( - new ObjectName(":*"),null). - contains(moi3.getObjectName()),true); - failed("queryNames(new ObjectName(\":*\"),null) " + - "should have failed for faked//"); - } catch (RuntimeOperationsException x) { - if (x.getCause() instanceof IllegalArgumentException) - System.out.println( - "Received expected exception for faked//: "+x); - else { - System.err.println( - "Expected exception has unexpected cause " + - "for faked//: "+x.getCause()); - x.printStackTrace(); - failed("queryNames(new ObjectName(\":*\"),null)" + - " failed with unexpected cause for faked//"); - } - } - // These should fail because the ObjectName doesn't start - // with "faked//" - try { - System.out.println("Checking queryMBeans(" + - "new ObjectName(\":*\"),null) with faked//"); - assertEquals(proxy.queryMBeans( - new ObjectName(":*"),null).contains(moi3),true); - failed("queryMBeans(new ObjectName(\":*\"),null)" + - " should have failed for faked//"); - } catch (RuntimeOperationsException x) { - if (x.getCause() instanceof IllegalArgumentException) - System.out.println( - "Received expected exception for faked//: "+x); - else { - System.err.println( - "Expected exception has unexpected cause " + - "for faked//: "+x.getCause()); - x.printStackTrace(); - failed("queryMBeans(new ObjectName(\":*\"),null) " + - "failed with unexpected cause for faked//"); - } - } - - System.out.println("Checking queryNames(faked//*:*,null)"); - assertEquals(proxy.queryNames(new ObjectName("faked//*:*"),null). - contains(moi3.getObjectName()),true); - - System.out.println("Checking queryMBeans(faked//*:*,null)"); - assertEquals(proxy.queryMBeans(new ObjectName("faked//*:*"),null). - contains(moi3),true); - - proxy.unregisterMBean(moi3.getObjectName()); - - // ADD NEW TESTS HERE ^^^ - - } finally { - srv.stop(); - } - - if (failure != null) - throw new Exception(failure); - - - } - private static void assertEquals(Object x, Object y) { - if (!equal(x, y)) - failed("expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } - - public static void main(String[] args) throws Exception { - testRegister(); - } -} diff --git a/test/javax/management/namespace/NullObjectNameTest.java b/test/javax/management/namespace/NullObjectNameTest.java deleted file mode 100644 index 5cf99a230..000000000 --- a/test/javax/management/namespace/NullObjectNameTest.java +++ /dev/null @@ -1,273 +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. - * - * 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. - */ -/* - * @test NullObjectNameTest.java - * @summary Test that null ObjectName are correctly handled in namespaces. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean NullObjectNameTest Wombat WombatMBean - * @compile -XDignore.symbol.file=true NullObjectNameTest.java - * @run build NullObjectNameTest Wombat WombatMBean - * @run main NullObjectNameTest - */ - -import com.sun.jmx.namespace.RoutingServerProxy; -import java.lang.management.ManagementFactory; -import java.util.Arrays; -import java.util.logging.Logger; -import javax.management.MBeanRegistrationException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.JMXRemoteNamespace; -import javax.management.namespace.JMXNamespace; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -/** - * Class NullObjectNameTest - * @author Sun Microsystems, 2005 - All rights reserved. - */ -public class NullObjectNameTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(NullObjectNameTest.class.getName()); - - /** Creates a new instance of NullObjectNameTest */ - public NullObjectNameTest() { - } - - public static class MyWombat - extends Wombat { - public MyWombat() throws NotCompliantMBeanException { - super(); - } - @Override - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - - if (name == null) - name = new ObjectName(":type=Wombat"); - - return super.preRegister(server, name); - } - - } - - static String failure=null; - - public static void testRegister() throws Exception { - final MBeanServer top = ManagementFactory.getPlatformMBeanServer(); - final MBeanServer sub = MBeanServerFactory.createMBeanServer(); - final JMXServiceURL url = new JMXServiceURL("rmi",null,0); - final JMXConnectorServer srv = - JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub); - srv.start(); - - try { - - // Create a namespace rmi// that points to 'sub' and flows through - // a JMXRemoteNamespace connected to 'srv' - // The namespace rmi// will accept createMBean, but not registerMBean. - // - final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace. - newJMXRemoteNamespace(srv.getAddress(),null); - top.registerMBean(rmiHandler,JMXNamespaces.getNamespaceObjectName("rmi")); - top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"), - "connect", null, null); - - // Create a namespace direct// that points to 'sub' and flows - // through a direct reference to 'sub'. - // The namespace direct// will accept createMBean, and registerMBean. - // - final JMXNamespace directHandler = new JMXNamespace(sub); - top.registerMBean(directHandler, - JMXNamespaces.getNamespaceObjectName("direct")); - - // Now cd to each of the created namespace. - // - MBeanServer cdrmi = JMXNamespaces.narrowToNamespace(top,"rmi"); - MBeanServer cddirect = JMXNamespaces.narrowToNamespace(top,"direct"); - boolean ok = false; - - // Check that calling createMBean with a null ObjectName fails - // gracefully for namespace rmi// (we can't add rmi// to a null - // ObjectName. - // - // TODO: do this test for all createMBean flavors! - try { - final ObjectInstance moi1 = - cdrmi.createMBean(MyWombat.class.getName(),null); - System.out.println(moi1.getObjectName().toString()+ - ": created through rmi//"); - cddirect.unregisterMBean(moi1.getObjectName()); - failed("expected MBeanRegistrationException"); - } catch (MBeanRegistrationException x) { - System.out.println("Received expected exception: " + x); - if (!(x.getCause() instanceof IllegalArgumentException)) { - System.err.println("Bad wrapped exception: "+ x.getCause()); - failed("expected IllegalArgumentException"); - } - } - - // Check that calling refgisterMBean with a null ObjectName fails - // gracefully for namespace direct// (we can't add direct// to a null - // ObjectName. - // - try { - final ObjectInstance moi2 = - cddirect.registerMBean(new MyWombat(), (ObjectName)null); - System.out.println(moi2.getObjectName().toString()+ - ": created through direct//"); - cdrmi.unregisterMBean(moi2.getObjectName()); - failed("expected MBeanRegistrationException"); - } catch (MBeanRegistrationException x) { - System.out.println("Received expected exception: " + x); - if (!(x.getCause() instanceof IllegalArgumentException)) { - System.err.println("Bad wrapped exception: "+ x.getCause()); - failed("expected IllegalArgumentException"); - } - } - - // Now artificially pretend that 'sub' is contained in a faked// - // namespace. - // We should be able to use 'null' in registerMBean/createMBean in - // this case. - // - RoutingServerProxy proxy = - new RoutingServerProxy(sub, "", "faked", true); - final ObjectInstance moi3 = - proxy.registerMBean(new MyWombat(),null); - System.out.println(moi3.getObjectName().toString()+ - ": created through faked//"); - - // Now check that null is correctly handled (accepted or rejected) - // in queries for each of the above configs. - // - ObjectName wombat = moi3.getObjectName().withDomain( - moi3.getObjectName().getDomain().substring("faked//".length())); - ObjectInstance moi = new ObjectInstance(wombat,moi3.getClassName()); - - System.out.println("Checking queryNames(null,null) with rmi//"); - assertEquals(cdrmi.queryNames(null,null).contains(wombat),true); - System.out.println("Checking queryNames(null,null) with direct//"); - assertEquals(cddirect.queryNames(null,null).contains(wombat),true); - System.out.println("Checking queryMBeans(null,null) with rmi//"); - assertEquals(cdrmi.queryMBeans(null,null).contains(moi),true); - System.out.println("Checking queryMBeans(null,null) with direct//"); - assertEquals(cddirect.queryMBeans(null,null).contains(moi),true); - - try { - System.out.println("Checking queryNames(null,null) with faked//"); - assertEquals(proxy.queryNames(null,null). - contains(moi3.getObjectName()),true); - failed("queryNames(null,null) should have failed for faked//"); - } catch (RuntimeOperationsException x) { - if (x.getCause() instanceof IllegalArgumentException) - System.out.println( - "Received expected exception for faked//: "+x); - else { - System.err.println( - "Expected exception has unexpected cause " + - "for faked//: "+x.getCause()); - x.printStackTrace(); - failed("queryNames(null,null) failed with unexpected " + - "cause for faked//"); - } - } - try { - System.out.println("Checking queryMBeans(null,null) with faked//"); - assertEquals(proxy.queryMBeans(null,null).contains(moi3),true); - failed("queryMBeans(null,null) should have failed for faked//"); - } catch (RuntimeOperationsException x) { - if (x.getCause() instanceof IllegalArgumentException) - System.out.println( - "Received expected exception for faked//: "+x); - else { - System.err.println( - "Expected exception has unexpected cause " + - "for faked//: "+x.getCause()); - x.printStackTrace(); - failed("queryMBeans(null,null) failed with unexpected " + - "cause for faked//"); - } - } - System.out.println("Checking queryNames(faked//*:*,null)"); - assertEquals(proxy.queryNames(new ObjectName("faked//*:*"),null). - contains(moi3.getObjectName()),true); - - System.out.println("Checking queryMBeans(faked//*:*,null)"); - assertEquals(proxy.queryMBeans(new ObjectName("faked//*:*"),null). - contains(moi3),true); - - proxy.unregisterMBean(moi3.getObjectName()); - - // ADD NEW TESTS HERE ^^^ - - } finally { - srv.stop(); - } - - if (failure != null) - throw new Exception(failure); - - - } - private static void assertEquals(Object x, Object y) { - if (!equal(x, y)) - failed("expected " + string(x) + "; got " + string(y)); - } - - private static boolean equal(Object x, Object y) { - if (x == y) - return true; - if (x == null || y == null) - return false; - if (x.getClass().isArray()) - return Arrays.deepEquals(new Object[] {x}, new Object[] {y}); - return x.equals(y); - } - - private static String string(Object x) { - String s = Arrays.deepToString(new Object[] {x}); - return s.substring(1, s.length() - 1); - } - - - private static void failed(String why) { - failure = why; - new Throwable("FAILED: " + why).printStackTrace(System.out); - } - - public static void main(String[] args) throws Exception { - testRegister(); - } -} diff --git a/test/javax/management/namespace/QueryNamesTest.java b/test/javax/management/namespace/QueryNamesTest.java deleted file mode 100644 index 5b5076446..000000000 --- a/test/javax/management/namespace/QueryNamesTest.java +++ /dev/null @@ -1,473 +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. - * - * 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. - */ -/* - * - * @test QueryNamesTest.java 1.4 - * @summary Test how queryNames works with Namespaces. - * @author Daniel Fuchs - * @bug 5072476 6768935 - * @run clean QueryNamesTest Wombat WombatMBean - * @run build QueryNamesTest Wombat WombatMBean - * @run main QueryNamesTest - */ - - -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.logging.Logger; -import javax.management.InstanceNotFoundException; -import javax.management.JMException; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; - -/** - * Class QueryNamesTest - * @author Sun Microsystems, 2005 - All rights reserved. - */ -public class QueryNamesTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(QueryNamesTest.class.getName()); - - public static class LocalNamespace - extends JMXNamespace { - - private static MBeanServer check(MBeanServer server) { - if (server == null) - throw new IllegalArgumentException("MBeanServer can't be null"); - return server; - } - - public LocalNamespace() { - this(MBeanServerFactory.createMBeanServer()); - } - - public LocalNamespace(MBeanServer server) { - super(check(server)); - } - - - public static String add(MBeanServerConnection server, - String nspath) - throws IOException, JMException { - server.createMBean(LocalNamespace.class.getName(), - JMXNamespaces.getNamespaceObjectName(nspath)); - return nspath; - } - } - - /** Creates a new instance of QueryNamesTest */ - public QueryNamesTest() { - } - - private static String[] namespaces = { - "greg", "greg//chichille", "greg//chichille//petard", - "greg//alambic", "greg//alambic//canette", - "greg//chichille/virgule", "greg//chichille/funeste", - "greg//chichille/virgule//bidouble", - "greg//chichille/virgule//bi/double", - "fran", "fran//gast", "fran//gast//gaf", - "fran//longtar", "fran//longtar//parcmetre" - }; - - private static void createNamespaces(MBeanServer server) throws Exception { - final LinkedList all = new LinkedList(); - try { - for (String ns : namespaces) - all.addFirst(LocalNamespace.add(server,ns)); - } catch (Exception e) { - removeNamespaces(server,all.toArray(new String[all.size()])); - throw e; - } - } - - // Dummy test that checks that all JMXNamespaces are registered, - // but are not returned by queryNames("*:*"); - // - private static void checkRegistration(MBeanServer server) - throws Exception { - final Set handlerNames = new HashSet(namespaces.length); - for (String ns : namespaces) - handlerNames.add(JMXNamespaces.getNamespaceObjectName(ns)); - for (ObjectName nh : handlerNames) // check handler registration - if (!server.isRegistered(nh)) - throw new InstanceNotFoundException("handler "+nh+ - " is not registered"); - - // global: queryNames("*:*") from top level - final Set all1 = server.queryNames(null,null); - final Set all2 = server.queryNames(ObjectName.WILDCARD,null); - if (!all1.equals(all2)) - throw new Exception("queryNames(*:*) != queryNames(null)"); - final Set common = new HashSet(all1); - common.retainAll(handlerNames); - - final Set ref = new HashSet(); - for (String ns : namespaces) { - if (!ns.contains(JMXNamespaces.NAMESPACE_SEPARATOR)) - ref.add(JMXNamespaces.getNamespaceObjectName(ns)); - } - if (!common.equals(ref)) { - throw new Exception("some handler names were not returned by " + - "wildcard query - only returned: "+common+ - ", expected: "+ref); - } - - // for each namespace: queryNames("//*:*"); - for (String ns : namespaces) { - final ObjectName pattern = new ObjectName(ns+ - JMXNamespaces.NAMESPACE_SEPARATOR+"*:*"); - final Set all4 = - server.queryNames(pattern,null); - final Set common4 = new HashSet(all4); - common4.retainAll(handlerNames); - - final Set ref4 = new HashSet(); - for (String ns2 : namespaces) { - if (! ns2.startsWith(ns+JMXNamespaces.NAMESPACE_SEPARATOR)) - continue; - if (!ns2.substring(ns.length()+ - JMXNamespaces.NAMESPACE_SEPARATOR.length()). - contains(JMXNamespaces.NAMESPACE_SEPARATOR)) - ref4.add(JMXNamespaces.getNamespaceObjectName(ns2)); - } - if (!common4.equals(ref4)) { - throw new Exception("some handler names were not returned by " + - "wildcard query on "+pattern+" - only returned: "+common4+ - ", expected: "+ref4); - } - } - } - - // Make a Map - private static Map> makeNsTree(String[] nslist) { - final Map> nsTree = - new LinkedHashMap>(nslist.length); - for (String ns : nslist) { - if (nsTree.get(ns) == null) - nsTree.put(ns,new LinkedHashSet()); - final String[] elts = ns.split(JMXNamespaces.NAMESPACE_SEPARATOR); - int last = ns.lastIndexOf(JMXNamespaces.NAMESPACE_SEPARATOR); - if (last<0) continue; - while (last > 0 && ns.charAt(last-1) == '/') last--; - final String parent = ns.substring(0,last); - if (nsTree.get(parent) == null) - nsTree.put(parent,new LinkedHashSet()); - nsTree.get(parent).add(ns); - } - return nsTree; - } - - private static class Rigolo { - final static String[] ones = { "a", "e", "i", "o", "u", "y", "ai", "oo", - "ae", "ey", "ay", "oy", "au", "ou", "eu", "oi", "ei", "ea"}; - final static String[] twos = { "b", "bz", "c", "cz", "ch", - "ct", "ck", "cs", "d", "ds", "f", "g", "gh", "h", "j", "k", "l", "m", - "n", "p", "ps", "q", "r", "s", "sh", "t", "v", "w", "x", - "z"}; - final static String[] threes = {"rr","tt","pp","ss","dd","ff","ll", "mm", "nn", - "zz", "cc", "bb"}; - final static String[] fours = {"x", "s", "ght", "cks", "rt", "rts", "ghts", "bs", - "ts", "gg" }; - final static String[] fives = { "br", "bl", "cr", "cn", "cth", "dr", - "fr", "fl", "cl", "chr", "gr", "gl", "kr", "kh", "pr", "pl", "ph", - "rh", "sr", "tr", "vr"}; - - private Random rg = new Random(); - - private String next(String[] table) { - return table[rg.nextInt(table.length)]; - } - - public String nextName(int max) { - final Random rg = new Random(); - final int nl = 3 + rg.nextInt(max); - boolean begin = rg.nextBoolean(); - StringBuilder sb = new StringBuilder(); - for (int j = 0; j < nl ; j++) { - if (begin) { - sb.append(next(ones)); - } else if (j > 0 && j < nl-1 && rg.nextInt(4)==0) { - sb.append(next(threes)); - } else if (j < nl-1 && rg.nextInt(3)==0) { - sb.append(next(fives)); - } else { - sb.append(next(twos)); - } - begin = !begin; - } - if (!begin && rg.nextInt(2)==0) - sb.append(next(fours)); - return sb.toString(); - } - - private ObjectName getWombatName(String ns, String domain, String name) - throws MalformedObjectNameException { - String d = domain; - if (ns != null && !ns.equals("")) - d = ns + JMXNamespaces.NAMESPACE_SEPARATOR + domain; - return new ObjectName(d+":type=Wombat,name="+name); - } - - public Set nextWombats(String ns) - throws MalformedObjectNameException { - final int dcount = 1 + rg.nextInt(5); - final Set wombats = new HashSet(); - for (int i = 0; i < dcount ; i++) { - final String d = nextName(7); - final int ncount = 5 + rg.nextInt(20); - for (int j = 0 ; j> nsTree = makeNsTree(namespaces); - final Random rg = new Random(); - final Rigolo rigolo = new Rigolo(); - for (String ns : namespaces) { - final ObjectName name = JMXNamespaces.getNamespaceObjectName(ns); - final String[] doms = - (String[])server.getAttribute(name,"Domains"); - final Set subs = new HashSet(); - for (String d : doms) { - if (d.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) { - subs.add(ns+JMXNamespaces.NAMESPACE_SEPARATOR+d.substring(0, - d.length()-JMXNamespaces.NAMESPACE_SEPARATOR.length())); - } - } - - final Set expectNs = new HashSet(nsTree.get(ns)); - - if (! subs.containsAll(expectNs)) - throw new Exception("getDomains didn't return all namespaces: "+ - "returned="+subs+", expected="+expectNs); - if (! expectNs.containsAll(subs)) - throw new Exception("getDomains returned additional namespaces: "+ - "returned="+subs+", expected="+expectNs); - - final Set nsNames = server.queryNames( - new ObjectName(ns+ - JMXNamespaces.NAMESPACE_SEPARATOR+"*"+ - JMXNamespaces.NAMESPACE_SEPARATOR+":*"),null); - - final Set expect = - new HashSet(expectNs.size()); - for (String sub : expectNs) { - expect.add(JMXNamespaces.getNamespaceObjectName(sub)); - } - - if (! nsNames.containsAll(expect)) - throw new Exception("queryNames didn't return all namespaces: "+ - "returned="+nsNames+", expected="+expect); - if (! expect.containsAll(nsNames)) - throw new Exception("getDomains returned additional namespaces: "+ - "returned="+nsNames+", expected="+expect); - - } - } - - private static void addWombats(MBeanServer server, Set names) - throws Exception { - for (ObjectName on : names) { - if (! server.isRegistered(on)) { - server.createMBean(Wombat.class.getName(),on); - System.out.println("A new wombat is born: "+on); - } - } - } - - private static void addWombats(MBeanServer server, - Map> wombats) - throws Exception { - for (String ns : wombats.keySet()) { - addWombats(server,wombats.get(ns)); - } - } - - private static Map> nameWombats() - throws Exception { - final Rigolo rigolo = new Rigolo(); - final Map> wombats = - new HashMap>(namespaces.length); - - for (String ns : namespaces) { - wombats.put(ns,rigolo.nextWombats(ns)); - } - wombats.put("",rigolo.nextWombats("")); - return wombats; - } - - private static boolean removeWombats(MBeanServer server, - Map> wombats) { - boolean res = true; - for (String ns : wombats.keySet()) { - res = res && removeWombats(server,wombats.get(ns)); - } - return res; - } - - private static boolean removeWombats(MBeanServer server, - Set wombats) { - boolean res = true; - for (ObjectName on : wombats) { - try { - if (server.isRegistered(on)) - server.unregisterMBean(on); - } catch (Exception x) { - res = false; - System.out.println("Failed to remove "+on+": "+x); - } - } - return res; - } - - private static void checkNsPattern(MBeanServer server) throws Exception { - final List list = new ArrayList(); - for (String s : namespaces) { - final String[] cmpnt = s.split("//"); - for (int i=0;i res = new HashSet(); - - try { - res.addAll(server.queryNames(ObjectName.valueOf(s),null)); - } catch (RuntimeOperationsException x) { - if (x.getCause() instanceof IllegalArgumentException) { - System.out.println("queryNames("+s+"): OK - received "+x.getCause()); - continue; - } - System.err.println("queryNames("+s+"): Bad cause: "+x.getCause()); - throw x; - } catch (Exception x) { - System.err.println("queryNames("+s+"): Bad exception: "+x); - throw x; - } - System.err.println("queryNames("+s+"): Bad result: "+res); - System.err.println("queryNames("+s+"): Excpected exception not thrown."); - throw new Exception("queryNames("+s+"): Excpected exception not thrown."); - } - for (String s : list) { - final Set res = new HashSet(); - - try { - res.addAll(server.queryMBeans(ObjectName.valueOf(s),null)); - } catch (RuntimeOperationsException x) { - if (x.getCause() instanceof IllegalArgumentException) { - System.out.println("queryMBeans("+s+"): OK - received "+x.getCause()); - continue; - } - System.err.println("queryMBeans("+s+"): Bad cause: "+x.getCause()); - throw x; - } catch (Exception x) { - System.err.println("queryMBeans("+s+"): Bad exception: "+x); - throw x; - } - System.err.println("queryMBeans("+s+"): Bad result: "+res); - System.err.println("queryMBeans("+s+"): Excpected exception not thrown."); - throw new Exception("queryMBeans("+s+"): Excpected exception not thrown."); - } - } - - public static void main(String[] args) - throws Exception { - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - Map> wombats = nameWombats(); - createNamespaces(server); - try { - addWombats(server,wombats); - System.out.println("MBeans: " +server.getMBeanCount()); - System.out.println("Visible: " +server.queryNames(null,null).size()); - System.out.println("Domains: " +Arrays.asList(server.getDomains())); - checkRegistration(server); - checkNsQuery(server); - checkNsPattern(server); - } finally { - boolean res = true; - res = res && removeWombats(server, wombats); - if (!res) - throw new RuntimeException("failed to cleanup some namespaces"); - } - - } - - private static boolean removeNamespaces(MBeanServer server) { - final List l = Arrays.asList(namespaces); - Collections.reverse(l); - return removeNamespaces(server, l.toArray(new String[namespaces.length])); - } - - private static boolean removeNamespaces(MBeanServer server, String[] t) { - boolean success = true; - for (String ns : t) { - try { - server.unregisterMBean(JMXNamespaces.getNamespaceObjectName(ns)); - } catch (Exception x) { - System.out.println("failed to remove namespace: "+ ns); - success = false; - } - } - return success; - } - -} diff --git a/test/javax/management/namespace/RemoveNotificationListenerTest.java b/test/javax/management/namespace/RemoveNotificationListenerTest.java deleted file mode 100644 index a8ea2aee3..000000000 --- a/test/javax/management/namespace/RemoveNotificationListenerTest.java +++ /dev/null @@ -1,377 +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. - * - * 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. - */ -/* - * - * @test RemoveNotificationListenerTest.java 1.8 - * @summary General RemoveNotificationListenerTest test. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean RemoveNotificationListenerTest JMXRemoteTargetNamespace - * @compile -XDignore.symbol.file=true JMXRemoteTargetNamespace.java - * @run build RemoveNotificationListenerTest JMXRemoteTargetNamespace - * @run main/othervm RemoveNotificationListenerTest - */ - -import com.sun.jmx.remote.util.EventClientConnection; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.security.Principal; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; -import javax.management.JMException; -import javax.management.JMX; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.namespace.JMXNamespaces; -import javax.management.remote.JMXAuthenticator; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXConnectorServerMBean; -import javax.management.remote.JMXPrincipal; -import javax.management.remote.JMXServiceURL; -import javax.security.auth.Subject; - -/** - * Class RemoveNotificationListenerTest - */ -public class RemoveNotificationListenerTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(RemoveNotificationListenerTest.class.getName()); - - /** Creates a new instance of RemoveNotificationListenerTest */ - public RemoveNotificationListenerTest() { - } - - public static class SubjectAuthenticator implements JMXAuthenticator { - final Set authorized; - public SubjectAuthenticator(Subject[] authorized) { - this.authorized = new HashSet(Arrays.asList(authorized)); - } - - public Subject authenticate(Object credentials) { - if (authorized.contains(credentials)) - return (Subject)credentials; - else - throw new SecurityException("Subject not authorized: "+credentials); - } - - } - - public static interface LongtarMBean { - public void sendNotification(Object userData) - throws IOException, JMException; - } - public static class Longtar extends NotificationBroadcasterSupport - implements LongtarMBean { - public Longtar() { - super(new MBeanNotificationInfo[] { - new MBeanNotificationInfo(new String[] {"papillon"}, - "pv","M'enfin???") - }); - } - - public void sendNotification(Object userData) - throws IOException, JMException { - final Notification n = - new Notification("papillon",this,nextseq(),"M'enfin???"); - n.setUserData(userData); - System.out.println("Sending notification: "+userData); - sendNotification(n); - } - - private static synchronized long nextseq() {return ++seqnb;} - private static volatile long seqnb=0; - } - - private static final String NS = JMXNamespaces.NAMESPACE_SEPARATOR; - private static final String CS = "jmx.rmi:type=JMXConnectorServer"; - private static final String BD = "longtar:type=Longtar"; - - private static void createNamespace(MBeanServerConnection server, - String namespace, Subject creator, boolean forwarding) - throws Exception { - final MBeanServer sub = MBeanServerFactory.createMBeanServer(); - final JMXServiceURL url = new JMXServiceURL("rmi",null,0); - final Map smap = new HashMap(); - smap.put(JMXConnectorServer.AUTHENTICATOR, - new SubjectAuthenticator(new Subject[] {creator})); - final JMXConnectorServer rmi = - JMXConnectorServerFactory.newJMXConnectorServer(url,smap,null); - final ObjectName name = new ObjectName(CS); - sub.registerMBean(rmi,name); - rmi.start(); - final Map cmap = new HashMap(); - cmap.put(JMXConnector.CREDENTIALS,creator); - final Map options = new HashMap(cmap); - options.put(JMXRemoteTargetNamespace.CREATE_EVENT_CLIENT,"true"); - JMXRemoteTargetNamespace.createNamespace(server, - namespace, - rmi.getAddress(), - options - ); - server.invoke(JMXNamespaces.getNamespaceObjectName(namespace), - "connect", null,null); - } - private static void closeNamespace(MBeanServerConnection server, - String namespace) { - try { - final ObjectName hname = - JMXNamespaces.getNamespaceObjectName(namespace); - if (!server.isRegistered(hname)) - return; - final ObjectName sname = - new ObjectName(namespace+NS+CS); - if (!server.isRegistered(sname)) - return; - final JMXConnectorServerMBean cs = - JMX.newMBeanProxy(server,sname, - JMXConnectorServerMBean.class,true); - try { - cs.stop(); - } finally { - server.unregisterMBean(hname); - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - - private static Subject newSubject(String[] principals) { - final Set ps = new HashSet(); - for (String p:principals) ps.add(new JMXPrincipal(p)); - return new Subject(true,ps,Collections.emptySet(),Collections.emptySet()); - } - - - public static void testSubject() throws Exception { - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - final String a = "a"; - final String b = a + NS + "b"; - - final Subject s1 = newSubject(new String[] {"chichille"}); - final Subject s2 = newSubject(new String[] {"alambic"}); - final Subject s3 = newSubject(new String[] {"virgule"}); - final Subject s4 = newSubject(new String[] {"funeste"}); - - final JMXServiceURL url = new JMXServiceURL("rmi",null,0); - final Map smap = new HashMap(); - smap.put(JMXConnectorServer.AUTHENTICATOR, - new SubjectAuthenticator(new Subject[] {s1})); - final JMXConnectorServer rmi = - JMXConnectorServerFactory.newJMXConnectorServer(url,smap,null); - final ObjectName name = new ObjectName(CS); - server.registerMBean(rmi,name); - rmi.start(); - - try { - - final Map map = new HashMap(); - map.put(JMXConnector.CREDENTIALS,s1); - final JMXConnector c = - JMXConnectorFactory.connect(rmi.getAddress(),map); - final MBeanServerConnection mbsorig = c.getMBeanServerConnection(); - - final MBeanServerConnection mbs = - EventClientConnection.getEventConnectionFor(mbsorig,null); - - createNamespace(mbs,a,s2,true); - createNamespace(mbs,b,s3,true); - - final ObjectName longtar = new ObjectName(b+NS+BD); - - mbs.createMBean(Longtar.class.getName(),longtar); - final LongtarMBean proxy = - JMX.newMBeanProxy(mbs,longtar,LongtarMBean.class,true); - - - final BlockingQueue bbq = - new ArrayBlockingQueue(10); - final NotificationListener listener1 = new NotificationListener() { - public void handleNotification(Notification notification, - Object handback) { - System.out.println(notification.getSequenceNumber()+": "+ - notification.getMessage()); - bbq.add(notification); - } - }; - final NotificationListener listener2 = new NotificationListener() { - public void handleNotification(Notification notification, - Object handback) { - System.out.println(notification.getSequenceNumber()+": "+ - notification.getMessage()); - bbq.add(notification); - } - }; - - final NotificationEmitter ubpdalfdla = (NotificationEmitter)proxy; - try { - - // Add 1 NL, send 1 notif (1) - ubpdalfdla.addNotificationListener(listener1,null,listener1); - proxy.sendNotification(new Integer(1)); - // Thread.sleep(180000); - - // We should have 1 notif with userdata = 1 - final Notification n1 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n1.getUserData()).intValue() != 1) - throw new Exception("Expected 1, got"+n1.getUserData()); - - // remove NL, send 1 notif (2) => we shouldn't receive it - ubpdalfdla.removeNotificationListener(listener1,null,listener1); - proxy.sendNotification(new Integer(2)); - - // add NL, send 1 notif (3) - ubpdalfdla.addNotificationListener(listener1,null,listener1); - proxy.sendNotification(new Integer(3)); - - // we should receive only 1 notif (3) - final Notification n3 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n3.getUserData()).intValue() != 3) - throw new Exception("Expected 3, got"+n3.getUserData()); - - // remove NL, send 1 notif (4) => we shouldn't receive it. - ubpdalfdla.removeNotificationListener(listener1); - proxy.sendNotification(new Integer(4)); - - // add NL, send 1 notif (5). - ubpdalfdla.addNotificationListener(listener1,null,listener1); - proxy.sendNotification(new Integer(5)); - - // next notif in queue should be (5) - final Notification n5 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n5.getUserData()).intValue() != 5) - throw new Exception("Expected 5, got"+n5.getUserData()); - - // add 2 NL, send 1 notif (6) - ubpdalfdla.addNotificationListener(listener2,null,listener2); - ubpdalfdla.addNotificationListener(listener2,null,null); - proxy.sendNotification(new Integer(6)); - - // We have 3 NL, we should receive (6) 3 times.... - final Notification n61 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n61.getUserData()).intValue() != 6) - throw new Exception("Expected 6 (#1), got"+n61.getUserData()); - final Notification n62 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n62.getUserData()).intValue() != 6) - throw new Exception("Expected 6 (#2), got"+n62.getUserData()); - final Notification n63 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n63.getUserData()).intValue() != 6) - throw new Exception("Expected 6 (#3), got"+n63.getUserData()); - - // Remove 1 NL, send 1 notif (7) - ubpdalfdla.removeNotificationListener(listener2,null,null); - proxy.sendNotification(new Integer(7)); - - // next notifs in queue should be (7), twice... - final Notification n71 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n71.getUserData()).intValue() != 7) - throw new Exception("Expected 7 (#1), got"+n71.getUserData()); - final Notification n72 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n72.getUserData()).intValue() != 7) - throw new Exception("Expected 7 (#2), got"+n72.getUserData()); - - // Add 1 NL, send 1 notif (8) - ubpdalfdla.addNotificationListener(listener2,null,null); - proxy.sendNotification(new Integer(8)); - - // Next notifs in queue should be (8), 3 times. - final Notification n81 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n81.getUserData()).intValue() != 8) - throw new Exception("Expected 8 (#1), got"+n81.getUserData()); - final Notification n82 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n82.getUserData()).intValue() != 8) - throw new Exception("Expected 8 (#2), got"+n82.getUserData()); - final Notification n83 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n83.getUserData()).intValue() != 8) - throw new Exception("Expected 8 (#3), got"+n83.getUserData()); - - // Remove 2 NL, send 1 notif (9) - ubpdalfdla.removeNotificationListener(listener2); - proxy.sendNotification(new Integer(9)); - - // Next notifs in queue should be (9), 1 time only. - final Notification n9 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n9.getUserData()).intValue() != 9) - throw new Exception("Expected 9, got"+n9.getUserData()); - - // send 1 notif (10) - proxy.sendNotification(new Integer(10)); - - // Next notifs in queue should be (10), 1 time only. - final Notification n10 = bbq.poll(3,TimeUnit.SECONDS); - // may throw NPE => would indicate a bug. - if (((Integer)n10.getUserData()).intValue() != 10) - throw new Exception("Expected 10, got"+n10.getUserData()); - - ubpdalfdla.removeNotificationListener(listener1); - mbs.unregisterMBean(longtar); - - } finally { - c.close(); - } - } finally { - closeNamespace(server,b); - closeNamespace(server,a); - rmi.stop(); - } - - } - - public static void main(String[] args) throws Exception { - testSubject(); - } - -} diff --git a/test/javax/management/namespace/RoutingServerProxyTest.java b/test/javax/management/namespace/RoutingServerProxyTest.java deleted file mode 100644 index 698021321..000000000 --- a/test/javax/management/namespace/RoutingServerProxyTest.java +++ /dev/null @@ -1,400 +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. - * - * 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. - */ - -/* - * @test RoutingServerProxyTest.java 1.6 - * @summary General RoutingServerProxyTest test. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean RoutingServerProxyTest Wombat WombatMBean - * @compile -XDignore.symbol.file=true RoutingServerProxyTest.java - * @run build RoutingServerProxyTest Wombat WombatMBean - * @run main RoutingServerProxyTest - */ - -import com.sun.jmx.namespace.RoutingServerProxy; -import java.io.IOException; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; - -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.JMException; -import javax.management.JMX; -import javax.management.MBeanInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationEmitter; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.StandardEmitterMBean; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.MBeanServerSupport; - -/** - * Class RoutingServerProxyTest - * - * @author Sun Microsystems, Inc. - */ -public class RoutingServerProxyTest { - - /** - * A logger for this class. - **/ - private static final Logger LOG = - Logger.getLogger(RoutingServerProxyTest.class.getName()); - - /** - * Creates a new instance of RoutingServerProxyTest - */ - public RoutingServerProxyTest() { - } - - public static class DynamicWombat extends StandardEmitterMBean { - DynamicWombat(Wombat w) throws NotCompliantMBeanException { - super(w,WombatMBean.class,w); - } - - @Override - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - final ObjectName myname = ((Wombat)getImplementation()). - preRegister(server,name); - return super.preRegister(server,myname); - } - - @Override - public void postRegister(Boolean registrationDone) { - try { - ((Wombat)getImplementation()). - postRegister(registrationDone); - } finally { - super.postRegister(registrationDone); - } - } - - @Override - public void preDeregister() throws Exception { - ((Wombat)getImplementation()). - preDeregister(); - super.preDeregister(); - - } - - @Override - public void postDeregister() { - try { - ((Wombat)getImplementation()). - postDeregister(); - } finally { - super.postDeregister(); - } - } - } - - public static class VirtualWombatHandler - extends JMXNamespace { - - public static class VirtualWombatRepository - extends MBeanServerSupport { - - final Map bush; - - VirtualWombatRepository(Map bush) { - this.bush = bush; - } - - @Override - protected Set getNames() { - return bush.keySet(); - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - final DynamicMBean mb = bush.get(name); - if (mb == null) { - throw new InstanceNotFoundException(String.valueOf(name)); - } - return mb; - } - - @Override - public NotificationEmitter getNotificationEmitterFor( - ObjectName name) throws InstanceNotFoundException { - DynamicMBean mbean = getDynamicMBeanFor(name); - if (mbean instanceof NotificationEmitter) { - return (NotificationEmitter) mbean; - } - return null; - } - } - VirtualWombatRepository bush; - - VirtualWombatHandler(Map bush) { - this(new VirtualWombatRepository(Collections.synchronizedMap(bush))); - } - - private VirtualWombatHandler(VirtualWombatRepository repository) { - super(repository); - bush = repository; - } - - @Override - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - final ObjectName myname = super.preRegister(server, name); - return myname; - } - - @Override - public void postRegister(Boolean registrationDone) { - if (!registrationDone.booleanValue()) { - return; - } - final MBeanServer me = JMXNamespaces.narrowToNamespace(getMBeanServer(), - getObjectName().getDomain()); - for (Map.Entry e : bush.bush.entrySet()) { - final DynamicMBean obj = e.getValue(); - try { - if (obj instanceof MBeanRegistration) { - ((MBeanRegistration) obj).preRegister(me, e.getKey()); - } - } catch (Exception x) { - System.err.println("preRegister failed for " + - e.getKey() + ": " + x); - bush.bush.remove(e.getKey()); - } - } - for (Map.Entry e : bush.bush.entrySet()) { - final Object obj = e.getValue(); - if (obj instanceof MBeanRegistration) { - ((MBeanRegistration) obj).postRegister(registrationDone); - } - } - } - - @Override - public void preDeregister() throws Exception { - for (Map.Entry e : bush.bush.entrySet()) { - final Object obj = e.getValue(); - if (obj instanceof MBeanRegistration) { - ((MBeanRegistration) obj).preDeregister(); - } - } - } - - @Override - public void postDeregister() { - for (Map.Entry e : bush.bush.entrySet()) { - final Object obj = e.getValue(); - if (obj instanceof MBeanRegistration) { - ((MBeanRegistration) obj).postDeregister(); - } - } - } - } - - public static ObjectName getWombatName(String name) - throws MalformedObjectNameException { - return ObjectName.getInstance("australian.bush:type=Wombat,name="+name); - } - - public static ObjectName addDir(String dir, ObjectName name) - throws MalformedObjectNameException { - return name.withDomain( - dir+JMXNamespaces.NAMESPACE_SEPARATOR+ name.getDomain()); - } - - public static void simpleTest() - throws JMException, IOException { - final MBeanServer master = MBeanServerFactory.createMBeanServer(); - final MBeanServer agent1 = MBeanServerFactory.createMBeanServer(); - final Wombat w1 = new Wombat(); - final Wombat w2 = new Wombat(); - final Wombat w3 = new Wombat(); - final Map wombats = - new ConcurrentHashMap(); - wombats.put(getWombatName("LittleWombat"), - new DynamicWombat(w2)); - wombats.put(getWombatName("BigWombat"), - new DynamicWombat(w3)); - final Wombat w4 = new Wombat(); - final Wombat w5 = new Wombat(); - - final JMXNamespace agent2 = - new VirtualWombatHandler(wombats); - agent1.registerMBean(w4,getWombatName("LittleWombat")); - master.registerMBean(w1,getWombatName("LittleWombat")); - master.registerMBean(new JMXNamespace(agent1), - JMXNamespaces.getNamespaceObjectName("south.east")); - master.registerMBean(agent2, - JMXNamespaces.getNamespaceObjectName("north")); - master.registerMBean(w5,addDir("south.east", - getWombatName("GrandWombat"))); - - MBeanServer se = null; - - try { - se = JMXNamespaces.narrowToNamespace(master,"south.easht"); - } catch (Exception x) { - System.out.println("Caught expected exception: "+x); - } - if (se != null) - throw new RuntimeException("Expected exception for "+ - "cd(south.easht)"); - se = JMXNamespaces.narrowToNamespace(master,"south.east"); - - MBeanServer nth = JMXNamespaces.narrowToNamespace(master,"north"); - - final ObjectName ln = getWombatName("LittleWombat"); - MBeanInfo mb1 = master.getMBeanInfo(ln); - MBeanInfo mb2 = se.getMBeanInfo(ln); - MBeanInfo mb3 = nth.getMBeanInfo(ln); - - final WombatMBean grand = JMX.newMBeanProxy(se, - getWombatName("GrandWombat"),WombatMBean.class); - final WombatMBean big = JMX.newMBeanProxy(nth, - getWombatName("BigWombat"),WombatMBean.class); - grand.getCaption(); - big.getCaption(); - grand.setCaption("I am GrandWombat"); - big.setCaption("I am BigWombat"); - - final WombatMBean grand2 = - JMX.newMBeanProxy(master,addDir("south.east", - getWombatName("GrandWombat")),WombatMBean.class); - final WombatMBean big2 = - JMX.newMBeanProxy(master,addDir("north", - getWombatName("BigWombat")),WombatMBean.class); - if (!"I am GrandWombat".equals(grand2.getCaption())) - throw new RuntimeException("bad caption for GrandWombat"+ - grand2.getCaption()); - if (!"I am BigWombat".equals(big2.getCaption())) - throw new RuntimeException("bad caption for BigWombat"+ - big2.getCaption()); - - - final Set northWombats = - nth.queryMBeans(ObjectName.WILDCARD,null); - final Set seWombats = - se.queryMBeans(ObjectName.WILDCARD,null); - if (!northWombats.equals( - agent2.getSourceServer().queryMBeans(ObjectName.WILDCARD,null))) { - throw new RuntimeException("Bad Wombat census in northern territory: got " - +northWombats+", expected "+ - agent2.getSourceServer(). - queryMBeans(ObjectName.WILDCARD,null)); - } - if (!seWombats.equals( - agent1.queryMBeans(ObjectName.WILDCARD,null))) { - throw new RuntimeException("Bad Wombat census in south east: got " - +seWombats+", expected "+ - agent1. - queryMBeans(ObjectName.WILDCARD,null)); - } - - final MBeanServer supermaster = MBeanServerFactory.createMBeanServer(); - supermaster.registerMBean(new JMXNamespace(master), - JMXNamespaces.getNamespaceObjectName("australia")); - final MBeanServer proxymaster = - JMXNamespaces.narrowToNamespace(supermaster,"australia"); - final MBeanServer sem = - JMXNamespaces.narrowToNamespace(proxymaster,"south.east"); - final MBeanServer nthm = - JMXNamespaces.narrowToNamespace(proxymaster,"north"); - final Set northWombats2 = - nthm.queryMBeans(ObjectName.WILDCARD,null); - final Set seWombats2 = - sem.queryMBeans(ObjectName.WILDCARD,null); - if (!northWombats2.equals( - agent2.getSourceServer().queryMBeans(ObjectName.WILDCARD,null))) { - throw new RuntimeException("Bad Wombat census in " + - "Australia // North"); - } - if (!seWombats2.equals( - agent1.queryMBeans(ObjectName.WILDCARD,null))) { - throw new RuntimeException("Bad Wombat census in " + - "Australia // South East"); - } - final WombatMBean grand3 = - JMX.newMBeanProxy(supermaster, - addDir("australia//south.east", - getWombatName("GrandWombat")),WombatMBean.class); - final WombatMBean big3 = - JMX.newMBeanProxy(supermaster,addDir("australia//north", - getWombatName("BigWombat")),WombatMBean.class); - if (!"I am GrandWombat".equals(grand3.getCaption())) - throw new RuntimeException("bad caption for " + - "australia//south.east//GrandWombat"+ - grand3.getCaption()); - if (!"I am BigWombat".equals(big3.getCaption())) - throw new RuntimeException("bad caption for " + - "australia//north//BigWombat"+ - big3.getCaption()); - final WombatMBean grand4 = - JMX.newMBeanProxy(sem, - getWombatName("GrandWombat"),WombatMBean.class); - final WombatMBean big4 = - JMX.newMBeanProxy(nthm, - getWombatName("BigWombat"),WombatMBean.class); - if (!"I am GrandWombat".equals(grand4.getCaption())) - throw new RuntimeException("bad caption for " + - "[australia//south.east//] GrandWombat"+ - grand4.getCaption()); - if (!"I am BigWombat".equals(big4.getCaption())) - throw new RuntimeException("bad caption for " + - "[australia//north//] BigWombat"+ - big4.getCaption()); - - if (!(nthm instanceof RoutingServerProxy)) - throw new AssertionError("expected RoutingServerProxy for nthm"); - if (!(sem instanceof RoutingServerProxy)) - throw new AssertionError("expected RoutingServerProxy for sem"); - - if (!"australia//north".equals(( - (RoutingServerProxy)nthm).getSourceNamespace())) - throw new RuntimeException("north territory should be in australia"); - if (!"australia//south.east".equals(( - (RoutingServerProxy)sem).getSourceNamespace())) - throw new RuntimeException("south east territory should be in australia"); - - } - - public static void main(String[] args) { - try { - simpleTest(); - } catch (Exception x) { - System.err.println("SimpleTest failed: "+x); - throw new RuntimeException(x); - } - } - -} diff --git a/test/javax/management/namespace/SerialParamProcessorTest.java b/test/javax/management/namespace/SerialParamProcessorTest.java deleted file mode 100644 index 20df761d0..000000000 --- a/test/javax/management/namespace/SerialParamProcessorTest.java +++ /dev/null @@ -1,572 +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. - * - * 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. - */ - -/* - * - * @test SerialParamProcessorTest.java 1.8 - * @summary General SerialParamProcessorTest test. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean SerialParamProcessorTest Wombat WombatMBean - * @compile -XDignore.symbol.file=true SerialParamProcessorTest.java - * @run build SerialParamProcessorTest Wombat WombatMBean - * @run main SerialParamProcessorTest - */ - -import com.sun.jmx.namespace.serial.RewritingProcessor; -import java.beans.ConstructorProperties; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import javax.management.AttributeChangeNotification; -import javax.management.AttributeList; -import javax.management.JMException; -import javax.management.Notification; -import javax.management.ObjectName; -import javax.management.StandardMBean; - -/** - * Class SerialParamProcessorTest - * - * @author Sun Microsystems, Inc. - */ -public class SerialParamProcessorTest { - - /** - * Creates a new instance of SerialParamProcessorTest - */ - public SerialParamProcessorTest() { - } - - public static class MyCompositeData implements Serializable { - private static final long serialVersionUID = 3186492415099133506L; - public MyCompositeData(ObjectName foobar,ObjectName absolute, - long count, String name) { - this(foobar,absolute,count,name,new ObjectName[]{foobar,absolute}); - } - @ConstructorProperties(value={"fooBar","absolute","count","name", - "allNames"}) - public MyCompositeData(ObjectName foobar,ObjectName absolute, - long count, String name, ObjectName[] allnames) { - this.foobar = foobar; - this.absolute = absolute; - this.count = count; - this.name = name; - this.allnames = allnames; - } - ObjectName foobar,absolute,allnames[]; - long count; - String name; - public ObjectName getFooBar() { - return foobar; - } - public ObjectName getAbsolute() { - return absolute; - } - public ObjectName[] getAllNames() { - return allnames; - } - public long getCount() { - return count; - } - public String getName() { - return name; - } - private Object[] toArray() { - final Object[] props = { - getName(),getFooBar(),getAbsolute(),getAllNames(),getCount() - }; - return props; - } - @Override - public boolean equals(Object o) { - if (o instanceof MyCompositeData) - return Arrays.deepEquals(toArray(), - ((MyCompositeData)o).toArray()); - return false; - } - @Override - public int hashCode() { - return Arrays.deepHashCode(toArray()); - } - } - - public static interface MyMXBean { - public Map getAll(); - public MyCompositeData lookup(String name); - public void put(String name, MyCompositeData data); - public MyCompositeData remove(String name); - } - - public static class My implements MyMXBean { - Map datas = - new HashMap(); - public Map getAll() { - return datas; - } - public MyCompositeData lookup(String name) { - return datas.get(name); - } - public void put(String name, MyCompositeData data) { - datas.put(name,data); - } - public MyCompositeData remove(String name) { - return datas.remove(name); - } - } - - public static class BandicootClass implements Serializable { - private static final long serialVersionUID = -5494055748633966355L; - public final Object gloups; - public BandicootClass(Object gloups) { - this.gloups = gloups; - } - private Object[] toArray() { - final Object[] one = {gloups}; - return one; - } - @Override - public boolean equals(Object obj) { - if (!(obj instanceof BandicootClass)) return false; - final Object[] one = {gloups}; - return Arrays.deepEquals(toArray(),((BandicootClass)obj).toArray()); - } - @Override - public int hashCode() { - if (gloups == null) return 0; - return Arrays.deepHashCode(toArray()); - } - } - - // Need this to override equals. - public static class BandicootNotification extends Notification { - private static final long serialVersionUID = 664758643764049001L; - public BandicootNotification(String type, Object source, long seq) { - super(type,source,seq,0L,""); - } - private Object[] toArray() { - final Object[] vals = {getMessage(),getSequenceNumber(), - getSource(),getTimeStamp(),getType(),getUserData()}; - return vals; - } - @Override - public boolean equals(Object o) { - if (!(o instanceof BandicootNotification)) return false; - return Arrays.deepEquals(toArray(), - ((BandicootNotification)o).toArray()); - } - @Override - public int hashCode() { - return Arrays.deepHashCode(toArray()); - } - - } - - // Need this to override equals. - public static class BandicootAttributeChangeNotification - extends AttributeChangeNotification { - private static final long serialVersionUID = -1392435607144396125L; - public BandicootAttributeChangeNotification(Object source, - long seq, long time, String msg, String name, String type, - Object oldv, Object newv) { - super(source,seq,time,msg,name,type,oldv,newv); - } - private Object[] toArray() { - final Object[] vals = {getMessage(),getSequenceNumber(), - getSource(),getTimeStamp(),getType(),getUserData(), - getAttributeName(), getAttributeType(),getNewValue(), - getOldValue()}; - return vals; - } - @Override - public boolean equals(Object o) { - if (!(o instanceof BandicootAttributeChangeNotification)) - return false; - return Arrays.deepEquals(toArray(), - ((BandicootAttributeChangeNotification)o).toArray()); - } - @Override - public int hashCode() { - return Arrays.deepHashCode(toArray()); - } - @Override - public String toString() { - final StringBuilder b = new StringBuilder(); - b.append(this.getClass().getName()).append(": "); - b.append("[type=").append(getType()).append("]"); - b.append("[source=").append(getSource()).append("]"); - b.append("[message=").append(getMessage()).append("]"); - b.append("[sequence=").append(getSequenceNumber()).append("]"); - - b.append("[attribute=").append(getAttributeName()).append("]"); - b.append("[class=").append(getAttributeType()).append("]"); - b.append("[oldvalue=").append(getOldValue()).append("]"); - b.append("[newvalue=").append(getNewValue()).append("]"); - - b.append("[time=").append(getTimeStamp()).append("]"); - b.append("[data=").append(getUserData()).append("]"); - return b.toString(); - } - } - - private static void addToList(Object[] foos, List foolist) { - final ArrayList fal = new ArrayList(foos.length); - for (Object f : foos) { - if (f.getClass().isArray()) { - foolist.add(new BandicootClass(f)); - fal.add(new BandicootClass(f)); - } else { - foolist.add(f); - fal.add(f); - } - } - foolist.add(new BandicootClass(foos)); - foolist.add(fal); - } - - public static void testSerial(String msg, Object foo, Object bar, - RewritingProcessor procForFoo, - RewritingProcessor procForBar, List foolist, - List barlist, boolean recurse) { - System.err.println(msg+" Testing serial - "+foo.getClass().getName()); - final Object bar1 = procForFoo.rewriteInput(foo); - final Object foo1 = procForFoo.rewriteOutput(bar); - final Object bar2 = procForFoo.rewriteInput(foo1); - final Object foo2 = procForFoo.rewriteOutput(bar1); - - final Object bar3 = procForBar.rewriteOutput(foo); - final Object foo3 = procForBar.rewriteInput(bar); - final Object bar4 = procForBar.rewriteOutput(foo3); - final Object foo4 = procForBar.rewriteInput(bar3); - - final Object bar5 = procForFoo.rewriteInput(foo3); - final Object foo5 = procForFoo.rewriteOutput(bar3); - - final Object bar6 = procForBar.rewriteOutput(foo1); - final Object foo6 = procForBar.rewriteInput(bar1); - - final Object[] foos = {foo, foo1, foo2, foo3, foo4, foo5, foo6}; - final Object[] bars = {bar, bar1, bar2, bar3, bar4, bar5, bar6}; - - final Object[] foot = { foo }; - final Object[] bart = { bar }; - for (int j=1;j foolist = new LinkedList(); - final List barlist = new LinkedList(); - for (Object[] row : objects) { - i++; - Object foo = row[0]; - Object bar = row[1]; - String msg1 = "[" +foo.getClass().getName() + "] step " + - i +": "; - - testSerial(msg1,foo,bar,procForFoo,procForBar,foolist,barlist,true); - - final BandicootClass kfoo = new BandicootClass(foo); - final BandicootClass kbar = new BandicootClass(bar); - - String msg2 = "[" +kfoo.getClass().getName() + "] step " + - i +": "; - testSerial(msg2,kfoo,kbar,procForFoo,procForBar,foolist,barlist,true); - } - String msg31 = "foo[] and bar[]: "; - testSerial(msg31,foolist.toArray(),barlist.toArray(), - procForFoo,procForBar,foolist,barlist,false); - - String msg3 = "foolist and barlist: "; - testSerial(msg3,new LinkedList(foolist), - new LinkedList(barlist), - procForFoo,procForBar,foolist,barlist,false); - - final BandicootClass kfoolist = new BandicootClass(foolist); - final BandicootClass kbarlist = new BandicootClass(barlist); - String msg4 = "kfoolist and kbarlist: "; - testSerial(msg4,kfoolist,kbarlist,procForFoo,procForBar,foolist,barlist,false); - } - - /** - * The idea of this method is to convert {@code foo} things into - * {@code bar} things... - * @param foo the string to replace. - * @param bar the replacement for {@code foo} - * ({@code foo} becomes {@code bar}). - * @param sfoo a string that may contain {@code foo}, that will be embedded - * in non-replaceable parts of the domain in order to attempt to - * trick the replacement logic. - * @param sbar a string that may contain {@code bar}, that will be embedded - * in non-replaceable parts of the domain in order to attempt to - * trick the replacement logic. - **/ - public static void doSerialTest(String foo, String bar, String sfoo, - String sbar) { - try { - final RewritingProcessor procForFoo = RewritingProcessor. - newRewritingProcessor(foo,bar); - final RewritingProcessor procForBar =RewritingProcessor. - newRewritingProcessor(bar,foo); - final String foop = (foo.isEmpty())?foo:foo+"//"; - final String pfoo = (foo.isEmpty())?foo:"//"+foo; - final String barp = (bar.isEmpty())?bar:bar+"//"; - final String pbar = (bar.isEmpty())?bar:"//"+bar; - final String sfoop = (sfoo.isEmpty())?sfoo:sfoo+"//"; - final String psfoo = (sfoo.isEmpty())?sfoo:"//"+sfoo; - final String sbarp = (sbar.isEmpty())?sbar:sbar+"//"; - final String psbar = (sbar.isEmpty())?sbar:"//"+sbar; - - // A trick to avoid writing Open Data by hand... - final My tricks = new My(); - - // A treat to automagically convert trick things into Open Data. - final StandardMBean treats = - new StandardMBean(tricks,MyMXBean.class,true); - - // datas[i][0] is expected to be transformed in datas[i][1] - // - final MyCompositeData[][] datas = { - { // this foo thing: - new MyCompositeData(new ObjectName(foop+sbarp+"x:y=z"), - new ObjectName("//"+foop+sbarp+"x:y=z"),1,sfoop+sbarp+"foobar"), - // should be transformed into this bar thing: - new MyCompositeData(new ObjectName(barp+sbarp+"x:y=z"), - new ObjectName("//"+foop+sbarp+"x:y=z"),1,sfoop+sbarp+"foobar"), - }, - { // this foo thing: - new MyCompositeData(new ObjectName(foop+sfoop+"x:y=z"), - new ObjectName("//"+foop+sfoop+"x:y=z"),1,sfoop+sbarp+"barfoo"), - // should be transformed into this bar thing: - new MyCompositeData(new ObjectName(barp+sfoop+"x:y=z"), - new ObjectName("//"+foop+sfoop+"x:y=z"),1,sfoop+sbarp+"barfoo"), - } - }; - - // objects[i][0] is expected to be transformed into objects[i][1] - // - final Object[][] objects = new Object[][] { - {new Long(1), new Long(1)}, - { - new ObjectName(foop+sbarp+"x:y=z"), - new ObjectName(barp+sbarp+"x:y=z") - }, - { - new ObjectName(foop+sfoop+"x:y=z"), - new ObjectName(barp+sfoop+"x:y=z") - }, - { - new ObjectName("//"+foop+sbarp+"x:y=z"), - new ObjectName("//"+foop+sbarp+"x:y=z"), - }, - { - new ObjectName("//"+foop+sfoop+"x:y=z"), - new ObjectName("//"+foop+sfoop+"x:y=z") - }, - { - foop+sbarp+"x:y=z",foop+sbarp+"x:y=z" - }, - { - foop+sfoop+"x:y=z",foop+sfoop+"x:y=z" - }, - { - barp+sbarp+"x:y=z",barp+sbarp+"x:y=z" - }, - { - barp+sfoop+"x:y=z",barp+sfoop+"x:y=z" - }, - { - new BandicootNotification("test",new ObjectName(foop+sfoop+"x:y=z"),1L), - new BandicootNotification("test",new ObjectName(barp+sfoop+"x:y=z"),1L), - }, - { - new BandicootNotification("test",new ObjectName("//"+foop+sfoop+"x:y=z"),2L), - new BandicootNotification("test",new ObjectName("//"+foop+sfoop+"x:y=z"),2L), - }, - { - new BandicootAttributeChangeNotification( - new ObjectName(foop+sfoop+"x:y=z"),1L,2L,"blah","attrname", - ObjectName.class.getName(), - new ObjectName(foop+sfoop+"x:y=old"), - new ObjectName(foop+sfoop+"x:y=new")), - new BandicootAttributeChangeNotification( - new ObjectName(barp+sfoop+"x:y=z"),1L,2L,"blah","attrname", - ObjectName.class.getName(), - new ObjectName(barp+sfoop+"x:y=old"), - new ObjectName(barp+sfoop+"x:y=new")), - }, - { - new BandicootAttributeChangeNotification( - new ObjectName("//"+foop+sfoop+"x:y=z"),1L,2L,"blah","attrname", - ObjectName.class.getName(), - new ObjectName("//"+foop+sfoop+"x:y=old"), - new ObjectName(foop+sfoop+"x:y=new")), - new BandicootAttributeChangeNotification( - new ObjectName("//"+foop+sfoop+"x:y=z"),1L,2L,"blah","attrname", - ObjectName.class.getName(), - new ObjectName("//"+foop+sfoop+"x:y=old"), - new ObjectName(barp+sfoop+"x:y=new")), - } - }; - - // List that will merge datas & objects & datas converted to open - // types... - // - final List list = new ArrayList(); - - // Add all objects... - // - list.addAll(Arrays.asList(objects)); - - // Build Map with datas[i][0] (cfoo) - // - for (int i=0;i to TabularData - // (foo things) - final Object cfoo = treats.getAttribute("All"); - final AttributeList afoo = treats.getAttributes(new String[] {"All"}); - - // Build Map with datas[i][1] (cbar) - // - for (int i=0;i to TabularData - // (bar things) - final Object cbar = treats.getAttribute("All"); - final AttributeList abar = treats.getAttributes(new String[] {"All"}); - - // Add all datas to list - for (int i=0;i unmapped = new HashSet(); - final static Set mapped = new HashSet(); - - /** - * For each method define in one of the interfaces intf, tries - * to find a corresponding method in the reference class ref, where - * the method in ref has the same name, and takes an additional - * ObjectName as first parameter. - * - * So for instance, if ref is MBeanServer and intf is {DynamicMBean} - * the result map is: - * DynamicMBean.getAttribute -> MBeanServer.getAttribute - * DynamicMBean.setAttribute -> MBeanServer.setAttribute - * etc... - * If a method was mapped, it is additionally added to 'mapped' - * If a method couldn't be mapped, it is added to 'unmmapped'. - * In our example above, DynamicMBean.getNotificationInfo will end - * up in 'unmapped'. - * - * @param ref The reference class - to which calls will be forwarded - * with an additional ObjectName parameter inserted. - * @param intf The proxy interface classes - for which we must find an - * equivalent in 'ref' - * @return A map mapping the methods from intfs to the method of ref. - */ - static Map makeMapFor(Class ref, Class... intf) { - final Map map = new HashMap(); - for (Class clazz : intf) { - for (Method m : clazz.getMethods()) { - try { - final Method m2 = - ref.getMethod(m.getName(), - concat(ObjectName.class,m.getParameterTypes())); - map.put(m,m2); - mapped.add(m); - } catch (Exception x) { - unmapped.add(m); - } - } - } - return map; - } - - /** - * Tries to map all methods from DynamicMBean.class and - * NotificationEmitter.class to their equivalent in MBeanServer. - * This should be all the methods except - * DynamicMBean.getNotificationInfo. - */ - static final Map mbeanmap = - makeMapFor(MBeanServer.class,DynamicMBean.class, - NotificationEmitter.class); - /** - * Tries to map all methods from DynamicMBean.class and - * NotificationEmitter.class to an equivalent in DynamicWrapper. - * This time only DynamicMBean.getNotificationInfo will be mapped. - */ - static final Map selfmap = - makeMapFor(DynamicWrapper.class,DynamicMBean.class, - NotificationEmitter.class); - - /** - * Now check that we have mapped all methods. - */ - static { - unmapped.removeAll(mapped); - if (unmapped.size() > 0) - throw new ExceptionInInitializerError("Couldn't map "+ unmapped); - } - - /** - * The wrapped MBeanServer to which everything is delegated. - */ - private final MBeanServer server; - - /** - * The name of the MBean we're proxying. - */ - private final ObjectName name; - DynamicWrapper(MBeanServer server, ObjectName name) { - this.server=server; - this.name=name; - } - - /** - * Creates a new proxy for the given MBean. Implements - * NotificationEmitter/NotificationBroadcaster if the proxied - * MBean also does. - * @param name the name of the proxied MBean - * @param server the wrapped server - * @return a DynamicMBean proxy - * @throws javax.management.InstanceNotFoundException - */ - public static DynamicMBean newProxy(ObjectName name, MBeanServer server) - throws InstanceNotFoundException { - if (server.isInstanceOf(name, - NotificationEmitter.class.getName())) { - // implements NotificationEmitter - return (DynamicMBean) - Proxy.newProxyInstance( - DynamicWrapper.class.getClassLoader(), - new Class[] {NotificationEmitter.class, - DynamicMBean.class}, - new DynamicWrapper(server, name)); - } - if (server.isInstanceOf(name, - NotificationBroadcaster.class.getName())) { - // implements NotificationBroadcaster - return (DynamicMBean) - Proxy.newProxyInstance( - DynamicWrapper.class.getClassLoader(), - new Class[] {NotificationBroadcaster.class, - DynamicMBean.class}, - new DynamicWrapper(server, name)); - } - // Only implements DynamicMBean. - return (DynamicMBean) - Proxy.newProxyInstance( - DynamicWrapper.class.getClassLoader(), - new Class[] {DynamicMBean.class}, - new DynamicWrapper(server, name)); - } - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - // Look for a method on this class (takes precedence) - final Method self = selfmap.get(method); - if (self != null) - return call(this,self,concat(name,args)); - - // no method found on this class, look for the same method - // on the wrapped MBeanServer - final Method mbean = mbeanmap.get(method); - if (mbean != null) - return call(server,mbean,concat(name,args)); - - // This isn't a method that can be forwarded to MBeanServer. - // If it's a method from Object, call it on this. - if (method.getDeclaringClass().equals(Object.class)) - return call(this,method,args); - throw new NoSuchMethodException(method.getName()); - } - - // Call a method using reflection, unwraps invocation target exceptions - public Object call(Object handle, Method m, Object[] args) - throws Throwable { - try { - return m.invoke(handle, args); - } catch (InvocationTargetException x) { - throw x.getCause(); - } - } - - // this method is called when DynamicMBean.getNotificationInfo() is - // called. This is the method that should be mapped in - // 'selfmap' - public MBeanNotificationInfo[] getNotificationInfo(ObjectName name) - throws JMException { - return server.getMBeanInfo(name).getNotifications(); - } - } - - /** - * Just so that we can call the same test twice but with two - * different implementations of VirtualMBeanServerSupport. - */ - public static interface MBeanServerWrapperFactory { - public MBeanServer wrapMBeanServer(MBeanServer wrapped); - } - - /** - * A VirtualMBeanServerSupport that wrapps an MBeanServer and does not - * use VirtualEventManager. - */ - public static class VirtualMBeanServerTest - extends MBeanServerSupport { - - final MBeanServer wrapped; - - public VirtualMBeanServerTest(MBeanServer wrapped) { - this.wrapped=wrapped; - } - - @Override - public DynamicMBean getDynamicMBeanFor(final ObjectName name) - throws InstanceNotFoundException { - if (wrapped.isRegistered(name)) - return DynamicWrapper.newProxy(name,wrapped); - throw new InstanceNotFoundException(String.valueOf(name)); - } - - @Override - protected Set getNames() { - return wrapped.queryNames(null, null); - } - - public final static MBeanServerWrapperFactory factory = - new MBeanServerWrapperFactory() { - - public MBeanServer wrapMBeanServer(MBeanServer wrapped) { - return new VirtualMBeanServerTest(wrapped); - } - @Override - public String toString() { - return VirtualMBeanServerTest.class.getName(); - } - }; - } - - /** - * A VirtualMBeanServerSupport that wrapps an MBeanServer and - * uses a VirtualEventManager. - */ - public static class VirtualMBeanServerTest2 - extends VirtualMBeanServerTest { - - final EventSubscriber sub; - final NotificationListener nl; - final VirtualEventManager mgr; - - /** - * We use an EventSubscriber to subscribe for all notifications from - * the wrapped MBeanServer, and publish them through a - * VirtualEventManager. Not a very efficient way of doing things. - * @param wrapped - */ - public VirtualMBeanServerTest2(MBeanServer wrapped) { - super(wrapped); - this.sub = EventSubscriber.getEventSubscriber(wrapped); - this.mgr = new VirtualEventManager(); - this.nl = new NotificationListener() { - public void handleNotification(Notification notification, Object handback) { - mgr.publish((ObjectName)notification.getSource(), notification); - } - }; - try { - sub.subscribe(ObjectName.WILDCARD, nl, null, null); - } catch (RuntimeException x) { - throw x; - } catch (Exception x) { - throw new IllegalStateException("can't subscribe for notifications!"); - } - } - - @Override - public NotificationEmitter - getNotificationEmitterFor(ObjectName name) - throws InstanceNotFoundException { - final DynamicMBean mbean = getDynamicMBeanFor(name); - if (mbean instanceof NotificationEmitter) - return mgr.getNotificationEmitterFor(name); - return null; - } - - public final static MBeanServerWrapperFactory factory = - new MBeanServerWrapperFactory() { - - public MBeanServer wrapMBeanServer(MBeanServer wrapped) { - return new VirtualMBeanServerTest2(wrapped); - } - @Override - public String toString() { - return VirtualMBeanServerTest2.class.getName(); - } - }; - } - - - public static void test(MBeanServerWrapperFactory factory) throws Exception { - final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - - // names[] are NotificationEmitters - final ObjectName[] emitters = new ObjectName[2]; - // shields[] have been shielded by wrapping them in a StandardMBean, - // so although the resource is an MBean that implements - // NotificationEmitter, the registered MBean (the wrapper) doesn't. - final ObjectName[] shielded = new ObjectName[2]; - - final List registered = new ArrayList(4); - - try { - // register two MBeans before wrapping - server.registerMBean(new Wombat(), - emitters[0] = new ObjectName("bush:type=Wombat,name=wom")); - registered.add(emitters[0]); - - // we shield the second MBean in a StandardMBean so that it does - // not appear as a NotificationEmitter. - server.registerMBean( - new StandardMBean(new Wombat(), WombatMBean.class), - shielded[0] = new ObjectName("bush:type=Wombat,name=womshield")); - registered.add(shielded[0]); - - final MBeanServer vserver = factory.wrapMBeanServer(server); - - // register two other MBeans after wrapping - server.registerMBean(new Wombat(), - emitters[1] = new ObjectName("bush:type=Wombat,name=bat")); - registered.add(emitters[1]); - - // we shield the second MBean in a StandardMBean so that it does - // not appear as a NotificationEmitter. - server.registerMBean( - new StandardMBean(new Wombat(), WombatMBean.class), - shielded[1] = new ObjectName("bush:type=Wombat,name=batshield")); - registered.add(shielded[1]); - - // Call test with this config - we have two wombats who broadcast - // notifs (emitters) and two wombats who don't (shielded). - test(vserver, emitters, shielded); - - System.out.println("*** Test passed for: " + factory); - } finally { - // Clean up the platform mbean server for the next test... - for (ObjectName n : registered) { - try { - server.unregisterMBean(n); - } catch (Exception x) { - x.printStackTrace(); - } - } - } - } - - /** - * Perform the actual test. - * @param vserver A virtual MBeanServerSupport implementation - * @param emitters Names of NotificationBroadcaster MBeans - * @param shielded Names of non NotificationBroadcaster MBeans - * @throws java.lang.Exception - */ - public static void test(MBeanServer vserver, ObjectName[] emitters, - ObjectName[] shielded) throws Exception { - - // To catch exception in NotificationListener - final List fail = new CopyOnWriteArrayList(); - - // A queue of received notifications - final BlockingQueue notifs = - new ArrayBlockingQueue(50); - - // A notification listener that puts the notification it receives - // in the queue. - final NotificationListener handler = new NotificationListener() { - - public void handleNotification(Notification notification, - Object handback) { - try { - notifs.put(notification); - } catch (Exception x) { - fail.add(x); - } - } - }; - - // A list of attribute names for which we might receive an - // exception. If an exception is received when getting these - // attributes - the test will not fail. - final List exceptions = Arrays.asList( new String[] { - "UsageThresholdCount","UsageThreshold","UsageThresholdExceeded", - "CollectionUsageThresholdCount","CollectionUsageThreshold", - "CollectionUsageThresholdExceeded" - }); - - // This is just a sanity check. Get all attributes of all MBeans. - for (ObjectName n : vserver.queryNames(null, null)) { - final MBeanInfo m = vserver.getMBeanInfo(n); - for (MBeanAttributeInfo mba : m.getAttributes()) { - // System.out.println(n+":"); - Object val; - try { - val = vserver.getAttribute(n, mba.getName()); - } catch (Exception x) { - // only accept exception for those attributes that - // have a valid reason to fail... - if (exceptions.contains(mba.getName())) val = x; - else throw new Exception("Failed to get " + - mba.getName() + " from " + n,x); - } - // System.out.println("\t "+mba.getName()+": "+ val); - } - } - - // The actual tests. Register for notifications with notif emitters - for (ObjectName n : emitters) { - vserver.addNotificationListener(n, handler, null, n); - } - - // Trigger the emission of notifications, check that we received them. - for (ObjectName n : emitters) { - vserver.setAttribute(n, - new Attribute("Caption","I am a new wombat!")); - final Notification notif = notifs.poll(4, TimeUnit.SECONDS); - if (!notif.getSource().equals(n)) - throw new Exception("Bad source for "+ notif); - if (fail.size() > 0) - throw new Exception("Failed to handle notif",fail.remove(0)); - } - - // Check that we didn't get more notifs than expected - if (notifs.size() > 0) - throw new Exception("Extra notifications in queue: "+notifs); - - // Check that if the MBean doesn't exist, we get InstanceNotFound. - try { - vserver.addNotificationListener(new ObjectName("toto:toto=toto"), - handler, null, null); - throw new Exception("toto:toto=toto doesn't throw INFE"); - } catch (InstanceNotFoundException x) { - System.out.println("Received "+x+" as expected."); - } - - // For those MBeans that shouldn't be NotificationEmitters, check that - // we get IllegalArgumentException - for (ObjectName n : shielded) { - try { - vserver.addNotificationListener(n, handler, null, n); - } catch (RuntimeOperationsException x) { - System.out.println("Received "+x+" as expected."); - System.out.println("Cause is: "+x.getCause()); - if (!(x.getCause() instanceof IllegalArgumentException)) - throw new Exception("was expecting IllegalArgumentException cause. Got "+x.getCause(),x); - } - } - - // Sanity check. Remove our listeners. - for (ObjectName n : emitters) { - vserver.removeNotificationListener(n, handler, null, n); - } - - // That's it. - // Sanity check: we shouldn't have received any new notif. - if (notifs.size() > 0) - throw new Exception("Extra notifications in queue: "+notifs); - // The NotifListener shouldn't have logged any new exception. - if (fail.size() > 0) - throw new Exception("Failed to handle notif",fail.remove(0)); - } - - public static void main(String[] args) throws Exception { - // test with a regular MBeanServer (no VirtualMBeanServerSupport) - final MBeanServerWrapperFactory identity = - new MBeanServerWrapperFactory() { - public MBeanServer wrapMBeanServer(MBeanServer wrapped) { - return wrapped; - } - }; - test(identity); - // test with no EventManager - test(VirtualMBeanServerTest.factory); - // test with VirtualEventManager - test(VirtualMBeanServerTest2.factory); - } -} diff --git a/test/javax/management/namespace/VirtualMBeanTest.java b/test/javax/management/namespace/VirtualMBeanTest.java deleted file mode 100644 index 03fd3983e..000000000 --- a/test/javax/management/namespace/VirtualMBeanTest.java +++ /dev/null @@ -1,409 +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. - * - * 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. - */ - -/* - * @test VirtualMBeanTest.java - * @bug 5108776 5072476 - * @summary Test that Virtual MBeans can be implemented and emit notifs. - * @author Eamonn McManus - */ - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.MBeanInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.MalformedObjectNameException; -import javax.management.Notification; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.SendNotification; -import javax.management.StandardEmitterMBean; -import javax.management.StandardMBean; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.VirtualEventManager; -import javax.management.namespace.MBeanServerSupport; -import javax.management.timer.TimerMBean; - -// In this test, we check that the two main use case types for -// MBeanServerSupport work correctly: -// (1) as a special-purpose implementation of MBeanServer for a fixed number -// of MBeans (e.g. for QueryNotificationFilter) -// (2) as an MBeanServer supporting Virtual MBeans. -// In each case we are particularly interested in the notification behaviour. -// We check that the behaviour is correct when calling addNotificationListener -// (a) for an MBean that does not exist; (b) for an MBean that does exist but -// is not a NotificationEmitter; and (c) for an MBean that exists and is -// a NotificationEmitter. We also check the degenerate and usual case -// where the MBeanServerSupport subclass does not support notifications -// at all. -// -// Each subclass will have an MBean called test:type=NotEmitter that -// does not support addNotificationListener. If it also has MBeans called -// test:type=Emitter,* then they are expected to support addNL. No subclass -// will have any other MBeans, so in particular no subclass will have -// test:type=Nonexistent. -// -public class VirtualMBeanTest { - static final ObjectName - nonExistentName, notEmitterName, emitterName1, emitterName2; - static { - try { - nonExistentName = new ObjectName("test:type=NonExistent"); - notEmitterName = new ObjectName("test:type=NotEmitter"); - emitterName1 = new ObjectName("test:type=Emitter,id=1"); - emitterName2 = new ObjectName("test:type=Emitter,id=2"); - } catch (MalformedObjectNameException e) { - throw new AssertionError(e); - } - } - - static final StandardMBean.Options wrappedVisible = new StandardMBean.Options(); - static { - wrappedVisible.setWrappedObjectVisible(true); - } - - public static interface NothingMBean {} - public static class Nothing implements NothingMBean {} - public static class NothingNBS extends NotificationBroadcasterSupport - implements NothingMBean {} - - // Class that has hardwired MBeans test:type=NotEmitter, - // test:type=Broadcaster, and test:type=Emitter. - private static class HardwiredMBS extends MBeanServerSupport - implements SendNotification { - private final DynamicMBean notEmitter = - new StandardMBean(new Nothing(), NothingMBean.class, wrappedVisible); - private final StandardEmitterMBean emitter1, emitter2; - { - NothingNBS nnbs1 = new NothingNBS(); - emitter1 = new StandardEmitterMBean( - nnbs1, NothingMBean.class, wrappedVisible, nnbs1); - NothingNBS nnbs2 = new NothingNBS(); - emitter2 = new StandardEmitterMBean( - nnbs2, NothingMBean.class, wrappedVisible, nnbs2); - } - - private final Map map = - new TreeMap(); - { - map.put(notEmitterName, notEmitter); - map.put(emitterName1, emitter1); - map.put(emitterName2, emitter2); - } - - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - DynamicMBean mbean = map.get(name); - if (mbean != null) - return mbean; - else - throw new InstanceNotFoundException(name); - } - - @Override - protected Set getNames() { - return map.keySet(); - } - - @Override - public String toString() { - return "Hardwired MBeanServerSupport"; - } - - public void sendNotification(Notification notification) { - emitter1.sendNotification(notification); - emitter2.sendNotification(notification); - } - } - - // Class that has the notEmitter MBean but not either of the others, so does - // not support listeners. - private static class VirtualMBSWithoutListeners - extends MBeanServerSupport { - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (name.equals(notEmitterName)) { - return new StandardMBean( - new Nothing(), NothingMBean.class, wrappedVisible); - } else - throw new InstanceNotFoundException(name); - } - - @Override - protected Set getNames() { - return Collections.singleton(notEmitterName); - } - - @Override - public String toString() { - return "Virtual MBeanServerSupport without listener support"; - } - } - - // Class that has the notEmitter and emitter MBeans as Virtual MBeans, using - // VirtualEventManager to handle listeners for the emitter MBean. We - // implement the broadcaster MBean (which is a NotificationBroadcaster but - // not a NotificationEmitter) even though it's very hard to imagine a real - // use case where that would happen. - private static class VirtualMBSWithListeners - extends MBeanServerSupport implements SendNotification { - private final VirtualEventManager vem = new VirtualEventManager(); - - private static final List names = - Arrays.asList(notEmitterName, emitterName1, emitterName2); - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (names.contains(name)) { - return new StandardMBean( - new Nothing(), NothingMBean.class, wrappedVisible); - } else - throw new InstanceNotFoundException(name); - } - - @Override - public NotificationEmitter getNotificationEmitterFor( - ObjectName name) throws InstanceNotFoundException { - if (name.equals(emitterName1) || name.equals(emitterName2)) - return vem.getNotificationEmitterFor(name); - else if (name.equals(notEmitterName)) - return null; - else - throw new InstanceNotFoundException(name); - } - - @Override - protected Set getNames() { - return new TreeSet(Arrays.asList(notEmitterName, emitterName2)); - } - - @Override - public String toString() { - return "Virtual MBeanServerSupport with listener support"; - } - - public void sendNotification(Notification notification) { - vem.publish(emitterName1, notification); - vem.publish(emitterName2, notification); - } - } - - private static final MBeanServer[] vmbsss = { - new HardwiredMBS(), - new VirtualMBSWithoutListeners(), - new VirtualMBSWithListeners(), - }; - - public static void main(String[] args) throws Exception { - Exception lastEx = null; - for (MBeanServer vmbs : vmbsss) { - String testName = "\"" + vmbs + "\""; - System.out.println("===Test " + testName + "==="); - try { - test(vmbs); - } catch (Exception e) { - System.out.println( - "===Test " + testName + " failed with exception " + e); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - pw.flush(); - String es = sw.toString(); - System.out.println("......" + es.replace("\n", "\n......")); - lastEx = e; - } - } - if (lastEx != null) - throw lastEx; - System.out.println("TEST PASSED"); - } - - private static class NothingListener implements NotificationListener { - public void handleNotification(Notification notification, - Object handback) { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - private static class QueueListener implements NotificationListener { - final BlockingQueue queue = - new ArrayBlockingQueue(10); - - public void handleNotification(Notification notification, - Object handback) { - queue.add(notification); - } - } - - private static void test(MBeanServer vmbs) throws Exception { - MBeanServer mmbs = MBeanServerFactory.newMBeanServer(); - ObjectName namespaceName = new ObjectName("test//:type=JMXNamespace"); - JMXNamespace namespace = new JMXNamespace(vmbs); - mmbs.registerMBean(namespace, namespaceName); - MBeanServer mbs = JMXNamespaces.narrowToNamespace(mmbs, "test"); - - Set names = mbs.queryNames(null, null); - //names.remove(new ObjectName(":type=JMXNamespace")); - - // Make sure that notEmitterName exists according to query... - System.out.println("Checking query"); - if (!names.contains(notEmitterName)) - throw new Exception("Bad query result: " + names); - - // ...and according to getMBeanInfo - System.out.println("Checking getMBeanInfo(" + notEmitterName + ")"); - MBeanInfo mbi = mbs.getMBeanInfo(notEmitterName); - if (mbi.getNotifications().length > 0) - throw new Exception("notEmitter has NotificationInfo"); - - // Make sure we get the right exception for getMBeanInfo on a - // non-existent MBean - System.out.println("Checking getMBeanInfo on a non-existent MBean"); - try { - mbi = mbs.getMBeanInfo(nonExistentName); - throw new Exception("getMBI succeeded but should not have"); - } catch (InstanceNotFoundException e) { - } - - // Make sure we get the right exception for addNotificationListener on a - // non-existent MBean - System.out.println( - "Checking addNotificationListener on a non-existent MBean"); - try { - mbs.addNotificationListener( - nonExistentName, new NothingListener(), null, null); - throw new Exception("addNL succeeded but should not have"); - } catch (InstanceNotFoundException e) { - } - - // Make sure we get the right exception for isInstanceOf on a - // non-existent MBean - System.out.println( - "Checking isInstanceOf on a non-existent MBean"); - for (Class c : new Class[] { - Object.class, NotificationBroadcaster.class, NotificationEmitter.class, - }) { - try { - boolean is = mbs.isInstanceOf(nonExistentName, c.getName()); - throw new Exception( - "isInstanceOf " + c.getName() + - " succeeded but should not have"); - } catch (InstanceNotFoundException e) { - } - } - - // Make sure isInstanceOf works correctly for classes without special - // treatment - System.out.println( - "Checking isInstanceOf on normal classes"); - for (ObjectName name : names) { - boolean isNothing = mbs.isInstanceOf(name, NothingMBean.class.getName()); - if (!isNothing) { - throw new Exception("isInstanceOf " + NothingMBean.class.getName() + - " returned false, should be true"); - } - boolean isTimer = mbs.isInstanceOf(name, TimerMBean.class.getName()); - if (isTimer) { - throw new Exception("isInstanceOf " + TimerMBean.class.getName() + - " returned true, should be false"); - } - } - - // Make sure that addNL on notEmitterName gets the right exception - System.out.println("Checking addNL on non-broadcaster"); - try { - mbs.addNotificationListener( - notEmitterName, new NothingListener(), null, null); - throw new Exception("addNL succeeded but should not have"); - } catch (RuntimeOperationsException e) { - if (!(e.getCause() instanceof IllegalArgumentException)) - throw new Exception("Wrong exception from addNL", e); - } - - if (!(vmbs instanceof SendNotification)) { - System.out.println("Not testing notifications for this implementation"); - return; - } - - QueueListener qListener = new QueueListener(); - - System.out.println("Testing addNL on emitters"); - mbs.addNotificationListener(emitterName1, qListener, null, null); - mbs.addNotificationListener(emitterName2, qListener, null, null); - - System.out.println("Testing that listeners work"); - Notification notif = new Notification("notif.type", "source", 0L); - - ((SendNotification) vmbs).sendNotification(notif); - testListeners(qListener, "notif.type", 2); - - System.out.println("Testing 2-arg removeNL on emitter1"); - mbs.removeNotificationListener(emitterName1, qListener); - - ((SendNotification) vmbs).sendNotification(notif); - testListeners(qListener, "notif.type", 1); - - System.out.println("Testing 4-arg removeNL on emitter2"); - mbs.removeNotificationListener(emitterName2, qListener, null, null); - - ((SendNotification) vmbs).sendNotification(notif); - testListeners(qListener, "notif.type", 0); - } - - private static void testListeners( - QueueListener qListener, String expectedNotifType, int expectedNotifs) - throws Exception { - for (int i = 1; i <= expectedNotifs; i++) { - Notification rNotif = qListener.queue.poll(1, TimeUnit.SECONDS); - if (rNotif == null) - throw new Exception("Notification " + i + " never arrived"); - if (!rNotif.getType().equals(expectedNotifType)) - throw new Exception("Wrong type notif: " + rNotif.getType()); - } - Notification xNotif = qListener.queue.poll(10, TimeUnit.MILLISECONDS); - if (xNotif != null) - throw new Exception("Extra notif: " + xNotif); - } -} diff --git a/test/javax/management/namespace/VirtualNamespaceQueryTest.java b/test/javax/management/namespace/VirtualNamespaceQueryTest.java deleted file mode 100644 index 8af244a7b..000000000 --- a/test/javax/management/namespace/VirtualNamespaceQueryTest.java +++ /dev/null @@ -1,128 +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. - * - * 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. - */ - -/* - * - * @test VirtualNamespaceQueryTest.java - * @summary General VirtualNamespaceQueryTest test. - * @author Daniel Fuchs - * @bug 5072476 - * @run clean VirtualNamespaceQueryTest Wombat WombatMBean - * NamespaceController NamespaceControllerMBean - * JMXRemoteTargetNamespace - * @compile -XDignore.symbol.file=true VirtualNamespaceQueryTest.java - * Wombat.java WombatMBean.java - * NamespaceController.java NamespaceControllerMBean.java - * JMXRemoteTargetNamespace.java - * @run main VirtualNamespaceQueryTest - */ - -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.NotificationEmitter; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.MBeanServerSupport; - -/** - * - * @author dfuchs - */ -public class VirtualNamespaceQueryTest { - public static class WombatRepository extends MBeanServerSupport { - final Wombat wombat; - final StandardMBean mbean; - final ObjectName wombatName; - - public WombatRepository(ObjectName wombatName) { - try { - wombat = new Wombat(); - mbean = wombat; - this.wombatName = wombatName; - wombat.preRegister(null,wombatName); - } catch (Exception x) { - throw new IllegalArgumentException(x); - } - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (wombatName.equals(name)) return mbean; - else throw new InstanceNotFoundException(String.valueOf(name)); - } - - @Override - protected Set getNames() { - final Set res = Collections.singleton(wombatName); - return res; - } - - @Override - public NotificationEmitter getNotificationEmitterFor( - ObjectName name) throws InstanceNotFoundException { - DynamicMBean mb = getDynamicMBeanFor(name); - if (mb instanceof NotificationEmitter) - return (NotificationEmitter)mb; - return null; - } - } - public static class WombatNamespace extends JMXNamespace { - public WombatNamespace(ObjectName wombatName) { - super(new WombatRepository(wombatName)); - } - } - - public static void simpleTest() throws Exception { - final MBeanServer server = MBeanServerFactory.newMBeanServer(); - final ObjectName wombatName = new ObjectName("burrow:type=Wombat"); - final JMXNamespace ns = new WombatNamespace(wombatName); - server.registerMBean(ns, JMXNamespaces.getNamespaceObjectName("wombats")); - final Set dirs = - server.queryNames(new ObjectName("wombats//*//:type=JMXNamespace"), - wombatName); - System.out.println("all dirs: "+dirs); - if (dirs.size()>0) - throw new RuntimeException("Unexpected ObjectNames returned: "+dirs); - - final ObjectInstance inst = NamespaceController.createInstance(server); - final NamespaceControllerMBean controller = - JMX.newMBeanProxy(server, inst.getObjectName(), - NamespaceControllerMBean.class); - final String[] dirNames = controller.findNamespaces(null,null,2); - System.err.println(Arrays.toString(dirNames)); - } - - public static void main(String[] args) throws Exception { - simpleTest(); - } -} diff --git a/test/javax/management/namespace/VirtualPropsTest.java b/test/javax/management/namespace/VirtualPropsTest.java deleted file mode 100644 index 904cc5359..000000000 --- a/test/javax/management/namespace/VirtualPropsTest.java +++ /dev/null @@ -1,179 +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. - * - * 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. - */ - -/* - * @test - * @bug 5108776 5072476 - * @summary Test the properties use case for Virtual MBeans that is documented - * in MBeanServerSupport. - * @author Eamonn McManus - */ - -import java.lang.management.ManagementFactory; -import java.util.Properties; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.TimeUnit; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MalformedObjectNameException; -import javax.management.Notification; -import javax.management.NotificationEmitter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.StandardMBean; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.VirtualEventManager; -import javax.management.namespace.MBeanServerSupport; - -public class VirtualPropsTest { - public static interface PropertyMBean { - public String getValue(); - } - - public static class PropsMBS extends MBeanServerSupport { - private static ObjectName newObjectName(String name) { - try { - return new ObjectName(name); - } catch (MalformedObjectNameException e) { - throw new AssertionError(e); - } - } - - public static class PropertyImpl implements PropertyMBean { - private final String name; - - public PropertyImpl(String name) { - this.name = name; - } - - public String getValue() { - return System.getProperty(name); - } - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - ObjectName namePattern = newObjectName( - "com.example:type=Property,name=\"*\""); - if (!namePattern.apply(name)) - throw new InstanceNotFoundException(name); - - String propName = ObjectName.unquote(name.getKeyProperty("name")); - if (System.getProperty(propName) == null) - throw new InstanceNotFoundException(name); - PropertyMBean propMBean = new PropertyImpl(propName); - return new StandardMBean(propMBean, PropertyMBean.class, false); - } - - @Override - protected Set getNames() { - Set names = new TreeSet(); - Properties props = System.getProperties(); - for (String propName : props.stringPropertyNames()) { - ObjectName objectName = newObjectName( - "com.example:type=Property,name=" + - ObjectName.quote(propName)); - names.add(objectName); - } - return names; - } - - private final VirtualEventManager vem = new VirtualEventManager(); - - @Override - public NotificationEmitter getNotificationEmitterFor( - ObjectName name) throws InstanceNotFoundException { - getDynamicMBeanFor(name); // check that the name is valid - return vem.getNotificationEmitterFor(name); - } - - public void propertyChanged(String name, String newValue) { - ObjectName objectName = newObjectName( - "com.example:type=Property,name=" + ObjectName.quote(name)); - Notification n = new Notification( - "com.example.property.changed", objectName, 0L, - "Property " + name + " changed"); - n.setUserData(newValue); - vem.publish(objectName, n); - } - } - - static class QueueListener implements NotificationListener { - BlockingQueue q = new ArrayBlockingQueue(10); - public void handleNotification(Notification notification, - Object handback) { - q.add(notification); - } - } - - public static void main(String[] args) throws Exception { - MBeanServer mmbs = ManagementFactory.getPlatformMBeanServer(); - String namespace = "props"; - PropsMBS pmbs = new PropsMBS(); - Object namespaceMBean = new JMXNamespace(pmbs); - mmbs.registerMBean(namespaceMBean, new ObjectName( - namespace + "//:type=JMXNamespace")); - MBeanServer mbs = JMXNamespaces.narrowToNamespace(mmbs, namespace); - - Properties props = System.getProperties(); - - int nprops = props.stringPropertyNames().size(); - if (nprops != mbs.getMBeanCount()) { - throw new Exception(String.format("Properties: %d; MBeans: %d", - nprops, mbs.getMBeanCount())); - } - - for (String propName : props.stringPropertyNames()) { - ObjectName propObjectName = new ObjectName( - "com.example:type=Property,name=" + ObjectName.quote(propName)); - PropertyMBean propProx = JMX.newMBeanProxy( - mbs, propObjectName, PropertyMBean.class); - String propValue = propProx.getValue(); - String realPropValue = props.getProperty(propName); - if (!realPropValue.equals(propValue)) { - throw new Exception(String.format("Property %s: value is \"%s\"; " + - "mbean says \"%s\"", propName, realPropValue, propValue)); - } - } - - ObjectName fooPropObjectName = - new ObjectName("com.example:type=Property,name=\"java.home\""); - QueueListener ql = new QueueListener(); - mbs.addNotificationListener(fooPropObjectName, ql, null, null); - pmbs.propertyChanged("java.home", "bar"); - Notification n = ql.q.poll(1, TimeUnit.SECONDS); - if (n == null) - throw new Exception("Notif didn't arrive"); - if (!"bar".equals(n.getUserData())) - throw new Exception("Bad user data: " + n.getUserData()); - - System.out.println("TEST PASSED"); - } -} diff --git a/test/javax/management/namespace/Wombat.java b/test/javax/management/namespace/Wombat.java deleted file mode 100644 index bef648c0f..000000000 --- a/test/javax/management/namespace/Wombat.java +++ /dev/null @@ -1,259 +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. - * - * 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. - */ - -import java.util.Random; -import java.util.Set; -import javax.management.AttributeChangeNotification; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.MBeanRegistration; -import javax.management.MBeanServer; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.StandardMBean; - - -/** - * Dynamic MBean based on StandardMBean - * Class Wombat - * Wombat Description - * @author dfuchs - */ -public class Wombat extends StandardMBean - implements WombatMBean, NotificationEmitter, MBeanRegistration { - - /** - * Attribute : Caption - */ - private String caption = "I'm a wombat"; - - private final long MAX_SEED = 36000; - private final long seed; - private final long period; - private volatile int mood = 0; - - public int getMood() { - final long degree = seed + (System.currentTimeMillis()/period)%MAX_SEED; - final double angle = ((double)degree)/100; - mood = (int)(100.0*Math.sin(angle)); - return mood; - } - - public Wombat() throws NotCompliantMBeanException { - this(WombatMBean.class); - } - - public Wombat(Class clazz) - throws NotCompliantMBeanException { - super(clazz); - final Random r = new Random(); - seed = ((r.nextLong() % MAX_SEED) + MAX_SEED)%MAX_SEED; - period = 200 + (((r.nextLong()%80)+80)%80)*10; - } - - /** - * Next are the methods to compute MBeanInfo. - * You shouldn't update these methods. - */ - @Override - protected String getDescription(MBeanInfo info) { - return "Wombats are strange beasts. You will find them down under " + - "and in some computer programms."; - } - - @Override - protected String getDescription(MBeanAttributeInfo info) { - String description = null; - if (info.getName().equals("Caption")) { - description = "A simple caption to describe a wombat"; - } - if (info.getName().equals("Mood")) { - description = "This Wombat's mood on a [-100,+100] scale."+ - " -100 means that this wombat is very angry."; - } - return description; - } - - @Override - protected String getDescription(MBeanOperationInfo op, - MBeanParameterInfo param, - int sequence) { - return null; - } - - @Override - protected String getParameterName(MBeanOperationInfo op, - MBeanParameterInfo param, - int sequence) { - return null; - } - - @Override - protected String getDescription(MBeanOperationInfo info) { - String description = null; - return description; - } - - @Override - public MBeanInfo getMBeanInfo() { - MBeanInfo mbinfo = super.getMBeanInfo(); - return new MBeanInfo(mbinfo.getClassName(), - mbinfo.getDescription(), - mbinfo.getAttributes(), - mbinfo.getConstructors(), - mbinfo.getOperations(), - getNotificationInfo()); - } - - /** - * Get A simple caption to describe a wombat - */ - public synchronized String getCaption() { - return caption; - } - - /** - * Set A simple caption to describe a wombat - */ - public void setCaption(String value) { - final String oldValue; - synchronized (this) { - oldValue = caption; - caption = value; - } - final AttributeChangeNotification notif = - new AttributeChangeNotification(objectName, - getNextSeqNumber(), - System.currentTimeMillis(), - "Caption changed","Caption", - String.class.getName(),oldValue,value); - broadcaster.sendNotification(notif); - } - - /** - * MBeanNotification support - * You shouldn't update these methods - */ - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { - broadcaster.addNotificationListener(listener, filter, handback); - } - - public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[] { - new MBeanNotificationInfo(new String[] { - AttributeChangeNotification.ATTRIBUTE_CHANGE}, - javax.management.AttributeChangeNotification.class.getName(), - "Sent when the caption changes") - }; - } - - public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { - broadcaster.removeNotificationListener(listener); - } - - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { - broadcaster.removeNotificationListener(listener, filter, handback); - } - - private synchronized long getNextSeqNumber() { - return seqNumber++; - } - - private long seqNumber; - - private final NotificationBroadcasterSupport broadcaster = new NotificationBroadcasterSupport(); - - /** - * Allows the MBean to perform any operations it needs before being - * registered in the MBean server. If the name of the MBean is not - * specified, the MBean can provide a name for its registration. If - * any exception is raised, the MBean will not be registered in the - * MBean server. - * @param server The MBean server in which the MBean will be registered. - * @param name The object name of the MBean. This name is null if the - * name parameter to one of the createMBean or registerMBean methods in - * the MBeanServer interface is null. In that case, this method must - * return a non-null ObjectName for the new MBean. - * @return The name under which the MBean is to be registered. This value - * must not be null. If the name parameter is not null, it will usually - * but not necessarily be the returned value. - * @throws Exception This exception will be caught by the MBean server and - * re-thrown as an MBeanRegistrationException. - */ - @Override - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - objectName = name; - mbeanServer = server; - return super.preRegister(server, name); - } - - /** - * Allows the MBean to perform any operations needed after having - * been registered in the MBean server or after the registration has - * failed. - * @param registrationDone Indicates wether or not the MBean has been - * successfully registered in the MBean server. The value false means - * that the registration has failed. - */ - @Override - public void postRegister(Boolean registrationDone) { - super.postRegister(registrationDone); - } - - /** - * Allows the MBean to perform any operations it needs before being - * unregistered by the MBean server. - * @throws Exception This exception will be caught by the MBean server and - * re-thrown as an MBeanRegistrationException. - */ - @Override - public void preDeregister() throws Exception { - super.preDeregister(); - } - - /** - * Allows the MBean to perform any operations needed after having been - * unregistered in the MBean server. - */ - @Override - public void postDeregister() { - super.postDeregister(); - } - - public Set listMatching(ObjectName pattern) { - return mbeanServer.queryNames(pattern, null); - } - - private MBeanServer mbeanServer; - - private ObjectName objectName; -} diff --git a/test/javax/management/namespace/WombatMBean.java b/test/javax/management/namespace/WombatMBean.java deleted file mode 100644 index 73f487531..000000000 --- a/test/javax/management/namespace/WombatMBean.java +++ /dev/null @@ -1,59 +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. - * - * 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. - */ - -import java.util.Set; -import javax.management.ObjectName; - -/** - * Interface WombatMBean - * Wombat Description - * @author dfuchs - */ -public interface WombatMBean -{ - /** - * This Wombat's mood on a [-100,+100] scale. - * -100 means that this wombat is very angry. - * @return The wombat's mood. - */ - public int getMood(); - - /** - * Get A simple caption to describe a wombat - */ - public String getCaption(); - - /** - * Set A simple caption to describe a wombat - */ - public void setCaption(String value); - - /** - * List matching MBeans in the same server. - * @param pattern an ObjectName pattern or null. - * @return A list of matching MBeans. - */ - public Set listMatching(ObjectName pattern); - -} diff --git a/test/javax/management/namespace/namespace.policy b/test/javax/management/namespace/namespace.policy deleted file mode 100644 index e77bb79c9..000000000 --- a/test/javax/management/namespace/namespace.policy +++ /dev/null @@ -1,85 +0,0 @@ -grant codebase "file:/-" { - permission java.util.PropertyPermission "jmx.wait", "read"; - permission java.util.PropertyPermission "jmx.rmi.port", "read"; - permission java.net.SocketPermission "*", "accept,connect,resolve"; - permission java.security.SecurityPermission "*"; - - // Attribute Caption: allow get everywhere - // ================== - - // allow getAttribute(*:*,Caption) in all MBeanServers - permission javax.management.MBeanPermission "#Caption", "getAttribute"; - // allow getAttribute(*:*,Caption) in all namespaces recursively. - permission javax.management.namespace.JMXNamespacePermission "Caption", - "getAttribute"; - - // Attribute Mood: allow get only in MBeanServers named rmi* - // =============== - - // allow to get attribute Mood of Wombat MBeans only in namespaces - // whose name match rmi*, wherever they are. - // for this we need two permissions: - permission javax.management.namespace.JMXNamespacePermission - "*::Mood[**//rmi*//wombat:*]", - "getAttribute"; - permission javax.management.namespace.JMXNamespacePermission - "*::Mood[rmi*//wombat:*]", - "getAttribute"; - - // allow to get attribute mood in any MBeanServer whose name starts with - // rmi - permission javax.management.MBeanPermission "rmi*::#Mood", - "getAttribute"; - - // Attribute UUID: - // =============== - - // allow to get attribute "UUID" everywhere. - permission javax.management.namespace.JMXNamespacePermission - "*::UUID[*//**//:*]", - "getAttribute"; - permission javax.management.MBeanPermission - "#UUID[*//:*]", - "getAttribute"; - - - - // Let getMBeanInfo and queryNames through everywhere... - // - permission javax.management.namespace.JMXNamespacePermission "[]", - "getMBeanInfo,queryNames"; - permission javax.management.MBeanPermission "*", - "getMBeanInfo,queryNames"; - - // special permission for all wombats: - // - permission javax.management.namespace.JMXNamespacePermission - "[**//*:type=Wombat,*]", - "getObjectInstance,isInstanceOf,queryMBeans"; - permission javax.management.MBeanPermission "[*:type=Wombat,*]", - "getObjectInstance,isInstanceOf,queryMBeans"; - - // allow JMXNamespace::getDefaultDomain - permission javax.management.namespace.JMXNamespacePermission - "*::DefaultDomain", - "getAttribute"; - - // These permissions are required to connect visualvm. - // - permission javax.management.MBeanPermission "default::[java.lang:*]", - "getObjectInstance,isInstanceOf,getAttribute,getMBeanInfo,queryNames,queryMBeans"; - permission javax.management.MBeanPermission "root::", - "isInstanceOf,queryNames,queryMBeans,getAttribute,getMBeanInfo,getObjectInstance,getDomains"; - permission javax.management.namespace.JMXNamespacePermission - "[**//JMImplementation:type=MBeanServerDelegate]", - "addNotificationListener,removeNotificationListener,isInstanceOf,queryNames,queryMBeans,getAttribute,getMBeanInfo,getObjectInstance"; - permission javax.management.MBeanPermission - "javax.management.MBeanServerDelegate", - "addNotificationListener,removeNotificationListener,isInstanceOf,queryNames,queryMBeans,getAttribute,getMBeanInfo,getObjectInstance"; - - // Thread monitoring - permission java.lang.management.ManagementPermission "monitor"; - permission javax.management.MBeanPermission "*::sun.management.*#*[java.lang:*]", "invoke"; -}; - - diff --git a/test/javax/management/notification/SupportClearTest.java b/test/javax/management/notification/SupportClearTest.java deleted file mode 100644 index 56712cf48..000000000 --- a/test/javax/management/notification/SupportClearTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - */ - -/* - * @test - * @bug 6336980 - * @summary test 2 new methods: isListenedTo() and clear() - * @author Shanliang JIANG - * @run clean SupportClearTest - * @run build SupportClearTest - * @run main SupportClearTest - */ - -import javax.management.*; - -public class SupportClearTest { - private static boolean received = false; - - public static void main(String[] args) throws Exception { - System.out.println(">>> test 2 new methods: isListenedTo() and clear()."); - - final NotificationListener listener = new NotificationListener() { - public void handleNotification(Notification n, Object hb) { - received = true; - } - }; - - final NotificationBroadcasterSupport broadcaster = - new NotificationBroadcasterSupport(); - - System.out.println(">>> testing the method \"isListenedTo\"..."); - if (broadcaster.isListenedTo()) { - throw new RuntimeException( - "Bad implementation of the method \"isListenedTo\"!"); - } - - broadcaster.addNotificationListener(listener, null, null); - - if (!broadcaster.isListenedTo()) { - throw new RuntimeException( - "Bad implementation of the method \"isListenedTo\"!"); - } - - System.out.println(">>> testing the method \"clear\"..."); - broadcaster.removeAllNotificationListeners(); - if (broadcaster.isListenedTo()) { - throw new RuntimeException( - "Bad implementation of the method \"clear\"!"); - } - - broadcaster.sendNotification(new Notification("", "", 1L)); - - if (received) { - throw new RuntimeException( - "Bad implementation of the method \"clear\"!"); - } - - System.out.println(">>> PASSED!"); - } -} diff --git a/test/javax/management/openmbean/CompositeDataToMapTest.java b/test/javax/management/openmbean/CompositeDataToMapTest.java deleted file mode 100644 index 30641b7c7..000000000 --- a/test/javax/management/openmbean/CompositeDataToMapTest.java +++ /dev/null @@ -1,116 +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. - * - * 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. - */ - -/* - * @test - * @bug 6750472 6752563 - * @summary Test CompositeDataSupport.toMap. - * @author Eamonn McManus - * @run main/othervm -ea CompositeDataToMapTest - */ - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; - -public class CompositeDataToMapTest { - private static class IdentityInvocationHandler implements InvocationHandler { - private final Object wrapped; - - public IdentityInvocationHandler(Object wrapped) { - this.wrapped = wrapped; - } - - public Object invoke(Object proxy, Method m, Object[] args) - throws Throwable { - try { - return m.invoke(wrapped, args); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } - } - - private static T wrap(T x, Class intf) { - InvocationHandler ih = new IdentityInvocationHandler(x); - return intf.cast(Proxy.newProxyInstance( - intf.getClassLoader(), new Class[] {intf}, ih)); - } - - public static void main(String[] args) throws Exception { - if (!CompositeDataToMapTest.class.desiredAssertionStatus()) - throw new AssertionError("Must be run with -ea"); - - CompositeType emptyCT = new CompositeType( - "empty", "empty", new String[0], new String[0], new OpenType[0]); - CompositeData emptyCD = new CompositeDataSupport( - emptyCT, Collections.emptyMap()); - assert CompositeDataSupport.toMap(emptyCD).isEmpty() : - "Empty CD produces empty Map"; - - CompositeData emptyCD2 = new CompositeDataSupport( - emptyCT, new String[0], new Object[0]); - assert emptyCD.equals(emptyCD2) : "Empty CD can be constructed two ways"; - - CompositeType namedNumberCT = new CompositeType( - "NamedNumber", "NamedNumber", - new String[] {"name", "number"}, - new String[] {"name", "number"}, - new OpenType[] {SimpleType.STRING, SimpleType.INTEGER}); - Map namedNumberMap = new HashMap(); - namedNumberMap.put("name", "Deich"); - namedNumberMap.put("number", 10); - CompositeData namedNumberCD = new CompositeDataSupport( - namedNumberCT, namedNumberMap); - assert CompositeDataSupport.toMap(namedNumberCD).equals(namedNumberMap) : - "Map survives passage through CompositeData"; - - namedNumberCD = wrap(namedNumberCD, CompositeData.class); - assert CompositeDataSupport.toMap(namedNumberCD).equals(namedNumberMap) : - "Map survives passage through wrapped CompositeData"; - - namedNumberMap = CompositeDataSupport.toMap(namedNumberCD); - namedNumberMap.put("name", "Ceathar"); - namedNumberMap.put("number", 4); - namedNumberCD = new CompositeDataSupport(namedNumberCT, namedNumberMap); - assert CompositeDataSupport.toMap(namedNumberCD).equals(namedNumberMap) : - "Modified Map survives passage through CompositeData"; - - try { - namedNumberMap = CompositeDataSupport.toMap(null); - assert false : "Null toMap arg provokes exception"; - } catch (Exception e) { - assert e instanceof IllegalArgumentException : - "Exception for null toMap arg is IllegalArgumentException"; - } - } -} diff --git a/test/javax/management/openmbean/GenericMBeanExceptionTest.java b/test/javax/management/openmbean/GenericMBeanExceptionTest.java deleted file mode 100644 index fa682d0d0..000000000 --- a/test/javax/management/openmbean/GenericMBeanExceptionTest.java +++ /dev/null @@ -1,278 +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. - * - * 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. - */ - -/* - * @test - * @bug 6456269 - * @summary Test GenericMBeanException - * @author Eamonn McManus - */ - -import java.beans.ConstructorProperties; -import java.lang.management.ManagementFactory; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import javax.management.GenericMBeanException; -import javax.management.JMX; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.MXBeanMapping; -import javax.management.openmbean.MXBeanMappingFactory; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class GenericMBeanExceptionTest { - private static volatile String failure = null; - - public static interface ThrowerMBean { - public void throwGeneric() throws GenericMBeanException; - public void throwGeneric(Throwable cause) throws GenericMBeanException; - public void throwGeneric(String errorCode) throws GenericMBeanException; - public void throwGeneric(CompositeData userData) throws GenericMBeanException; - public void throwGeneric(String errorCode, CompositeData userData) - throws GenericMBeanException; - public void throwGeneric(String errorCode, CompositeData userData, Throwable cause) - throws GenericMBeanException; - } - - public static class Thrower implements ThrowerMBean { - - public void throwGeneric() throws GenericMBeanException { - throw new GenericMBeanException("Message"); - } - - public void throwGeneric(Throwable cause) throws GenericMBeanException { - throw new GenericMBeanException("Message", cause); - } - - public void throwGeneric(String errorCode) throws GenericMBeanException { - throw new GenericMBeanException("Message", errorCode, null); - } - - public void throwGeneric(CompositeData userData) throws GenericMBeanException { - throw new GenericMBeanException("Message", null, userData); - } - - public void throwGeneric(String errorCode, CompositeData userData) - throws GenericMBeanException { - throw new GenericMBeanException("Message", errorCode, userData); - } - - public void throwGeneric(String errorCode, CompositeData userData, - Throwable cause) throws GenericMBeanException { - throw new GenericMBeanException("Message", errorCode, userData, cause); - } - } - - public static class Payload { - private final int severity; - private final String subsystem; - - @ConstructorProperties({"severity", "subsystem"}) - public Payload(int severity, String subsystem) { - this.severity = severity; - this.subsystem = subsystem; - } - - public int getSeverity() { - return severity; - } - - public String getSubsystem() { - return subsystem; - } - - @Override - public boolean equals(Object x) { - if (!(x instanceof Payload)) - return false; - Payload p = (Payload) x; - return (severity == p.severity && - (subsystem == null) ? - p.subsystem == null : subsystem.equals(p.subsystem)); - } - - @Override - public int hashCode() { - return severity + subsystem.hashCode(); - } - - @Override - public String toString() { - return "Payload{severity: " + severity + ", subsystem: " + subsystem + "}"; - } - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - ObjectName name = new ObjectName("test:type=Thrower"); - Thrower thrower = new Thrower(); - mbs.registerMBean(thrower, name); - - if (args.length > 0) { - System.out.println("Attach client now, hit return to exit"); - System.in.read(); - return; - } - - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( - url, null, mbs); - cs.start(); - JMXServiceURL addr = cs.getAddress(); - - JMXConnector cc = JMXConnectorFactory.connect(addr); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - - ThrowerMBean throwerProxy = JMX.newMBeanProxy(mbsc, name, ThrowerMBean.class); - - Payload payload = new Payload(5, "modular modulizer"); - MXBeanMapping payloadMapping = MXBeanMappingFactory.DEFAULT.mappingForType( - Payload.class, MXBeanMappingFactory.DEFAULT); - CompositeData userData = (CompositeData) - payloadMapping.toOpenValue(payload); - Throwable cause = new IllegalArgumentException("Badness"); - - Object[][] testCases = { - {}, - {"code1"}, - {userData}, - {"code2", userData}, - {(String) null, userData}, - {"code99", userData, cause}, - {(String) null, userData, cause}, - }; - - for (Object[] testCase : testCases) { - System.out.println("Test case: " + testCaseString(testCase)); - - // Find which ThrowerMBean method it corresponds to - Method testMethod = null; -search: - for (Method m : ThrowerMBean.class.getMethods()) { - Class[] paramTypes = m.getParameterTypes(); - if (paramTypes.length != testCase.length) - continue; - for (int i = 0; i < paramTypes.length; i++) { - if (testCase[i] != null && !paramTypes[i].isInstance(testCase[i])) - continue search; - } - testMethod = m; - } - - if (testMethod == null) { - throw new Exception("TEST ERROR: no method corresponds: " + - testCaseString(testCase)); - } - - try { - testMethod.invoke(throwerProxy, testCase); - fail("Did not throw exception", testCase); - continue; - } catch (InvocationTargetException e) { - Throwable iteCause = e.getCause(); - if (!(iteCause instanceof GenericMBeanException)) { - iteCause.printStackTrace(System.out); - fail("Threw wrong exception " + iteCause, testCase); - continue; - } - GenericMBeanException ge = (GenericMBeanException) iteCause; - if (!ge.getMessage().equals("Message")) - fail("Wrong message: " + ge.getMessage(), testCase); - - Class[] paramTypes = testMethod.getParameterTypes(); - for (int i = 0; i < paramTypes.length; i++) { - Class paramType = paramTypes[i]; - - if (paramType == Throwable.class) { // cause - Throwable geCause = ge.getCause(); - if (!(geCause instanceof IllegalArgumentException)) - fail("Wrong cause: " + geCause, testCase); - else if (!geCause.getMessage().equals("Badness")) - fail("Wrong cause message: " + geCause.getMessage(), testCase); - } else if (paramType == String.class) { // errorCode - String errorCode = ge.getErrorCode(); - String expectedErrorCode = - (testCase[i] == null) ? "" : (String) testCase[i]; - if (!expectedErrorCode.equals(errorCode)) - fail("Wrong error code: " + ge.getErrorCode(), testCase); - } else if (paramType == CompositeData.class) { // userData - CompositeData userData2 = ge.getUserData(); - if (!userData.equals(userData2)) - fail("Wrong userData: " + userData2, testCase); - Payload payload2 = (Payload) payloadMapping.fromOpenValue(userData2); - if (!payload.equals(payload2)) - fail("Wrong payload: " + payload2, testCase); - } else - throw new Exception("TEST ERROR: unknown parameter type: " + paramType); - } - } - } - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static String testCaseString(Object[] testCase) { - StringBuilder sb = new StringBuilder("["); - String sep = ""; - for (Object x : testCase) { - sb.append(sep); - String xs = (x instanceof CompositeData) ? - compositeDataString((CompositeData) x) : String.valueOf(x); - sb.append(xs); - sep = ", "; - } - sb.append("]"); - return sb.toString(); - } - - private static String compositeDataString(CompositeData cd) { - StringBuilder sb = new StringBuilder("CompositeData{"); - CompositeType ct = cd.getCompositeType(); - String sep = ""; - for (String key : ct.keySet()) { - sb.append(sep).append(key).append(": ").append(cd.get(key)); - sep = ", "; - } - sb.append("}"); - return sb.toString(); - } - - private static void fail(String why, Object[] testCase) { - fail(testCaseString(testCase) + ": " + why); - } - - private static void fail(String why) { - failure = why; - System.out.println("FAIL: " + why); - } -} diff --git a/test/javax/management/query/QueryDottedAttrTest.java b/test/javax/management/query/QueryDottedAttrTest.java deleted file mode 100644 index 956496db9..000000000 --- a/test/javax/management/query/QueryDottedAttrTest.java +++ /dev/null @@ -1,192 +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. - * - * 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. - */ - -/* - * @test QueryDottedAttrTest - * @bug 6602310 - * @summary Test that Query.attr can understand a.b etc. - * @author Eamonn McManus - */ - -import java.beans.ConstructorProperties; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Collections; -import java.util.Set; -import javax.management.AttributeNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; -import javax.management.Query; -import javax.management.QueryExp; -import javax.management.ReflectionException; -import javax.management.StandardMBean; - -public class QueryDottedAttrTest { - public static class Complex { - private final double re, im; - - @ConstructorProperties({"real", "imaginary"}) - public Complex(double re, double im) { - this.re = re; - this.im = im; - } - - public double getRe() { - return re; - } - - public double getIm() { - return im; - } - } - - public static interface Intf { - Complex getComplex(); - int[] getIntArray(); - String[] getStringArray(); - } - - public static class Impl implements Intf { - public Complex getComplex() { - return new Complex(1.0, 1.0); - } - - public int[] getIntArray() { - return new int[] {1, 2, 3}; - } - - public String[] getStringArray() { - return new String[] {"one", "two", "three"}; - } - } - - public static interface TestMBean extends Intf {} - - public static class Test extends Impl implements TestMBean {} - - public static interface TestMXBean extends Intf {} - - public static class TestMX extends Impl implements TestMXBean {} - - public static class AttrWithDot extends StandardMBean { - public AttrWithDot(Object impl, Class intf) { - super(intf.cast(impl), intf, (intf == TestMXBean.class)); - } - - public Object getAttribute(String attribute) - throws AttributeNotFoundException, MBeanException, ReflectionException { - if (attribute.equals("Complex.re")) - return 2.0; - else - return super.getAttribute(attribute); - } - } - - private static final boolean[] booleans = {false, true}; - - private static final QueryExp[] alwaysTrueQueries = { - Query.eq(Query.attr("IntArray.length"), Query.value(3)), - Query.eq(Query.attr("StringArray.length"), Query.value(3)), - Query.eq(Query.attr("Complex.im"), Query.value(1.0)), - }; - - private static final QueryExp[] alwaysFalseQueries = { - Query.eq(Query.attr("IntArray.length"), Query.value("3")), - Query.eq(Query.attr("IntArray.length"), Query.value(2)), - Query.eq(Query.attr("Complex.im"), Query.value(-1.0)), - Query.eq(Query.attr("Complex.xxx"), Query.value(0)), - }; - - private static final QueryExp[] attrWithDotTrueQueries = { - Query.eq(Query.attr("Complex.re"), Query.value(2.0)), - }; - - private static final QueryExp[] attrWithDotFalseQueries = { - Query.eq(Query.attr("Complex.re"), Query.value(1.0)), - }; - - private static String failure; - - public static void main(String[] args) throws Exception { - ObjectName name = new ObjectName("a:b=c"); - for (boolean attrWithDot : booleans) { - for (boolean mx : booleans) { - String what = - (mx ? "MXBean" : "Standard MBean") + - (attrWithDot ? " having attribute with dot in its name" : ""); - System.out.println("Testing " + what); - Class intf = mx ? TestMXBean.class : TestMBean.class; - Object impl = mx ? new TestMX() : new Test(); - if (attrWithDot) - impl = new AttrWithDot(impl, intf); - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - mbs.registerMBean(impl, name); - boolean ismx = "true".equals( - mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean")); - if (mx != ismx) - fail("MBean should " + (mx ? "" : "not ") + "be MXBean"); - test(mbs, name, alwaysTrueQueries, true); - test(mbs, name, alwaysFalseQueries, false); - test(mbs, name, attrWithDotTrueQueries, attrWithDot); - test(mbs, name, attrWithDotFalseQueries, !attrWithDot); - } - } - if (failure != null) - throw new Exception("TEST FAILED: " + failure); - } - - private static void test( - MBeanServer mbs, ObjectName name, QueryExp[] queries, boolean expect) - throws Exception { - for (QueryExp query : queries) { - // Serialize and deserialize the query to ensure that its - // serialization is correct - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - ObjectOutputStream oout = new ObjectOutputStream(bout); - oout.writeObject(query); - oout.close(); - ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); - ObjectInputStream oin = new ObjectInputStream(bin); - query = (QueryExp) oin.readObject(); - Set names = mbs.queryNames(null, query); - if (names.isEmpty()) { - if (expect) - fail("Query is false but should be true: " + query); - } else if (names.equals(Collections.singleton(name))) { - if (!expect) - fail("Query is true but should be false: " + query); - } else { - fail("Query returned unexpected set: " + names); - } - } - } - - private static void fail(String msg) { - failure = msg; - System.out.println("..." + msg); - } -} diff --git a/test/javax/management/query/QueryExpStringTest.java b/test/javax/management/query/QueryExpStringTest.java index 98d4ba9f6..0f5f42529 100644 --- a/test/javax/management/query/QueryExpStringTest.java +++ b/test/javax/management/query/QueryExpStringTest.java @@ -31,10 +31,6 @@ * @run main QueryExpStringTest */ -// This test is mostly obsolete, since we now have Query.fromString. -// The test includes its own parser, from which Query.fromString was derived. -// The parsers are not identical and the one here is no longer maintained. - import java.util.*; import javax.management.*; diff --git a/test/javax/management/query/QueryNotifFilterTest.java b/test/javax/management/query/QueryNotifFilterTest.java deleted file mode 100644 index 8b685741b..000000000 --- a/test/javax/management/query/QueryNotifFilterTest.java +++ /dev/null @@ -1,347 +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. - * - * 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. - */ - -/* - * @test QueryNotifFilterTest - * @bug 6610917 - * @summary Test the QueryNotificationFilter class - * @author Eamonn McManus - */ - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import javax.management.Attribute; -import javax.management.AttributeChangeNotification; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanServer; -import javax.management.MalformedObjectNameException; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.ObjectInstance; -import javax.management.ObjectName; -import javax.management.Query; -import javax.management.QueryEval; -import javax.management.QueryExp; -import javax.management.QueryNotificationFilter; - -public class QueryNotifFilterTest { - private static class Case { - final Notification notif; - final QueryExp query; - final boolean expect; - final Class notifClass; - Case(Notification notif, String query, boolean expect) { - this(notif, query, notif.getClass(), expect); - } - Case(Notification notif, String query, - Class notifClass, boolean expect) { - this(notif, Query.fromString(query), notifClass, expect); - } - Case(Notification notif, QueryExp query, boolean expect) { - this(notif, query, notif.getClass(), expect); - } - Case(Notification notif, QueryExp query, - Class notifClass, boolean expect) { - this.notif = notif; - this.query = query; - this.expect = expect; - this.notifClass = notifClass; - } - } - - /* In principle users can create their own implementations of QueryExp - * and use them with QueryNotificationFilter. If they do so, then - * they can call any MBeanServer method. Not all of those methods - * will work with the special MBeanServer we concoct to analyze a - * Notification, but some will, including some that are not called - * by the standard queries. So we check each of those cases too. - */ - private static class ExoticCase { - final Notification trueNotif; - final Notification falseNotif; - final QueryExp query; - ExoticCase(Notification trueNotif, Notification falseNotif, QueryExp query) { - this.trueNotif = trueNotif; - this.falseNotif = falseNotif; - this.query = query; - } - } - - private static abstract class ExoticQuery - extends QueryEval implements QueryExp { - private final String queryString; - ExoticQuery(String queryString) { - this.queryString = queryString; - } - abstract boolean apply(MBeanServer mbs, ObjectName name) throws Exception; - //@Override - doesn't override in JDK5 - public boolean apply(ObjectName name) { - try { - return apply(getMBeanServer(), name); - } catch (Exception e) { - e.printStackTrace(System.out); - return false; - } - } - @Override - public String toString() { - return queryString; - } - } - - private static ObjectName makeObjectName(String s) { - try { - return new ObjectName(s); - } catch (MalformedObjectNameException e) { - throw new RuntimeException(e); - } - } - - public static class CustomNotification extends Notification { - public CustomNotification(String type, Object source, long seqNo) { - super(type, source, seqNo); - } - - public String getName() { - return "claude"; - } - - public boolean isInteresting() { - return true; - } - } - - private static final Notification simpleNotif = - new Notification("mytype", "source", 0L); - private static final Notification attrChangeNotif = - new AttributeChangeNotification( - "x", 0L, 0L, "msg", "AttrName", "int", 2, 3); - private static final ObjectName testObjectName = makeObjectName("a:b=c"); - private static final Notification sourcedNotif = - new Notification("mytype", testObjectName, 0L); - private static final Notification customNotif = - new CustomNotification("mytype", testObjectName, 0L); - - private static final Case[] testCases = { - new Case(simpleNotif, "Type = 'mytype'", true), - new Case(simpleNotif, "Type = 'mytype'", - Notification.class, true), - new Case(simpleNotif, "Type = 'mytype'", - AttributeChangeNotification.class, false), - new Case(simpleNotif, "Type != 'mytype'", false), - new Case(simpleNotif, "Type = 'somethingelse'", false), - new Case(attrChangeNotif, "AttributeName = 'AttrName'", true), - new Case(attrChangeNotif, - "instanceof 'javax.management.AttributeChangeNotification'", - true), - new Case(attrChangeNotif, - "instanceof 'javax.management.Notification'", - true), - new Case(attrChangeNotif, - "instanceof 'javax.management.relation.MBeanServerNotification'", - false), - new Case(attrChangeNotif, - "class = 'javax.management.AttributeChangeNotification'", - true), - new Case(attrChangeNotif, - "javax.management.AttributeChangeNotification#AttributeName = 'AttrName'", - true), - new Case(sourcedNotif, - testObjectName, - true), - new Case(sourcedNotif, - makeObjectName("a*:b=*"), - true), - new Case(sourcedNotif, - makeObjectName("a*:c=*"), - false), - new Case(customNotif, "Name = 'claude'", true), - new Case(customNotif, "Name = 'tiddly'", false), - new Case(customNotif, "Interesting = true", true), - new Case(customNotif, "Interesting = false", false), - }; - - private static final ExoticCase[] exoticTestCases = { - new ExoticCase( - simpleNotif, new Notification("notmytype", "source", 0L), - new ExoticQuery("getAttributes") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - List attrs = mbs.getAttributes( - name, new String[] {"Type", "Source"}).asList(); - return (attrs.get(0).equals(new Attribute("Type", "mytype")) && - attrs.get(1).equals(new Attribute("Source", "source"))); - } - }), - new ExoticCase( - new Notification("mytype", "source", 0L) {}, - simpleNotif, - new ExoticQuery("getClassLoaderFor") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - return (mbs.getClassLoaderFor(name) == - this.getClass().getClassLoader()); - } - }), - new ExoticCase( - sourcedNotif, simpleNotif, - new ExoticQuery("getDomains") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - return Arrays.equals(mbs.getDomains(), - new String[] {testObjectName.getDomain()}); - } - }), - new ExoticCase( - simpleNotif, attrChangeNotif, - new ExoticQuery("getMBeanInfo") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - MBeanInfo mbi = mbs.getMBeanInfo(name); - // If we ever add a constructor to Notification then - // we will have to change the 4 below. - if (mbi.getOperations().length > 0 || - mbi.getConstructors().length != 4 || - mbi.getNotifications().length > 0) - return false; - Set expect = new HashSet( - Arrays.asList( - "Class", "Message", "SequenceNumber", "Source", - "TimeStamp", "Type", "UserData")); - Set actual = new HashSet(); - for (MBeanAttributeInfo mbai : mbi.getAttributes()) - actual.add(mbai.getName()); - return actual.equals(expect); - } - }), - new ExoticCase( - simpleNotif, attrChangeNotif, - new ExoticQuery("getObjectInstance") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - ObjectInstance oi = mbs.getObjectInstance(name); - return oi.getClassName().equals(Notification.class.getName()); - } - }), - new ExoticCase( - sourcedNotif, simpleNotif, - new ExoticQuery("queryNames") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - Set names = mbs.queryNames(null, - Query.eq(Query.attr("Type"), Query.value("mytype"))); - return names.equals(Collections.singleton(testObjectName)); - } - }), - new ExoticCase( - sourcedNotif, simpleNotif, - new ExoticQuery("queryMBeans") { - boolean apply(MBeanServer mbs, ObjectName name) - throws Exception { - Set insts = mbs.queryMBeans(null, - Query.eq(Query.attr("Type"), Query.value("mytype"))); - if (insts.size() != 1) - return false; - ObjectInstance inst = insts.iterator().next(); - return (inst.getObjectName().equals(testObjectName) && - inst.getClassName().equals(Notification.class.getName())); - } - }), - }; - - private static enum Test { - QUERY_EXP("query"), STRING("string"), STRING_PLUS_CLASS("string with class"); - private final String name; - Test(String name) { - this.name = name; - } - @Override - public String toString() { - return name; - } - } - - public static void main(String[] args) throws Exception { - boolean allok = true; - for (Case testCase : testCases) { - for (Test test : Test.values()) { - QueryNotificationFilter nf; - String queryString; - switch (test) { - case QUERY_EXP: { - QueryExp inst = Query.isInstanceOf( - Query.value(testCase.notifClass.getName())); - QueryExp and = Query.and(inst, testCase.query); - queryString = Query.toString(and); - nf = new QueryNotificationFilter(and); - break; - } - case STRING: { - String s = "instanceof '" + testCase.notifClass.getName() + "'"; - queryString = s + " and " + Query.toString(testCase.query); - nf = new QueryNotificationFilter(queryString); - break; - } - case STRING_PLUS_CLASS: - queryString = null; - nf = new QueryNotificationFilter( - testCase.notifClass, Query.toString(testCase.query)); - break; - default: - throw new AssertionError(); - } - boolean accept = nf.isNotificationEnabled(testCase.notif); - if (queryString != null) { - queryString = Query.toString(Query.fromString(queryString)); - if (!queryString.equals(Query.toString(nf.getQuery()))) { - System.out.println("FAIL: query string mismatch: expected " + - "\"" + queryString + "\", got \"" + - Query.toString(nf.getQuery())); - allok = false; - } - } - boolean ok = (accept == testCase.expect); - System.out.println((ok ? "pass" : "FAIL") + ": " + - testCase.query + " (" + test + ")"); - allok &= ok; - } - } - for (ExoticCase testCase : exoticTestCases) { - NotificationFilter nf = new QueryNotificationFilter(testCase.query); - for (boolean expect : new boolean[] {true, false}) { - Notification n = expect ? testCase.trueNotif : testCase.falseNotif; - boolean accept = nf.isNotificationEnabled(n); - boolean ok = (accept == expect); - System.out.println((ok ? "pass" : "FAIL") + ": " + - testCase.query + ": " + n); - allok &= ok; - } - } - if (!allok) - throw new Exception("TEST FAILED"); - } -} diff --git a/test/javax/management/query/QueryParseTest.java b/test/javax/management/query/QueryParseTest.java deleted file mode 100644 index 62b64bf71..000000000 --- a/test/javax/management/query/QueryParseTest.java +++ /dev/null @@ -1,781 +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. - * - * 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. - */ - -/* - * @test QueryParseTest - * @bug 6602310 6604768 - * @summary Test Query.fromString and Query.toString. - * @author Eamonn McManus - */ - -import java.util.Collections; -import java.util.Set; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; -import javax.management.Query; -import javax.management.QueryExp; - -public class QueryParseTest { - // In this table, each string constant corresponds to a test case. - // The objects following the string up to the next string are MBeans. - // Each MBean must implement ExpectedValue to return true or false - // according as it should return that value for the query parsed - // from the given string. The test will parse the string into a - // a query and verify that the MBeans return the expected value - // for that query. Then it will convert the query back into a string - // and into a second query, and check that the MBeans return the - // expected value for that query too. The reason we need to do all - // this is that the spec talks about "equivalent queries", and gives - // the implementation wide scope to rearrange queries. So we cannot - // just compare string values. - // - // We could also write an implementation-dependent test that knew what - // the strings look like, and that would have to be changed if the - // implementation changed. But the approach here is cleaner. - // - // To simplify the creation of MBeans, most use the expectTrue or - // expectFalse methods. The parameters of these methods end up in - // attributes called "A", "B", "C", etc. - private static final Object[] queryTests = { - // RELATIONS - - "A < B", - expectTrue(1, 2), expectTrue(1.0, 2.0), expectTrue("one", "two"), - expectTrue(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), - expectFalse(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY), - expectFalse(1, 1), expectFalse(1.0, 1.0), expectFalse("one", "one"), - expectFalse(2, 1), expectFalse(2.0, 1.0), expectFalse("two", "one"), - expectFalse(Double.NaN, Double.NaN), - - "One = two", - expectTrueOneTwo(1, 1), expectTrueOneTwo(1.0, 1.0), - expectFalseOneTwo(1, 2), expectFalseOneTwo(2, 1), - - "A <= B", - expectTrue(1, 1), expectTrue(1, 2), expectTrue("one", "one"), - expectTrue("one", "two"), - expectFalse(2, 1), expectFalse("two", "one"), - expectFalse(Double.NaN, Double.NaN), - - "A >= B", - expectTrue(1, 1), expectTrue(2, 1), expectTrue("two", "one"), - expectFalse(1, 2), expectFalse("one", "two"), - - "A > B", - expectTrue(2, 1), expectTrue("two", "one"), - expectFalse(2, 2), expectFalse(1, 2), expectFalse(1.0, 2.0), - expectFalse("one", "two"), - - "A <> B", - expectTrue(1, 2), expectTrue("foo", "bar"), - expectFalse(1, 1), expectFalse("foo", "foo"), - - "A != B", - expectTrue(1, 2), expectTrue("foo", "bar"), - expectFalse(1, 1), expectFalse("foo", "foo"), - - // PARENTHESES - - "(((A))) = (B)", - expectTrue(1, 1), expectFalse(1, 2), - - "(A = B)", - expectTrue(1, 1), expectFalse(1, 2), - - "(((A = (B))))", - expectTrue(1, 1), expectFalse(1, 2), - - // INTEGER LITERALS - - "A = 1234567890123456789", - expectTrue(1234567890123456789L), expectFalse(123456789L), - - "A = +1234567890123456789", - expectTrue(1234567890123456789L), expectFalse(123456789L), - - "A = -1234567890123456789", - expectTrue(-1234567890123456789L), expectFalse(-123456789L), - - - "A = + 1234567890123456789", - expectTrue(1234567890123456789L), expectFalse(123456789L), - - "A = - 1234567890123456789", - expectTrue(-1234567890123456789L), expectFalse(-123456789L), - - "A = " + Long.MAX_VALUE, - expectTrue(Long.MAX_VALUE), expectFalse(Long.MIN_VALUE), - - "A = " + Long.MIN_VALUE, - expectTrue(Long.MIN_VALUE), expectFalse(Long.MAX_VALUE), - - // DOUBLE LITERALS - - "A = 0.0", - expectTrue(0.0), expectFalse(1.0), - - "A = 0.0e23", - expectTrue(0.0), expectFalse(1.0), - - "A = 1.2e3", - expectTrue(1.2e3), expectFalse(1.2), - - "A = +1.2", - expectTrue(1.2), expectFalse(-1.2), - - "A = 1.2e+3", - expectTrue(1.2e3), expectFalse(1.2), - - "A = 1.2e-3", - expectTrue(1.2e-3), expectFalse(1.2), - - "A = 1.2E3", - expectTrue(1.2e3), expectFalse(1.2), - - "A = -1.2e3", - expectTrue(-1.2e3), expectFalse(1.2), - - "A = " + Double.MAX_VALUE, - expectTrue(Double.MAX_VALUE), expectFalse(Double.MIN_VALUE), - - "A = " + -Double.MAX_VALUE, - expectTrue(-Double.MAX_VALUE), expectFalse(-Double.MIN_VALUE), - - "A = " + Double.MIN_VALUE, - expectTrue(Double.MIN_VALUE), expectFalse(Double.MAX_VALUE), - - "A = " + -Double.MIN_VALUE, - expectTrue(-Double.MIN_VALUE), expectFalse(-Double.MAX_VALUE), - - Query.toString( // A = Infinity -> A = (1.0/0.0) - Query.eq(Query.attr("A"), Query.value(Double.POSITIVE_INFINITY))), - expectTrue(Double.POSITIVE_INFINITY), - expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), - - Query.toString( // A = -Infinity -> A = (-1.0/0.0) - Query.eq(Query.attr("A"), Query.value(Double.NEGATIVE_INFINITY))), - expectTrue(Double.NEGATIVE_INFINITY), - expectFalse(0.0), expectFalse(Double.POSITIVE_INFINITY), - - Query.toString( // A < NaN -> A < (0.0/0.0) - Query.lt(Query.attr("A"), Query.value(Double.NaN))), - expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), - expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN), - - Query.toString( // A >= NaN -> A < (0.0/0.0) - Query.geq(Query.attr("A"), Query.value(Double.NaN))), - expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY), - expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN), - - // STRING LITERALS - - "A = 'blim'", - expectTrue("blim"), expectFalse("blam"), - - "A = 'can''t'", - expectTrue("can't"), expectFalse("cant"), expectFalse("can''t"), - - "A = '''blim'''", - expectTrue("'blim'"), expectFalse("'blam'"), - - "A = ''", - expectTrue(""), expectFalse((Object) null), - - // BOOLEAN LITERALS - - "A = true", - expectTrue(true), expectFalse(false), expectFalse((Object) null), - - "A = TRUE", - expectTrue(true), expectFalse(false), - - "A = TrUe", - expectTrue(true), expectFalse(false), - - "A = false", - expectTrue(false), expectFalse(true), - - "A = fAlSe", - expectTrue(false), expectFalse(true), - - "A = \"true\"", // An attribute called "true" - expectFalse(true), expectFalse(false), expectFalse("\"true\""), - newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.2}, true), - newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.3}, false), - - "A = \"False\"", - expectFalse(true), expectFalse(false), expectFalse("\"False\""), - newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.2}, true), - newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.3}, false), - - // ARITHMETIC - - "A + B = 10", - expectTrue(4, 6), expectFalse(3, 8), - - "A + B = 'blim'", - expectTrue("bl", "im"), expectFalse("bl", "am"), - - "A - B = 10", - expectTrue(16, 6), expectFalse(16, 3), - - "A * B = 10", - expectTrue(2, 5), expectFalse(3, 3), - - "A / B = 10", - expectTrue(70, 7), expectTrue(70.0, 7), expectFalse(70.01, 7), - - "A + B + C = 10", - expectTrue(2, 3, 5), expectFalse(2, 4, 8), - - "A+B+C=10", - expectTrue(2, 3, 5), expectFalse(2, 4, 8), - - "A + B + C + D = 10", - expectTrue(1, 2, 3, 4), expectFalse(2, 3, 4, 5), - - "A + (B + C) = 10", - expectTrue(2, 3, 5), expectFalse(2, 4, 8), - - // It is not correct to rearrange A + (B + C) as A + B + C - // (which means (A + B) + C), because of overflow. - // In particular Query.toString must not do this. - "A + (B + C) = " + Double.MAX_VALUE, // ensure no false associativity - expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE), - expectFalse(-Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), - - "A * (B * C) < " + Double.MAX_VALUE, // same test for multiplication - expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE), - expectFalse(Double.MIN_VALUE, Double.MAX_VALUE, Double.MAX_VALUE), - - "A * B + C = 10", - expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), - - "A*B+C=10", - expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), - - "(A * B) + C = 10", - expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3), - - "A + B * C = 10", - expectTrue(1, 3, 3), expectTrue(2, 2, 4), expectFalse(1, 2, 3), - - "A - B * C = 10", - expectTrue(16, 2, 3), expectFalse(15, 2, 2), - - "A + B / C = 10", - expectTrue(5, 15, 3), expectFalse(5, 16, 4), - - "A - B / C = 10", - expectTrue(16, 12, 2), expectFalse(15, 10, 3), - - "A * (B + C) = 10", - expectTrue(2, 2, 3), expectFalse(1, 2, 3), - - "A / (B + C) = 10", - expectTrue(70, 4, 3), expectFalse(70, 3, 5), - - "A * (B - C) = 10", - expectTrue(2, 8, 3), expectFalse(2, 3, 8), - - "A / (B - C) = 10", - expectTrue(70, 11, 4), expectFalse(70, 4, 11), - - "A / B / C = 10", - expectTrue(140, 2, 7), expectFalse(100, 5, 5), - - "A / (B / C) = 10", - expectTrue(70, 14, 2), expectFalse(70, 10, 7), - - // LOGIC - - "A = B or C = D", - expectTrue(1, 1, 2, 3), expectTrue(1, 2, 3, 3), expectTrue(1, 1, 2, 2), - expectFalse(1, 2, 3, 4), expectFalse("!", "!!", "?", "??"), - - "A = B and C = D", - expectTrue(1, 1, 2, 2), - expectFalse(1, 1, 2, 3), expectFalse(1, 2, 3, 3), - - "A = 1 and B = 2 and C = 3", - expectTrue(1, 2, 3), expectFalse(1, 2, 4), - - "A = 1 or B = 2 or C = 3", - expectTrue(1, 2, 3), expectTrue(1, 0, 0), expectTrue(0, 0, 3), - expectFalse(2, 3, 4), - - // grouped as (a and b) or (c and d) - "A = 1 AND B = 2 OR C = 3 AND D = 4", - expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4), - expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1), - - "(A = 1 AND B = 2) OR (C = 3 AND D = 4)", - expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4), - expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1), - - "(A = 1 or B = 2) AND (C = 3 or C = 4)", - expectTrue(1, 1, 3, 3), expectTrue(2, 2, 4, 4), expectTrue(1, 2, 3, 4), - expectFalse(1, 2, 1, 2), expectFalse(3, 4, 3, 4), - - // LIKE - - "A like 'b*m'", - expectTrue("blim"), expectTrue("bm"), - expectFalse(""), expectFalse("blimmo"), expectFalse("mmm"), - - "A not like 'b*m'", - expectFalse("blim"), expectFalse("bm"), - expectTrue(""), expectTrue("blimmo"), expectTrue("mmm"), - - "A like 'b?m'", - expectTrue("bim"), expectFalse("blim"), - - "A like '*can''t*'", - expectTrue("can't"), - expectTrue("I'm sorry Dave, I'm afraid I can't do that"), - expectFalse("cant"), expectFalse("can''t"), - - "A like '\\**\\*'", - expectTrue("*blim*"), expectTrue("**"), - expectFalse("blim"), expectFalse("*asdf"), expectFalse("asdf*"), - - "A LIKE '%*_?'", - expectTrue("%blim_?"), expectTrue("%_?"), expectTrue("%blim_!"), - expectFalse("blim"), expectFalse("blim_"), - expectFalse("_%"), expectFalse("??"), expectFalse(""), expectFalse("?"), - - Query.toString( - Query.initialSubString(Query.attr("A"), Query.value("*?%_"))), - expectTrue("*?%_tiddly"), expectTrue("*?%_"), - expectFalse("?%_tiddly"), expectFalse("*!%_"), expectFalse("*??_"), - expectFalse("*?%!"), expectFalse("*?%!tiddly"), - - Query.toString( - Query.finalSubString(Query.attr("A"), Query.value("*?%_"))), - expectTrue("tiddly*?%_"), expectTrue("*?%_"), - expectFalse("tiddly?%_"), expectFalse("*!%_"), expectFalse("*??_"), - expectFalse("*?%!"), expectFalse("tiddly*?%!"), - - // BETWEEN - - "A between B and C", - expectTrue(1, 1, 2), expectTrue(2, 1, 2), expectTrue(2, 1, 3), - expectFalse(3, 1, 2), expectFalse(0, 1, 2), expectFalse(2, 3, 1), - expectTrue(1.0, 0.0, 2.0), expectFalse(2.0, 0.0, 1.0), - expectTrue(0.0, 0.0, 0.0), expectTrue(1.0, 0.0, 1.0), - expectTrue(1.0, 0.0, Double.POSITIVE_INFINITY), - expectFalse(1.0, Double.NEGATIVE_INFINITY, 0.0), - expectFalse(false, false, true), expectFalse(true, false, true), - expectTrue("jim", "fred", "sheila"), expectFalse("fred", "jim", "sheila"), - - "A between B and C and 1+2=3", - expectTrue(2, 1, 3), expectFalse(2, 3, 1), - - "A not between B and C", - expectTrue(1, 2, 3), expectFalse(2, 1, 3), - - // IN - - "A in (1, 2, 3)", - expectTrue(1), expectTrue(2), expectTrue(3), - expectFalse(0), expectFalse(4), - - "A in (1)", - expectTrue(1), expectFalse(0), - - "A in (1.2, 3.4)", - expectTrue(1.2), expectTrue(3.4), expectFalse(0.0), - - "A in ('foo', 'bar')", - expectTrue("foo"), expectTrue("bar"), expectFalse("baz"), - - "A in ('foo', 'bar') and 'bl'+'im'='blim'", - expectTrue("foo"), expectTrue("bar"), expectFalse("baz"), - - "A in (B, C, D)", // requires fix for CR 6604768 - expectTrue(1, 1, 2, 3), expectFalse(1, 2, 3, 4), - - "A not in (B, C, D)", - expectTrue(1, 2, 3, 4), expectFalse(1, 1, 2, 3), - - // QUOTING - - "\"LIKE\" = 1 and \"NOT\" = 2 and \"INSTANCEOF\" = 3 and " + - "\"TRUE\" = 4 and \"FALSE\" = 5", - newTester( - new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"}, - new Object[] {1, 2, 3, 4, 5}, - true), - newTester( - new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"}, - new Object[] {5, 4, 3, 2, 1}, - false), - - "\"\"\"woo\"\"\" = 5", - newTester(new String[] {"\"woo\""}, new Object[] {5}, true), - newTester(new String[] {"\"woo\""}, new Object[] {4}, false), - expectFalse(), - - // INSTANCEOF - - "instanceof '" + Tester.class.getName() + "'", - expectTrue(), - - "instanceof '" + String.class.getName() + "'", - expectFalse(), - - // LIKE OBJECTNAME - - // The test MBean is registered as a:b=c - "like 'a:b=c'", expectTrue(), - "like 'a:*'", expectTrue(), - "like '*:b=c'", expectTrue(), - "like 'a:b=*'", expectTrue(), - "like 'a:b=?'", expectTrue(), - "like 'd:b=c'", expectFalse(), - "like 'a:b=??*'", expectFalse(), - "like 'a:b=\"can''t\"'", expectFalse(), - - // QUALIFIED ATTRIBUTE - - Tester.class.getName() + "#A = 5", - expectTrue(5), expectFalse(4), - - Tester.class.getName() + " # A = 5", - expectTrue(5), expectFalse(4), - - Tester.class.getSuperclass().getName() + "#A = 5", - expectFalse(5), - - DynamicMBean.class.getName() + "#A = 5", - expectFalse(5), - - Tester.class.getName() + "#A = 5", - new Tester(new String[] {"A"}, new Object[] {5}, false) {}, - // note the little {} at the end which means this is a subclass - // and therefore QualifiedAttributeValue should return false. - - MBeanServerDelegate.class.getName() + "#SpecificationName LIKE '*'", - new Wrapped(new MBeanServerDelegate(), true), - new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), - - // DOTTED ATTRIBUTE - - "A.canonicalName = '" + - MBeanServerDelegate.DELEGATE_NAME.getCanonicalName() + "'", - expectTrue(MBeanServerDelegate.DELEGATE_NAME), - expectFalse(ObjectName.WILDCARD), - - "A.class.name = 'java.lang.String'", - expectTrue("blim"), expectFalse(95), expectFalse((Object) null), - - "A.canonicalName like 'JMImpl*:*'", - expectTrue(MBeanServerDelegate.DELEGATE_NAME), - expectFalse(ObjectName.WILDCARD), - - "A.true = 'blim'", - new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true), - new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false), - - "\"A.true\" = 'blim'", - new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true), - new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false), - - MBeanServerDelegate.class.getName() + - "#SpecificationName.class.name = 'java.lang.String'", - new Wrapped(new MBeanServerDelegate(), true), - new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), - - MBeanServerDelegate.class.getName() + - " # SpecificationName.class.name = 'java.lang.String'", - new Wrapped(new MBeanServerDelegate(), true), - new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false), - - // CLASS - - "class = '" + Tester.class.getName() + "'", - expectTrue(), - new Wrapped(new MBeanServerDelegate(), false), - - "Class = '" + Tester.class.getName() + "'", - expectTrue(), - new Wrapped(new MBeanServerDelegate(), false), - }; - - private static final String[] incorrectQueries = { - "", " ", "25", "()", "(a = b", "a = b)", "a.3 = 5", - "a = " + Long.MAX_VALUE + "0", - "a = " + Double.MAX_VALUE + "0", - "a = " + Double.MIN_VALUE + "0", - "a = 12a5", "a = 12e5e5", "a = 12.23.34", - "a = 'can't'", "a = 'unterminated", "a = 'asdf''", - "a = \"oops", "a = \"oops\"\"", - "a like 5", "true or false", - "a ! b", "? = 3", "a = @", "a##b", - "a between b , c", "a between and c", - "a in b, c", "a in 23", "a in (2, 3", "a in (2, 3x)", - "a like \"foo\"", "a like b", "a like 23", - "like \"foo\"", "like b", "like 23", "like 'a:b'", - "5 like 'a'", "'a' like '*'", - "a not= b", "a not = b", "a not b", "a not b c", - "a = +b", "a = +'b'", "a = +true", "a = -b", "a = -'b'", - "a#5 = b", "a#'b' = c", - "a instanceof b", "a instanceof 17", "a instanceof", - // "a like 'oops\\'", "a like '[oops'", - // We don't check the above because Query.match doesn't. If LIKE - // rejected bad patterns then there would be some QueryExp values - // that could not be converted to a string and back. - - // Check that -Long.MIN_VALUE is an illegal constant. This is one more - // than Long.MAX_VALUE and, like the Java language, we only allow it - // if it is the operand of unary minus. - "a = " + Long.toString(Long.MIN_VALUE).substring(1), - }; - - public static void main(String[] args) throws Exception { - int nexti; - String failed = null; - - System.out.println("TESTING CORRECT QUERY STRINGS"); - for (int i = 0; i < queryTests.length; i = nexti) { - for (nexti = i + 1; nexti < queryTests.length; nexti++) { - if (queryTests[nexti] instanceof String) - break; - } - if (!(queryTests[i] instanceof String)) - throw new Exception("Test bug: should be string: " + queryTests[i]); - - String qs = (String) queryTests[i]; - System.out.println("Test: " + qs); - - QueryExp qe = Query.fromString(qs); - String qes = Query.toString(qe); - System.out.println("...parses to: " + qes); - final QueryExp[] queries; - if (qes.equals(qs)) - queries = new QueryExp[] {qe}; - else { - QueryExp qe2 = Query.fromString(qes); - String qes2 = Query.toString(qe2); - System.out.println("...which parses to: " + qes2); - if (qes.equals(qes2)) - queries = new QueryExp[] {qe}; - else - queries = new QueryExp[] {qe, qe2}; - } - - for (int j = i + 1; j < nexti; j++) { - Object mbean; - if (queryTests[j] instanceof Wrapped) - mbean = ((Wrapped) queryTests[j]).mbean(); - else - mbean = queryTests[j]; - boolean expect = ((ExpectedValue) queryTests[j]).expectedValue(); - for (QueryExp qet : queries) { - boolean actual = runQuery(qet, mbean); - boolean ok = (expect == actual); - System.out.println( - "..." + mbean + " -> " + actual + - (ok ? " (OK)" : " ####INCORRECT####")); - if (!ok) - failed = qs; - } - } - } - - System.out.println(); - System.out.println("TESTING INCORRECT QUERY STRINGS"); - for (String s : incorrectQueries) { - try { - QueryExp qe = Query.fromString(s); - System.out.println("###DID NOT GET ERROR:### \"" + s + "\""); - failed = s; - } catch (IllegalArgumentException e) { - String es = (e.getClass() == IllegalArgumentException.class) ? - e.getMessage() : e.toString(); - System.out.println("OK: exception for \"" + s + "\": " + es); - } - } - - if (failed == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: Last failure: " + failed); - } - - private static boolean runQuery(QueryExp qe, Object mbean) - throws Exception { - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - ObjectName name = new ObjectName("a:b=c"); - mbs.registerMBean(mbean, name); - Set names = mbs.queryNames(new ObjectName("a:*"), qe); - if (names.isEmpty()) - return false; - if (names.equals(Collections.singleton(name))) - return true; - throw new Exception("Unexpected query result set: " + names); - } - - private static interface ExpectedValue { - public boolean expectedValue(); - } - - private static class Wrapped implements ExpectedValue { - private final Object mbean; - private final boolean expect; - - Wrapped(Object mbean, boolean expect) { - this.mbean = mbean; - this.expect = expect; - } - - Object mbean() { - return mbean; - } - - public boolean expectedValue() { - return expect; - } - } - - private static class Tester implements DynamicMBean, ExpectedValue { - private final AttributeList attributes; - private final boolean expectedValue; - - Tester(AttributeList attributes, boolean expectedValue) { - this.attributes = attributes; - this.expectedValue = expectedValue; - } - - Tester(String[] names, Object[] values, boolean expectedValue) { - this(makeAttributeList(names, values), expectedValue); - } - - private static AttributeList makeAttributeList( - String[] names, Object[] values) { - if (names.length != values.length) - throw new Error("Test bug: names and values different length"); - AttributeList list = new AttributeList(); - for (int i = 0; i < names.length; i++) - list.add(new Attribute(names[i], values[i])); - return list; - } - - public Object getAttribute(String attribute) - throws AttributeNotFoundException { - for (Attribute a : attributes.asList()) { - if (a.getName().equals(attribute)) - return a.getValue(); - } - throw new AttributeNotFoundException(attribute); - } - - public void setAttribute(Attribute attribute) { - throw new UnsupportedOperationException(); - } - - public AttributeList getAttributes(String[] attributes) { - AttributeList list = new AttributeList(); - for (String attribute : attributes) { - try { - list.add(new Attribute(attribute, getAttribute(attribute))); - } catch (AttributeNotFoundException e) { - // OK: ignore, per semantics of getAttributes - } - } - return list; - } - - public AttributeList setAttributes(AttributeList attributes) { - throw new UnsupportedOperationException(); - } - - public Object invoke(String actionName, Object[] params, String[] signature) { - throw new UnsupportedOperationException(); - } - - public MBeanInfo getMBeanInfo() { - MBeanAttributeInfo mbais[] = new MBeanAttributeInfo[attributes.size()]; - for (int i = 0; i < mbais.length; i++) { - Attribute attr = attributes.asList().get(i); - String name = attr.getName(); - Object value = attr.getValue(); - String type = - ((value == null) ? new Object() : value).getClass().getName(); - mbais[i] = new MBeanAttributeInfo( - name, type, name, true, false, false); - } - return new MBeanInfo( - getClass().getName(), "descr", mbais, null, null, null); - } - - public boolean expectedValue() { - return expectedValue; - } - - @Override - public String toString() { - return attributes.toString(); - } - } - - // Method rather than field, to avoid circular init dependencies - private static String[] abcd() { - return new String[] {"A", "B", "C", "D"}; - } - - private static String[] onetwo() { - return new String[] {"One", "two"}; - } - - private static Object expectTrue(Object... attrs) { - return newTester(abcd(), attrs, true); - } - - private static Object expectFalse(Object... attrs) { - return newTester(abcd(), attrs, false); - } - - private static Object expectTrueOneTwo(Object... attrs) { - return newTester(onetwo(), attrs, true); - } - - private static Object expectFalseOneTwo(Object... attrs) { - return newTester(onetwo(), attrs, false); - } - - private static Object newTester(String[] names, Object[] attrs, boolean expect) { - AttributeList list = new AttributeList(); - for (int i = 0; i < attrs.length; i++) - list.add(new Attribute(names[i], attrs[i])); - return new Tester(list, expect); - } -} diff --git a/test/javax/management/remote/mandatory/connection/CloseServerTest.java b/test/javax/management/remote/mandatory/connection/CloseServerTest.java index c5b1b19c3..ca92bc7cf 100644 --- a/test/javax/management/remote/mandatory/connection/CloseServerTest.java +++ b/test/javax/management/remote/mandatory/connection/CloseServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003 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 @@ -31,16 +31,11 @@ * @run main CloseServerTest */ -import com.sun.jmx.remote.util.EnvHelp; import java.net.MalformedURLException; +import java.io.IOException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; import javax.management.*; import javax.management.remote.*; -import javax.management.remote.rmi.RMIConnectorServer; public class CloseServerTest { private static final String[] protocols = {"rmi", "iiop", "jmxmp"}; @@ -136,54 +131,40 @@ public class CloseServerTest { server.stop(); - List> envs = Arrays.asList( - Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"), - Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "true")); - - for (Map env : envs) { - System.out.println( - ">>>>>>>> " + RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE + - " = " + env.get(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE)); - - // with a client listener, but close the server first - System.out.println(">>> Open, start a server, create a client, " + - "add a listener, close the server then the client."); - server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs); - server.start(); + // with a client listener, but close the server first + System.out.println(">>> Open, start a server, create a client, add a listener, close the server then the client."); + server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs); + server.start(); - addr = server.getAddress(); - client = JMXConnectorFactory.newJMXConnector(addr, null); - client.connect(null); + addr = server.getAddress(); + client = JMXConnectorFactory.newJMXConnector(addr, null); + client.connect(null); - mserver = client.getMBeanServerConnection(); - mserver.addNotificationListener(delegateName, dummyListener, null, null); + mserver = client.getMBeanServerConnection(); + mserver.addNotificationListener(delegateName, dummyListener, null, null); - server.stop(); + server.stop(); - try { - client.close(); - } catch (Exception e) { - // ok, it is because the server has been closed. - } + try { + client.close(); + } catch (Exception e) { + // ok, it is because the server has been closed. + } - // with a client listener, but close the client first - System.out.println(">>> Open, start a server, create a client, " + - "add a listener, close the client then the server."); - server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs); - server.start(); + // with a client listener, but close the client first + System.out.println(">>> Open, start a server, create a client, add a listener, close the client then the server."); + server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs); + server.start(); - addr = server.getAddress(); - client = JMXConnectorFactory.newJMXConnector(addr, null); - client.connect(null); + addr = server.getAddress(); + client = JMXConnectorFactory.newJMXConnector(addr, null); + client.connect(null); - mserver = client.getMBeanServerConnection(); - mserver.addNotificationListener(delegateName, dummyListener, null, null); + mserver = client.getMBeanServerConnection(); + mserver.addNotificationListener(delegateName, dummyListener, null, null); - client.close(); - server.stop(); - } + client.close(); + server.stop(); } catch (MalformedURLException e) { System.out.println(">>> Skipping unsupported URL " + u); return true; diff --git a/test/javax/management/remote/mandatory/connection/DeadLockTest.java b/test/javax/management/remote/mandatory/connection/DeadLockTest.java index 5ea4f8d50..52f2b3ca0 100644 --- a/test/javax/management/remote/mandatory/connection/DeadLockTest.java +++ b/test/javax/management/remote/mandatory/connection/DeadLockTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004 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 @@ -37,7 +37,6 @@ import java.util.HashMap; import javax.management.*; import javax.management.remote.*; -import javax.management.remote.rmi.RMIConnectorServer; public class DeadLockTest { private static final String[] protocols = {"rmi", "iiop", "jmxmp"}; @@ -73,9 +72,6 @@ public class DeadLockTest { // disable the client ping env.put("jmx.remote.x.client.connection.check.period", "0"); - // ensure we are not internally using the Event Service on the server - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); - try { u = new JMXServiceURL(proto, null, 0); server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs); diff --git a/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java b/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java index b157bf049..caf0bc770 100644 --- a/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java +++ b/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-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 @@ -50,8 +50,6 @@ import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import com.sun.jmx.remote.util.EnvHelp; -import java.util.Collections; -import javax.management.remote.rmi.RMIConnectorServer; public class IdleTimeoutTest { public static void main(String[] args) throws Exception { @@ -90,13 +88,8 @@ public class IdleTimeoutTest { private static long getIdleTimeout(MBeanServer mbs, JMXServiceURL url) throws Exception { - // If the connector server is using the Event Service, then connections - // never time out. This is by design. - Map env = - Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); JMXConnectorServer server = - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); server.start(); try { url = server.getAddress(); @@ -171,7 +164,6 @@ public class IdleTimeoutTest { Map idleMap = new HashMap(); idleMap.put(EnvHelp.SERVER_CONNECTION_TIMEOUT, new Long(timeout)); - idleMap.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url,idleMap,mbs); diff --git a/test/javax/management/remote/mandatory/connection/RMIExitTest.java b/test/javax/management/remote/mandatory/connection/RMIExitTest.java index 8b8d6e567..5d3649364 100644 --- a/test/javax/management/remote/mandatory/connection/RMIExitTest.java +++ b/test/javax/management/remote/mandatory/connection/RMIExitTest.java @@ -35,8 +35,6 @@ import java.net.MalformedURLException; import java.io.IOException; -import java.util.Collections; -import java.util.Map; import javax.management.MBeanServerFactory; import javax.management.MBeanServer; import javax.management.ObjectName; @@ -49,7 +47,6 @@ import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.rmi.RMIConnectorServer; /** * VM shutdown hook. Test that the hook is called less than 5 secs @@ -85,15 +82,12 @@ public class RMIExitTest { public static void main(String[] args) { System.out.println("Start test"); Runtime.getRuntime().addShutdownHook(new TimeChecker()); - test(false); - test(true); + test(); exitStartTime = System.currentTimeMillis(); System.out.println("End test"); } - private static void test(boolean eventService) { - System.out.println( - "---testing with" + (eventService ? "" : "out") + " Event Service"); + private static void test() { try { JMXServiceURL u = new JMXServiceURL("rmi", null, 0); JMXConnectorServer server; @@ -112,11 +106,8 @@ public class RMIExitTest { } }; - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); server = JMXConnectorServerFactory.newJMXConnectorServer(u, - env, + null, mbs); server.start(); diff --git a/test/javax/management/remote/mandatory/connection/ReconnectTest.java b/test/javax/management/remote/mandatory/connection/ReconnectTest.java index 6be0e9e39..674b830e5 100644 --- a/test/javax/management/remote/mandatory/connection/ReconnectTest.java +++ b/test/javax/management/remote/mandatory/connection/ReconnectTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2004 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 @@ -33,10 +33,10 @@ import java.util.*; import java.net.MalformedURLException; +import java.io.IOException; import javax.management.*; import javax.management.remote.*; -import javax.management.remote.rmi.RMIConnectorServer; public class ReconnectTest { private static final String[] protocols = {"rmi", "iiop", "jmxmp"}; @@ -48,7 +48,6 @@ public class ReconnectTest { String timeout = "1000"; env.put("jmx.remote.x.server.connection.timeout", timeout); env.put("jmx.remote.x.client.connection.check.period", timeout); - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); } public static void main(String[] args) throws Exception { diff --git a/test/javax/management/remote/mandatory/connectorServer/CloseConnectionTest.java b/test/javax/management/remote/mandatory/connectorServer/CloseConnectionTest.java deleted file mode 100644 index 54d05f842..000000000 --- a/test/javax/management/remote/mandatory/connectorServer/CloseConnectionTest.java +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2003-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. - * - * 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. - */ - - -/* - * @test - * @bug 6332907 - * @summary test the ability for connector server to close individual connections - * @author Shanliang JIANG - * @run clean CloseConnectionTest - * @run build CloseConnectionTest - * @run main CloseConnectionTest - */ -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.management.MBeanServerFactory; - -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; - -public class CloseConnectionTest { - - public static void main(String[] args) throws Exception { - System.out.println(">>> Test the ability for connector server to close " + - "individual connections."); - - final String[] protos = new String[]{"rmi", "iiop", "jmxmp"}; - for (String p : protos) { - System.out.println("\n>>> Testing the protocol " + p); - JMXServiceURL addr = new JMXServiceURL(p, null, 0); - System.out.println(">>> Creating a JMXConnectorServer on " + addr); - JMXConnectorServer server = null; - try { - server = JMXConnectorServerFactory.newJMXConnectorServer(addr, - null, - MBeanServerFactory.createMBeanServer()); - } catch (Exception e) { - System.out.println(">>> Skip the protocol: " + p); - continue; - } - - test1(server); - test2(server); - - server.stop(); - } - - System.out.println(">>> Bye bye!"); - } - - private static void test1(JMXConnectorServer server) throws Exception { - try { - server.closeConnection("toto"); - // not started, known id - throw new RuntimeException("An IllegalArgumentException is not thrown."); - } catch (IllegalStateException e) { - System.out.println(">>> Test1: Got expected IllegalStateException: " + e); - } - - server.start(); - System.out.println(">>>Test1 Started the server on " + server.getAddress()); - - try { - server.closeConnection("toto"); - throw new RuntimeException("An IllegalArgumentException is not thrown."); - } catch (IllegalArgumentException e) { - System.out.println(">> Test1: Got expected IllegalArgumentException: " + e); - } - - MyListener listener = new MyListener(); - server.addNotificationListener(listener, null, null); - - System.out.println(">>> Test1: Connecting a client to the server ..."); - final JMXConnector conn = JMXConnectorFactory.connect(server.getAddress()); - conn.getMBeanServerConnection().getDefaultDomain(); - final String id1 = conn.getConnectionId(); - - listener.wait(JMXConnectionNotification.OPENED, timeout); - - System.out.println(">>> Test1: Closing the connection: " + conn.getConnectionId()); - server.closeConnection(id1); - listener.wait(JMXConnectionNotification.CLOSED, timeout); - - System.out.println(">>> Test1: Using again the connector whose connection " + - "should be closed by the server, it should reconnect " + - "automatically to the server and get a new connection id."); - conn.getMBeanServerConnection().getDefaultDomain(); - final String id2 = conn.getConnectionId(); - listener.wait(JMXConnectionNotification.OPENED, timeout); - - if (id1.equals(id2)) { - throw new RuntimeException("Failed, the first client connection is not closed."); - } - - System.out.println(">>> Test1: Greate, we get a new connection id " + id2 + - ", the first one is closed as expected."); - - System.out.println(">>> Test1: Closing the client."); - conn.close(); - System.out.println(">>> Test1: Stopping the server."); - server.removeNotificationListener(listener); - } - - private static void test2(JMXConnectorServer server) throws Exception { - System.out.println(">>> Test2 close a connection before " + - "the client can use it..."); - final Killer killer = new Killer(server); - server.addNotificationListener(killer, null, null); - - System.out.println(">>> Test2 Connecting a client to the server ..."); - final JMXConnector conn; - try { - conn = JMXConnectorFactory.connect(server.getAddress()); - throw new RuntimeException(">>> Failed, do not receive an " + - "IOException telling the connection is refused."); - } catch (IOException ioe) { - System.out.println(">>> Test2 got expected IOException: "+ioe); - } - } - - private static class MyListener implements NotificationListener { - public void handleNotification(Notification n, Object hb) { - if (n instanceof JMXConnectionNotification) { - synchronized (received) { - received.add((JMXConnectionNotification) n); - received.notify(); - } - } - } - - public JMXConnectionNotification wait(String type, long timeout) - throws Exception { - JMXConnectionNotification waited = null; - long toWait = timeout; - long deadline = System.currentTimeMillis() + timeout; - synchronized (received) { - while (waited == null && toWait > 0) { - received.wait(toWait); - for (JMXConnectionNotification n : received) { - if (type.equals(n.getType())) { - waited = n; - break; - } - } - received.clear(); - toWait = deadline - System.currentTimeMillis(); - } - } - - if (waited == null) { - throw new RuntimeException("Do not receive expected notification " + type); - } else { - System.out.println(">>> Received expected notif: "+type+ - " "+waited.getConnectionId()); - } - - return waited; - } - - final List received = - new ArrayList(); - } - - private static class Killer implements NotificationListener { - public Killer(JMXConnectorServer server) { - this.server = server; - } - public void handleNotification(Notification n, Object hb) { - if (n instanceof JMXConnectionNotification) { - if (JMXConnectionNotification.OPENED.equals(n.getType())) { - final JMXConnectionNotification cn = - (JMXConnectionNotification)n; - try { - System.out.println(">>> Killer: close the connection "+ - cn.getConnectionId()); - server.closeConnection(cn.getConnectionId()); - } catch (Exception e) { - // impossible? - e.printStackTrace(); - System.exit(1); - } - } - } - } - - private final JMXConnectorServer server; - } - - private static final long timeout = 6000; -} diff --git a/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java b/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java deleted file mode 100644 index e1dcbcb6e..000000000 --- a/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java +++ /dev/null @@ -1,279 +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. - * - * 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. - */ - -import java.util.NoSuchElementException; -import java.util.Random; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerFactory; -import javax.management.remote.IdentityMBeanServerForwarder; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.MBeanServerForwarder; - -/* - * @test - * @bug 6218920 - * @summary Tests manipulation of MBeanServerForwarder chains. - * @author Eamonn McManus - */ -import javax.management.remote.rmi.RMIConnectorServer; - -public class ForwarderChainTest { - private static final TestMBeanServerForwarder[] forwarders = - new TestMBeanServerForwarder[10]; - static { - for (int i = 0; i < forwarders.length; i++) - forwarders[i] = new TestMBeanServerForwarder(i); - } - - private static class TestMBeanServerForwarder - extends IdentityMBeanServerForwarder { - private final int index; - volatile int defaultDomainCount; - - TestMBeanServerForwarder(int index) { - this.index = index; - } - - @Override - public String getDefaultDomain() { - defaultDomainCount++; - return super.getDefaultDomain(); - } - - @Override - public String toString() { - return "forwarders[" + index + "]"; - } - } - - private static String failure; - - public static void main(String[] args) throws Exception { - - System.out.println("===Test with newly created, unattached server==="); - - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///"); - JMXConnectorServer cs = new RMIConnectorServer(url, null); - test(cs, null); - - System.out.println("===Test with server attached to MBS==="); - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - cs = new RMIConnectorServer(url, null, mbs); - test(cs, mbs); - - System.out.println("===Remove any leftover forwarders==="); - MBeanServerForwarder systemMBSF = cs.getSystemMBeanServerForwarder(); - // Real code would just do systemMBSF.setMBeanServer(mbs). - while (true) { - MBeanServer xmbs = systemMBSF.getMBeanServer(); - if (!(xmbs instanceof MBeanServerForwarder)) - break; - cs.removeMBeanServerForwarder((MBeanServerForwarder) xmbs); - } - expectChain(cs, "U", mbs); - - System.out.println("===Ensure forwarders are called==="); - cs.setMBeanServerForwarder(forwarders[0]); - systemMBSF.setMBeanServer(forwarders[1]); - forwarders[1].setMBeanServer(forwarders[0]); - expectChain(cs, "1U0", mbs); - cs.start(); - if (forwarders[0].defaultDomainCount != 0 || - forwarders[1].defaultDomainCount != 0) { - fail("defaultDomainCount not zero"); - } - JMXServiceURL addr = cs.getAddress(); - JMXConnector cc = JMXConnectorFactory.connect(addr); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - mbsc.getDefaultDomain(); - cc.close(); - cs.stop(); - for (boolean system : new boolean[] {false, true}) { - TestMBeanServerForwarder mbsf = system ? forwarders[1] : forwarders[0]; - if (mbsf.defaultDomainCount != 1) { - fail((system ? "System" : "User") + " forwarder called " + - mbsf.defaultDomainCount + " times"); - } - } - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception("TEST FAILED: " + failure); - } - - private static void test(JMXConnectorServer cs, MBeanServer end) { - // A newly-created connector server might have system forwarders, - // so get rid of those. - MBeanServerForwarder systemMBSF = cs.getSystemMBeanServerForwarder(); - systemMBSF.setMBeanServer(cs.getMBeanServer()); - - expectChain(cs, "U", end); - - System.out.println("Add a user forwarder"); - cs.setMBeanServerForwarder(forwarders[0]); - expectChain(cs, "U0", end); - - System.out.println("Add another user forwarder"); - cs.setMBeanServerForwarder(forwarders[1]); - expectChain(cs, "U10", end); - - System.out.println("Add a system forwarder"); - forwarders[2].setMBeanServer(systemMBSF.getMBeanServer()); - systemMBSF.setMBeanServer(forwarders[2]); - expectChain(cs, "2U10", end); - - System.out.println("Add another user forwarder"); - cs.setMBeanServerForwarder(forwarders[3]); - expectChain(cs, "2U310", end); - - System.out.println("Add another system forwarder"); - forwarders[4].setMBeanServer(systemMBSF.getMBeanServer()); - systemMBSF.setMBeanServer(forwarders[4]); - expectChain(cs, "42U310", end); - - System.out.println("Remove the first user forwarder"); - cs.removeMBeanServerForwarder(forwarders[3]); - expectChain(cs, "42U10", end); - - System.out.println("Remove the last user forwarder"); - cs.removeMBeanServerForwarder(forwarders[0]); - expectChain(cs, "42U1", end); - - System.out.println("Remove the first system forwarder"); - cs.removeMBeanServerForwarder(forwarders[4]); - expectChain(cs, "2U1", end); - - System.out.println("Remove the last system forwarder"); - cs.removeMBeanServerForwarder(forwarders[2]); - expectChain(cs, "U1", end); - - System.out.println("Remove the last forwarder"); - cs.removeMBeanServerForwarder(forwarders[1]); - expectChain(cs, "U", end); - - System.out.println("---Doing random manipulations---"); - // In this loop we pick one of the forwarders at random each time. - // If it is already in the chain, then we remove it. If it is not - // in the chain, then we do one of three things: try to remove it - // (expecting an exception); add it to the user chain; or add it - // to the system chain. - // A subtle point is that if there is no MBeanServer then - // cs.setMBeanServerForwarder(mbsf) does not change mbsf.getMBeanServer(). - // Since we're recycling a random forwarder[i], we explicitly - // call mbsf.setMBeanServer(null) in this case. - String chain = "U"; - Random r = new Random(); - for (int i = 0; i < 50; i++) { - int fwdi = r.nextInt(10); - MBeanServerForwarder mbsf = forwarders[fwdi]; - char c = (char) ('0' + fwdi); - int ci = chain.indexOf(c); - if (ci >= 0) { - System.out.println("Remove " + c); - cs.removeMBeanServerForwarder(mbsf); - chain = chain.substring(0, ci) + chain.substring(ci + 1); - } else { - switch (r.nextInt(3)) { - case 0: { // try to remove it - try { - System.out.println("Try to remove absent " + c); - cs.removeMBeanServerForwarder(mbsf); - fail("Remove succeeded but should not have"); - return; - } catch (NoSuchElementException e) { - } - break; - } - case 1: { // add it to the user chain - System.out.println("Add " + c + " to user chain"); - if (cs.getMBeanServer() == null) - mbsf.setMBeanServer(null); - cs.setMBeanServerForwarder(mbsf); - int postu = chain.indexOf('U') + 1; - chain = chain.substring(0, postu) + c + - chain.substring(postu); - break; - } - case 2: { // add it to the system chain - System.out.println("Add " + c + " to system chain"); - mbsf.setMBeanServer(systemMBSF.getMBeanServer()); - systemMBSF.setMBeanServer(mbsf); - chain = c + chain; - break; - } - } - } - expectChain(cs, chain, end); - } - } - - /* - * Check that the forwarder chain has the expected contents. The forwarders - * are encoded as a string. For example, "12U34" means that the system - * chain contains forwarders[1] followed by forwarders[2], and the user - * chain contains forwarders[3] followed by forwarders[4]. Since the - * user chain is attached to the end of the system chain, another way to - * look at this is that the U marks the transition from one to the other. - * - * After traversing the chains, we should be pointing at "end". - */ - private static void expectChain( - JMXConnectorServer cs, String chain, MBeanServer end) { - System.out.println("...expected chain: " + chain); - MBeanServer curr = cs.getSystemMBeanServerForwarder().getMBeanServer(); - int i = 0; - while (i < chain.length()) { - char c = chain.charAt(i); - if (c == 'U') { - if (cs.getMBeanServer() != curr) { - fail("User chain should have started here: " + curr); - return; - } - } else { - int fwdi = c - '0'; - MBeanServerForwarder forwarder = forwarders[fwdi]; - if (curr != forwarder) { - fail("Expected forwarder " + c + " here: " + curr); - return; - } - curr = ((MBeanServerForwarder) curr).getMBeanServer(); - } - i++; - } - if (curr != end) { - fail("End of chain is " + curr + ", should be " + end); - return; - } - System.out.println("...OK"); - } - - private static void fail(String msg) { - System.out.println("FAILED: " + msg); - failure = msg; - } -} diff --git a/test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java b/test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java deleted file mode 100644 index 25efde9dd..000000000 --- a/test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java +++ /dev/null @@ -1,193 +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. - * - * 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. - */ - -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.management.ClientContext; -import javax.management.MBeanServer; -import javax.management.event.EventClientDelegate; -import javax.management.remote.JMXConnectorServer; - -/* - * @test - * @bug 6663757 - * @summary Tests standard MBeanServerForwarders introduced by connector server - * options. - * @author Eamonn McManus - */ -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.MBeanServerForwarder; - -public class StandardForwardersTest { - private static String failure; - - private static class Forwarder { - private final String attribute; - private final boolean defaultEnabled; - private final Class expectedClass; - - public Forwarder(String attribute, boolean defaultEnabled, - Class expectedClass) { - this.attribute = attribute; - this.defaultEnabled = defaultEnabled; - this.expectedClass = expectedClass; - } - } - - private static enum Status {DISABLED, ENABLED, DEFAULT} - - public static void main(String[] args) throws Exception { - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); - - MBeanServerForwarder ctxFwd = ClientContext.newContextForwarder(mbs, null); - Forwarder ctx = new Forwarder( - JMXConnectorServer.CONTEXT_FORWARDER, true, ctxFwd.getClass()); - - MBeanServerForwarder locFwd = - ClientContext.newLocalizeMBeanInfoForwarder(mbs); - Forwarder loc = new Forwarder( - JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER, false, - locFwd.getClass()); - - MBeanServerForwarder ecdFwd = - EventClientDelegate.newForwarder(mbs, null); - Forwarder ecd = new Forwarder( - JMXConnectorServer.EVENT_CLIENT_DELEGATE_FORWARDER, true, - ecdFwd.getClass()); - - Forwarder[] forwarders = {ctx, loc, ecd}; - - // Now go through every combination of forwarders. Each forwarder - // may be explicitly enabled, explicitly disabled, or left to its - // default value. - int nStatus = Status.values().length; - int limit = (int) Math.pow(nStatus, forwarders.length); - for (int i = 0; i < limit; i++) { - Status[] status = new Status[forwarders.length]; - int ii = i; - for (int j = 0; j < status.length; j++) { - status[j] = Status.values()[ii % nStatus]; - ii /= nStatus; - } - Map env = new HashMap(); - String test = ""; - for (int j = 0; j < status.length; j++) { - if (!test.equals("")) - test += "; "; - test += forwarders[j].attribute; - switch (status[j]) { - case DISABLED: - test += "=false"; - env.put(forwarders[j].attribute, "false"); - break; - case ENABLED: - test += "=true"; - env.put(forwarders[j].attribute, "true"); - break; - case DEFAULT: - test += "=default(" + forwarders[j].defaultEnabled + ")"; - break; - } - } - boolean consistent = isConsistent(env); - test += "; (" + (consistent ? "" : "in") + "consistent)"; - System.out.println(test); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///"); - try { - JMXConnectorServer cs = - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); - if (!consistent) { - fail("Inconsistent attributes should have been rejected " + - "but were not"); - } - checkForwarders(cs, forwarders, status); - } catch (IllegalArgumentException e) { - if (consistent) { - fail("Consistent attributes provoked IllegalArgumentException"); - e.printStackTrace(System.out); - } - } - } - - if (failure == null) - System.out.println("TEST PASSED"); - else - throw new Exception(failure); - } - - // Check that the classes of the forwarders in the system chain correspond - // to what we expect given the options we have passed. This check is a bit - // superficial in the sense that a forwarder might be for example a - // SingleMBeanForwarderHandler but that doesn't prove that it is the - // right Single MBean. Nevertheless the test should expose any severe - // wrongness. - // - // The check here makes some assumptions that could become untrue in the - // future. First, it assumes that the forwarders that are added have - // exactly the classes that are in the Forwarder[] array. So for example - // the forwarder for CONTEXT_FORWARDER must be of the same class as an - // explicit call to ClientContext.newContextForwarder. The spec doesn't - // require that - it only requires that the forwarder have the same - // behaviour. The second assumption is that the connector server doesn't - // add any forwarders of its own into the system chain, and again the spec - // doesn't disallow that. - private static void checkForwarders( - JMXConnectorServer cs, Forwarder[] forwarders, Status[] status) { - List> expectedClasses = new ArrayList>(); - for (int i = 0; i < forwarders.length; i++) { - if (status[i] == Status.ENABLED || - (status[i] == Status.DEFAULT && forwarders[i].defaultEnabled)) - expectedClasses.add(forwarders[i].expectedClass); - } - MBeanServer stop = cs.getMBeanServer(); - List> foundClasses = new ArrayList>(); - for (MBeanServer mbs = cs.getSystemMBeanServerForwarder().getMBeanServer(); - mbs != stop; - mbs = ((MBeanServerForwarder) mbs).getMBeanServer()) { - foundClasses.add(mbs.getClass()); - } - if (!expectedClasses.equals(foundClasses)) { - fail("Incorrect forwarder chain: expected " + expectedClasses + - "; found " + foundClasses); - } - } - - // env is consistent if either (a) localizer is not enabled or (b) - // localizer is enabled and context is enabled. - private static boolean isConsistent(Map env) { - String ctxS = env.get(JMXConnectorServer.CONTEXT_FORWARDER); - boolean ctx = (ctxS == null) ? true : Boolean.parseBoolean(ctxS); - String locS = env.get(JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER); - boolean loc = (locS == null) ? false : Boolean.parseBoolean(locS); - return !loc || ctx; - } - - private static void fail(String why) { - System.out.println("FAILED: " + why); - failure = why; - } -} diff --git a/test/javax/management/remote/mandatory/loading/MissingClassTest.java b/test/javax/management/remote/mandatory/loading/MissingClassTest.java index 98dbdd290..1f4d6f229 100644 --- a/test/javax/management/remote/mandatory/loading/MissingClassTest.java +++ b/test/javax/management/remote/mandatory/loading/MissingClassTest.java @@ -124,16 +124,7 @@ public class MissingClassTest { } private static boolean test(String proto) throws Exception { - boolean ok = true; - for (boolean eventService : new boolean[] {false, true}) - ok &= test(proto, eventService); - return ok; - } - - private static boolean test(String proto, boolean eventService) - throws Exception { - System.out.println("Testing for proto " + proto + " with" + - (eventService ? "" : "out") + " Event Service"); + System.out.println("Testing for proto " + proto); boolean ok = true; @@ -145,8 +136,6 @@ public class MissingClassTest { Map serverMap = new HashMap(); serverMap.put(JMXConnectorServerFactory.DEFAULT_CLASS_LOADER, serverLoader); - serverMap.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); // make sure no auto-close at server side serverMap.put("jmx.remote.x.server.connection.timeout", "888888888"); diff --git a/test/javax/management/remote/mandatory/notif/AddRemoveTest.java b/test/javax/management/remote/mandatory/notif/AddRemoveTest.java index 667badc7f..126a761ff 100644 --- a/test/javax/management/remote/mandatory/notif/AddRemoveTest.java +++ b/test/javax/management/remote/mandatory/notif/AddRemoveTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003 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 @@ -33,12 +33,10 @@ */ import java.net.MalformedURLException; +import java.io.IOException; -import java.util.Collections; -import java.util.Map; import javax.management.*; import javax.management.remote.*; -import javax.management.remote.rmi.RMIConnectorServer; public class AddRemoveTest { private static final String[] protocols = {"rmi", "iiop", "jmxmp"}; @@ -71,16 +69,9 @@ public class AddRemoveTest { } } - private static boolean test(String proto) throws Exception { - boolean ok = test(proto, false); - ok &= test(proto, true); - return ok; - } - - private static boolean test(String proto, boolean eventService) + private static boolean test(String proto) throws Exception { - System.out.println(">>> Test for protocol " + proto + " with" + - (eventService ? "" : "out") + " event service"); + System.out.println(">>> Test for protocol " + proto); JMXServiceURL u = new JMXServiceURL(proto, null, 0); JMXConnectorServer server; JMXServiceURL addr; @@ -98,10 +89,7 @@ public class AddRemoveTest { try { // with a client listener, but close the server first - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); - server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs); + server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs); server.start(); addr = server.getAddress(); diff --git a/test/javax/management/remote/mandatory/notif/DiffHBTest.java b/test/javax/management/remote/mandatory/notif/DiffHBTest.java index 887d94436..704e9aa17 100644 --- a/test/javax/management/remote/mandatory/notif/DiffHBTest.java +++ b/test/javax/management/remote/mandatory/notif/DiffHBTest.java @@ -32,11 +32,8 @@ */ -import java.util.Collections; -import java.util.Map; import javax.management.*; import javax.management.remote.*; -import javax.management.remote.rmi.RMIConnectorServer; /** * This test registeres an unique listener with two different handbacks, @@ -80,33 +77,14 @@ public class DiffHBTest { } private static String test(String proto) throws Exception { - String ret = null; - for (boolean eventService : new boolean[] {false, true}) { - String s = test(proto, eventService); - if (s != null) { - if (ret == null) - ret = s; - else - ret = ret + "; " + s; - } - } - return ret; - } - - private static String test(String proto, boolean eventService) - throws Exception { - System.out.println(">>> Test for protocol " + proto + " with" + - (eventService ? "" : "out") + " event service"); + System.out.println(">>> Test for protocol " + proto); JMXServiceURL u = new JMXServiceURL(proto, null, 0); JMXConnectorServer server; JMXConnector client; try { - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); server = - JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs); + JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs); server.start(); JMXServiceURL addr = server.getAddress(); client = JMXConnectorFactory.connect(addr, null); diff --git a/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java b/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java index 2d098bf4d..0e7a69d34 100644 --- a/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java +++ b/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java @@ -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 @@ -29,12 +29,11 @@ * @author Shanliang JIANG * @run clean EmptyDomainNotificationTest * @run build EmptyDomainNotificationTest - * @run main EmptyDomainNotificationTest classic - * @run main EmptyDomainNotificationTest event + * @run main EmptyDomainNotificationTest */ -import java.util.Collections; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; import javax.management.MBeanServerFactory; @@ -47,7 +46,6 @@ import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; public class EmptyDomainNotificationTest { @@ -82,25 +80,11 @@ public class EmptyDomainNotificationTest { public static void main(String[] args) throws Exception { - String type = args[0]; - boolean eventService; - if (type.equals("classic")) - eventService = false; - else if (type.equals("event")) - eventService = true; - else - throw new IllegalArgumentException(type); - final MBeanServer mbs = MBeanServerFactory.createMBeanServer(); final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); - - JMXConnectorServer server = - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); server.start(); JMXConnector client = JMXConnectorFactory.connect(server.getAddress(), null); diff --git a/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java b/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java index ea50947ad..56f0cc403 100644 --- a/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java +++ b/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java @@ -51,8 +51,6 @@ * been compiled by the second. */ -import java.util.Collections; -import java.util.Map; import java.util.concurrent.Semaphore; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; @@ -67,7 +65,6 @@ import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; public class ListenerScaleTest { private static final int WARMUP_WITH_ONE_MBEAN = 1000; @@ -128,20 +125,12 @@ public class ListenerScaleTest { }; public static void main(String[] args) throws Exception { - test(false); - test(true); - } - - private static void test(boolean eventService) throws Exception { MBeanServer mbs = MBeanServerFactory.newMBeanServer(); Sender sender = new Sender(); mbs.registerMBean(sender, testObjectName); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); JMXConnectorServer cs = - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); cs.start(); JMXServiceURL addr = cs.getAddress(); JMXConnector cc = JMXConnectorFactory.connect(addr); diff --git a/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java b/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java index 4fad7d03a..254e8712b 100644 --- a/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java +++ b/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2004-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 @@ -31,11 +31,11 @@ * @run main NotifBufferSizePropertyNameTest */ +import java.io.IOException; import java.util.*; import javax.management.*; import javax.management.remote.*; -import javax.management.remote.rmi.RMIConnectorServer; /** * This class tests also the size of a server notification buffer. @@ -88,9 +88,6 @@ public class NotifBufferSizePropertyNameTest { private static void test(Map env) throws Exception { final MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - env = new HashMap((env == null) ? Collections.emptyMap() : env); - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); - mbs.registerMBean(new NotificationEmitter(), oname); JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer( url, diff --git a/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java b/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java index eb3cd45be..e14244212 100644 --- a/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java +++ b/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java @@ -45,7 +45,6 @@ import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; /** * "This test checks for a bug whereby reconnection did not work if (a) it was @@ -74,7 +73,6 @@ public class NotifReconnectDeadlockTest { Map env = new HashMap(2); env.put("jmx.remote.x.server.connection.timeout", new Long(serverTimeout)); env.put("jmx.remote.x.client.connection.check.period", new Long(Long.MAX_VALUE)); - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); final MBeanServer mbs = MBeanServerFactory.newMBeanServer(); diff --git a/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java b/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java index c4988dd03..172164769 100644 --- a/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java +++ b/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-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 @@ -32,8 +32,6 @@ */ import java.net.MalformedURLException; -import java.util.Collections; -import java.util.Map; import javax.management.MBeanServerFactory; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; @@ -46,7 +44,6 @@ import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; public class NotificationBufferCreationTest { private static final MBeanServer mbs = @@ -89,8 +86,6 @@ public class NotificationBufferCreationTest { JMXServiceURL u = null; try { u = new JMXServiceURL(protocol, null, 0); - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"); server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, diff --git a/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java b/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java index ff3c51661..3698da49d 100644 --- a/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java +++ b/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java @@ -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 @@ -35,9 +35,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.MalformedURLException; -import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.Vector; import javax.management.*; @@ -90,7 +88,6 @@ import javax.management.remote.*; * If the logic for adding the notification buffer's listener is incorrect * we could remove zero or two notifications from an MBean. */ -import javax.management.remote.rmi.RMIConnectorServer; public class NotificationBufferDeadlockTest { public static void main(String[] args) throws Exception { System.out.println("Check no deadlock if notif sent while initial " + @@ -112,13 +109,7 @@ public class NotificationBufferDeadlockTest { } private static void test(String proto) throws Exception { - test(proto, false); - test(proto, true); - } - - private static void test(String proto, boolean eventService) throws Exception { - System.out.println("Testing protocol " + proto + " with" + - (eventService ? "" : "out") + " event service"); + System.out.println("Testing protocol " + proto); MBeanServer mbs = MBeanServerFactory.newMBeanServer(); ObjectName testName = newName(); DeadlockTest test = new DeadlockTest(); @@ -126,11 +117,8 @@ public class NotificationBufferDeadlockTest { JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + ":///"); JMXConnectorServer cs; try { - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); cs = - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs); } catch (MalformedURLException e) { System.out.println("...protocol not supported, ignoring"); return; diff --git a/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java b/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java index 0d132a4a0..a3a87cdf5 100644 --- a/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java +++ b/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java @@ -29,16 +29,11 @@ * @author Luis-Miguel Alventosa * @run clean NotificationEmissionTest * @run build NotificationEmissionTest - * @run main NotificationEmissionTest 1 Classic - * @run main NotificationEmissionTest 2 Classic - * @run main NotificationEmissionTest 3 Classic - * @run main NotificationEmissionTest 4 Classic - * @run main NotificationEmissionTest 5 Classic - * @run main NotificationEmissionTest 1 EventService - * @run main NotificationEmissionTest 2 EventService - * @run main NotificationEmissionTest 3 EventService - * @run main NotificationEmissionTest 4 EventService - * @run main NotificationEmissionTest 5 EventService + * @run main NotificationEmissionTest 1 + * @run main NotificationEmissionTest 2 + * @run main NotificationEmissionTest 3 + * @run main NotificationEmissionTest 4 + * @run main NotificationEmissionTest 5 */ import java.io.File; @@ -61,15 +56,9 @@ import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXPrincipal; import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; import javax.security.auth.Subject; public class NotificationEmissionTest { - private final boolean eventService; - - public NotificationEmissionTest(boolean eventService) { - this.eventService = eventService; - } public class CustomJMXAuthenticator implements JMXAuthenticator { public Subject authenticate(Object credentials) { @@ -228,13 +217,8 @@ public class NotificationEmissionTest { // final Map env = new HashMap(); env.put("jmx.remote.authenticator", new CustomJMXAuthenticator()); - env.put(RMIConnectorServer.EVENT_CLIENT_DELEGATE_FORWARDER, - Boolean.toString(eventService)); - if (prop) { - echo("Setting jmx.remote.x.check.notification.emission to " + - propValue); + if (prop) env.put("jmx.remote.x.check.notification.emission", propValue); - } // Create the JMXServiceURL // @@ -302,14 +286,11 @@ public class NotificationEmissionTest { // If the check is effective and we're using policy.negative, // then we should see the two notifs sent by nb2 (of which one // has a getSource() that is nb3), but not the notif sent by nb1. - // Otherwise we should see all three notifs. If we're using the - // Event Service with a Security Manager then the logic to - // reapply the addNL permission test for every notification is - // always enabled, regardless of the value of - // jmx.remote.x.check.notification.emission. Otherwise, the - // test is only applied if that property is explicitly true. + // Otherwise we should see all three notifs. The check is only + // effective if the property jmx.remote.x.check.notification.emission + // is explicitly true and there is a security manager. int expectedNotifs = - ((prop || eventService) && sm && !policyPositive) ? 2 : 3; + (prop && sm && !policyPositive) ? 2 : 3; // Wait for notifications to be emitted // @@ -324,15 +305,14 @@ public class NotificationEmissionTest { mbsc.removeNotificationListener(nb2, li); int result = 0; - List sources = new ArrayList(); + List sources = new ArrayList(); sources.add(nb1); sources.add(nb2); sources.add(nb3); result = checkNotifs(expectedNotifs, li.notifs, sources); if (result > 0) { - echo("...SecurityManager=" + sm + "; policy=" + policyPositive + - "; eventService=" + eventService); + echo("...SecurityManager=" + sm + "; policy=" + policyPositive); return result; } } finally { @@ -362,18 +342,9 @@ public class NotificationEmissionTest { public static void main(String[] args) throws Exception { echo("\n--- Check the emission of notifications " + - "when a Security Manager is installed [" + - args[1] + "] ---"); - - boolean eventService; - if (args[1].equals("Classic")) - eventService = false; - else if (args[1].equals("EventService")) - eventService = true; - else - throw new IllegalArgumentException(args[1]); - - NotificationEmissionTest net = new NotificationEmissionTest(eventService); + "when a Security Manager is installed"); + + NotificationEmissionTest net = new NotificationEmissionTest(); int error = 0; diff --git a/test/javax/management/remote/mandatory/notif/RMINotifTest.java b/test/javax/management/remote/mandatory/notif/RMINotifTest.java index 140c6cb5b..5369bf7af 100644 --- a/test/javax/management/remote/mandatory/notif/RMINotifTest.java +++ b/test/javax/management/remote/mandatory/notif/RMINotifTest.java @@ -25,10 +25,11 @@ * @test * @bug 7654321 * @summary Tests to receive notifications for opened and closed connections +ions * @author sjiang * @run clean RMINotifTest * @run build RMINotifTest - * @run main RMINotifTest classic + * @run main RMINotifTest * @run main RMINotifTest event */ @@ -38,8 +39,6 @@ import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; -import java.util.Collections; -import java.util.Map; import java.util.Random; import javax.management.MBeanNotificationInfo; import javax.management.MBeanServer; @@ -56,19 +55,10 @@ import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; -import javax.management.remote.rmi.RMIConnectorServer; public class RMINotifTest { public static void main(String[] args) { - String eventService; - if (args[0].equals("classic")) - eventService = "false"; - else if (args[0].equals("event")) - eventService = "true"; - else - throw new IllegalArgumentException(args[0]); - try { // create a rmi registry Registry reg = null; @@ -105,10 +95,9 @@ public class RMINotifTest { "/jndi/rmi://:" + port + "/server" + port); System.out.println("RMIConnectorServer address " + url); - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, eventService); JMXConnectorServer sServer = - JMXConnectorServerFactory.newJMXConnectorServer(url, env, null); + JMXConnectorServerFactory.newJMXConnectorServer(url, null, + null); ObjectInstance ss = server.registerMBean(sServer, new ObjectName("Default:name=RmiConnectorServer")); diff --git a/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java b/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java index 3166d3f37..adf1de1f4 100644 --- a/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java +++ b/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java @@ -63,17 +63,13 @@ public class UnexpectedNotifTest { } catch (ClassNotFoundException e) { // OK: JMXMP not present so don't test it. } - for (String proto : protos) { - test(proto, false); - test(proto, true); - } + for (String proto : protos) + test(proto); } - private static void test(String proto, boolean eventService) - throws Exception { + private static void test(String proto) throws Exception { System.out.println("Unexpected notifications test for protocol " + - proto + " with" + - (eventService ? "" : "out") + " event service"); + proto); MBeanServer mbs = null; try { // Create a MBeanServer @@ -88,12 +84,9 @@ public class UnexpectedNotifTest { // Create a connector server // url = new JMXServiceURL("service:jmx:" + proto + "://"); - Map env = Collections.singletonMap( - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, - Boolean.toString(eventService)); server = JMXConnectorServerFactory.newJMXConnectorServer(url, - env, + null, mbs); mbs.registerMBean( diff --git a/test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java b/test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java deleted file mode 100644 index 69782690d..000000000 --- a/test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java +++ /dev/null @@ -1,308 +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. - * - * 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. - */ - -/* - * @test - * @bug 6750008 - * @summary Test JMX.getSpecificationVersion - * @author Eamonn McManus - */ - -import java.io.IOException; -import java.util.Collections; -import java.util.ListIterator; -import java.util.Set; -import javax.management.Attribute; -import javax.management.AttributeList; -import javax.management.AttributeNotFoundException; -import javax.management.DynamicMBean; -import javax.management.InstanceNotFoundException; -import javax.management.InvalidAttributeValueException; -import javax.management.JMX; -import javax.management.MBeanException; -import javax.management.MBeanInfo; -import javax.management.MBeanServer; -import javax.management.MBeanServerConnection; -import javax.management.MBeanServerDelegate; -import javax.management.MBeanServerDelegateMBean; -import javax.management.MBeanServerFactory; -import javax.management.ObjectName; -import javax.management.ReflectionException; -import javax.management.StandardMBean; -import javax.management.namespace.JMXNamespace; -import javax.management.namespace.JMXNamespaces; -import javax.management.namespace.MBeanServerSupport; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXConnectorServerFactory; -import javax.management.remote.JMXServiceURL; - -public class JMXSpecVersionTest { - private static String failure; - private static final Object POISON_PILL = new Object(); - - private static class FakeDelegate implements DynamicMBean { - private final Object specVersion; - private final DynamicMBean delegate = new StandardMBean( - new MBeanServerDelegate(), MBeanServerDelegateMBean.class, false); - - FakeDelegate(Object specVersion) { - this.specVersion = specVersion; - } - - public Object getAttribute(String attribute) - throws AttributeNotFoundException, MBeanException, - ReflectionException { - if ("SpecificationVersion".equals(attribute)) { - if (specVersion == POISON_PILL) - throw new AttributeNotFoundException(attribute); - else - return specVersion; - } else - return delegate.getAttribute(attribute); - } - - public void setAttribute(Attribute attribute) - throws AttributeNotFoundException, InvalidAttributeValueException, - MBeanException, ReflectionException { - delegate.setAttribute(attribute); - } - - public AttributeList getAttributes(String[] attributes) { - AttributeList list = delegate.getAttributes(attributes); - for (ListIterator it = list.asList().listIterator(); - it.hasNext(); ) { - Attribute attr = it.next(); - if (attr.getName().equals("SpecificationVersion")) { - it.remove(); - if (specVersion != POISON_PILL) { - attr = new Attribute(attr.getName(), specVersion); - it.add(attr); - } - } - } - return list; - } - - public AttributeList setAttributes(AttributeList attributes) { - return delegate.setAttributes(attributes); - } - - public Object invoke(String actionName, Object[] params, - String[] signature) throws MBeanException, - ReflectionException { - return delegate.invoke(actionName, params, signature); - } - - public MBeanInfo getMBeanInfo() { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - private static class MBeanServerWithVersion extends MBeanServerSupport { - private final DynamicMBean delegate; - - public MBeanServerWithVersion(Object specVersion) { - this.delegate = new FakeDelegate(specVersion); - } - - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) - throws InstanceNotFoundException { - if (MBeanServerDelegate.DELEGATE_NAME.equals(name)) - return delegate; - else - throw new InstanceNotFoundException(name); - } - - @Override - protected Set getNames() { - return Collections.singleton(MBeanServerDelegate.DELEGATE_NAME); - } - } - - private static class EmptyMBeanServer extends MBeanServerSupport { - @Override - public DynamicMBean getDynamicMBeanFor(ObjectName name) throws InstanceNotFoundException { - throw new InstanceNotFoundException(name); - } - - @Override - protected Set getNames() { - return Collections.emptySet(); - } - } - - public static void main(String[] args) throws Exception { - MBeanServer mbs = MBeanServerFactory.newMBeanServer(); - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///"); - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( - url, null, mbs); - cs.start(); - - String realVersion = (String) mbs.getAttribute( - MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion"); - assertEquals("Reported local version", - realVersion, JMX.getSpecificationVersion(mbs, null)); - assertEquals("Reported local version >= \"2.0\"", - true, (realVersion.compareTo("2.0") >= 0)); - - JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress()); - MBeanServerConnection mbsc = cc.getMBeanServerConnection(); - assertEquals("Reported remote version", - realVersion, JMX.getSpecificationVersion(mbsc, null)); - - cc.close(); - try { - String brokenVersion = JMX.getSpecificationVersion(mbsc, null); - fail("JMX.getSpecificationVersion succeded over closed connection" + - " (returned " + brokenVersion + ")"); - } catch (Exception e) { - assertEquals("Exception for closed connection", - IOException.class, e.getClass()); - } - - try { - String brokenVersion = JMX.getSpecificationVersion( - new EmptyMBeanServer(), null); - fail("JMX.getSpecificationVersion succeded with empty MBean Server" + - " (returned " + brokenVersion + ")"); - } catch (Exception e) { - assertEquals("Exception for empty MBean Server", - IOException.class, e.getClass()); - } - - try { - String brokenVersion = JMX.getSpecificationVersion(null, null); - fail("JMX.getSpecificationVersion succeded with null MBean Server" + - " (returned " + brokenVersion + ")"); - } catch (Exception e) { - assertEquals("Exception for null MBean Server", - IllegalArgumentException.class, e.getClass()); - } - - MBeanServer mbs1_2 = new MBeanServerWithVersion("1.2"); - String version1_2 = JMX.getSpecificationVersion(mbs1_2, null); - assertEquals("Version for 1.2 MBean Server", "1.2", version1_2); - - // It's completely nutty for an MBean Server to return null as the - // value of its spec version, and we don't actually say what happens - // in that case, but in fact we return the null to the caller. - MBeanServer mbs_null = new MBeanServerWithVersion(null); - String version_null = JMX.getSpecificationVersion(mbs_null, null); - assertEquals("Version for MBean Server that declares null spec version", - null, version_null); - - try { - MBeanServer mbs1_2_float = new MBeanServerWithVersion(1.2f); - String version1_2_float = - JMX.getSpecificationVersion(mbs1_2_float, null); - fail("JMX.getSpecificationVersion succeeded with version 1.2f" + - " (returned " + version1_2_float + ")"); - } catch (Exception e) { - assertEquals("Exception for non-string version (1.2f)", - IOException.class, e.getClass()); - } - - try { - MBeanServer mbs_missing = new MBeanServerWithVersion(POISON_PILL); - String version_missing = - JMX.getSpecificationVersion(mbs_missing, null); - fail("JMX.getSpecificationVersion succeeded with null version" + - " (returned " + version_missing + ")"); - } catch (Exception e) { - assertEquals("Exception for missing version", - IOException.class, e.getClass()); - } - - ObjectName wildcardNamespaceName = new ObjectName("foo//*//bar//baz:k=v"); - try { - String brokenVersion = - JMX.getSpecificationVersion(mbsc, wildcardNamespaceName); - fail("JMX.getSpecificationVersion succeeded with wildcard namespace" + - " (returned " + brokenVersion + ")"); - } catch (Exception e) { - assertEquals("Exception for wildcard namespace", - IllegalArgumentException.class, e.getClass()); - } - - String sub1_2namespace = "blibby"; - JMXNamespace sub1_2 = new JMXNamespace(mbs1_2); - ObjectName sub1_2name = - JMXNamespaces.getNamespaceObjectName(sub1_2namespace); - mbs.registerMBean(sub1_2, sub1_2name); - String sub1_2namespaceHandlerVersion = - JMX.getSpecificationVersion(mbs, sub1_2name); - assertEquals("Spec version of namespace handler", - realVersion, sub1_2namespaceHandlerVersion); - // The namespace handler is in the top-level namespace so its - // version should not be 1.2. - - for (String nameInSub : new String[] {"*:*", "d:k=v"}) { - ObjectName subName = new ObjectName(sub1_2namespace + "//" + nameInSub); - String subVersion = JMX.getSpecificationVersion(mbs, subName); - assertEquals("Spec version in 1.2 namespace (" + nameInSub + ")", - "1.2", subVersion); - } - - mbs.unregisterMBean(sub1_2name); - for (String noSuchNamespace : new String[] { - sub1_2namespace + "//*:*", sub1_2namespace + "//d:k=v", - }) { - try { - String brokenVersion = JMX.getSpecificationVersion( - mbs, new ObjectName(noSuchNamespace)); - fail("JMX.getSpecificationVersion succeeded with missing " + - "namespace (" + noSuchNamespace + " -> " + - brokenVersion); - } catch (Exception e) { - assertEquals("Exception for missing namespace", - IOException.class, e.getClass()); - } - } - - if (failure != null) - throw new Exception("TEST FAILED: " + failure); - System.out.println("TEST PASSED"); - } - - private static void assertEquals(String what, Object expect, Object actual) { - if (equal(expect, actual)) - System.out.println("OK: " + what + ": " + expect); - else - fail(what + ": expected " + expect + ", got " + actual); - } - - private static boolean equal(Object x, Object y) { - if (x == null) - return (y == null); - else - return x.equals(y); - } - - private static void fail(String why) { - System.out.println("FAILED: " + why); - failure = why; - } -} diff --git a/test/javax/management/standardmbean/FindMethodTest.java b/test/javax/management/standardmbean/FindMethodTest.java deleted file mode 100644 index b568d70ac..000000000 --- a/test/javax/management/standardmbean/FindMethodTest.java +++ /dev/null @@ -1,384 +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. - * - * 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. - */ - -/* - * @test - * @bug 6287328 - * @summary Add methods to StandardMBean to retrieve a method based on - * MBean{Attribute|Operation}Info - * @author Jean-Francois Denise - * @run main FindMethodTest - */ - -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryMXBean; -import java.lang.management.ThreadMXBean; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import javax.management.MBean; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.MBeanServer; -import javax.management.ManagedAttribute; -import javax.management.ManagedOperation; -import javax.management.ObjectName; -import javax.management.StandardMBean; - -public class FindMethodTest { - - private static MBeanServer server = - ManagementFactory.getPlatformMBeanServer(); - - private static Map> expectedMapping = - new HashMap>(); - private static Set STATE_SET = new HashSet(); - private static Set ENABLED_SET = new HashSet(); - private static Set DOIT_SET = new HashSet(); - private static Set STATUS_SET = new HashSet(); - private static Set HEAPMEMORYUSAGE_SET = new HashSet(); - private static Set THREADINFO_SET = new HashSet(); - private static Set DOIT_ANNOTATED_SET = new HashSet(); - private static Set IT_ANNOTATED_SET = new HashSet(); - private static HashSet> TEST_MBEAN_SET = - new HashSet>(); - private static HashSet> ANNOTATED_MBEAN_SET = - new HashSet>(); - private static HashSet> MEMORY_MBEAN_SET = - new HashSet>(); - private static HashSet> THREAD_MBEAN_SET = - new HashSet>(); - - public interface TestMBean { - - public void doIt(); - - public void setState(String str); - - public String getState(); - - public boolean isEnabled(); - - public void setStatus(int i); - } - - public interface FaultyTestMBean { - - public void doIt(String doIt); - - public long getState(); - - public void setEnabled(boolean b); - - public int getStatus(); - - public String setWrong(int i); - } - - @MBean - public static class AnnotatedTest { - @ManagedOperation - public void doItAnnotated() { - - } - - public void dontDoIt() { - - } - - @ManagedAttribute - public String getItAnnotated() { - return null; - } - @ManagedAttribute - public void setItAnnotated(String str) { - - } - - public String getItNot() { - return null; - } - - } - - static class Test implements TestMBean { - - public void doIt() { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setState(String str) { - throw new UnsupportedOperationException("Not supported yet."); - } - - public String getState() { - throw new UnsupportedOperationException("Not supported yet."); - } - - public boolean isEnabled() { - throw new UnsupportedOperationException("Not supported yet."); - } - - public void setStatus(int i) { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - - static { - try { - ENABLED_SET.add(TestMBean.class.getDeclaredMethod("isEnabled")); - - STATE_SET.add(TestMBean.class.getDeclaredMethod("getState")); - STATE_SET.add(TestMBean.class.getDeclaredMethod("setState", - String.class)); - STATUS_SET.add(TestMBean.class.getDeclaredMethod("setStatus", - int.class)); - - DOIT_SET.add(TestMBean.class.getDeclaredMethod("doIt")); - - DOIT_ANNOTATED_SET.add(AnnotatedTest.class.getDeclaredMethod("doItAnnotated")); - - IT_ANNOTATED_SET.add(AnnotatedTest.class.getDeclaredMethod("getItAnnotated")); - IT_ANNOTATED_SET.add(AnnotatedTest.class.getDeclaredMethod("setItAnnotated", String.class)); - - THREADINFO_SET.add(ThreadMXBean.class.getDeclaredMethod("dumpAllThreads", boolean.class, - boolean.class)); - - HEAPMEMORYUSAGE_SET.add(MemoryMXBean.class.getDeclaredMethod("getHeapMemoryUsage")); - - TEST_MBEAN_SET.add(ENABLED_SET); - TEST_MBEAN_SET.add(STATE_SET); - TEST_MBEAN_SET.add(STATUS_SET); - TEST_MBEAN_SET.add(DOIT_SET); - - ANNOTATED_MBEAN_SET.add(DOIT_ANNOTATED_SET); - ANNOTATED_MBEAN_SET.add(IT_ANNOTATED_SET); - - MEMORY_MBEAN_SET.add(HEAPMEMORYUSAGE_SET); - - THREAD_MBEAN_SET.add(THREADINFO_SET); - - expectedMapping.put("State", STATE_SET); - expectedMapping.put("Enabled", ENABLED_SET); - expectedMapping.put("Status", STATUS_SET); - expectedMapping.put("doIt", DOIT_SET); - expectedMapping.put("HeapMemoryUsage", HEAPMEMORYUSAGE_SET); - expectedMapping.put("dumpAllThreads", THREADINFO_SET); - expectedMapping.put("doItAnnotated", DOIT_ANNOTATED_SET); - expectedMapping.put("ItAnnotated", IT_ANNOTATED_SET); - - } catch (Exception ex) { - ex.printStackTrace(); - throw new RuntimeException("Initialization failed"); - } - } - - private static void testMBean(ObjectName name, Class itf, - HashSet> expectMappings) - throws Exception { - - Set> expectedMappings = - (Set>) expectMappings.clone(); - - MBeanInfo info = server.getMBeanInfo(name); - for (MBeanAttributeInfo attr : info.getAttributes()) { - Set expected = expectedMapping.get(attr.getName()); - if (expected == null) { - continue; - } - if (!expectedMappings.remove(expected)) { - throw new Exception("The mapping to use is not the expected " + - "one for " + attr); - } - System.out.println("Expected : " + expected); - Set found = - StandardMBean.findAttributeAccessors(itf, attr); - System.out.println("Found : " + found); - if (!found.equals(expected)) { - throw new Exception("Mapping error."); - } - } - for (MBeanOperationInfo op : info.getOperations()) { - Set expected = expectedMapping.get(op.getName()); - if (expected == null) { - continue; - } - if (!expectedMappings.remove(expected)) { - throw new Exception("The mapping to use is not the expected " + - "one for " + op); - } - System.out.println("Expected : " + expected); - Method method = - StandardMBean.findOperationMethod(itf, op); - Set found = new HashSet(); - found.add(method); - System.out.println("Found : " + found); - if (!found.equals(expected)) { - throw new Exception("Mapping error."); - } - } - - if (expectedMappings.size() != 0) { - throw new Exception("Some mapping have not been found " + - expectedMappings); - } else { - System.out.println("All mappings have been found"); - } - } - - public static void main(String[] args) throws Exception { - // Positive tests - Test t = new Test(); - ObjectName name = ObjectName.valueOf(":type=Test"); - server.registerMBean(t, name); - AnnotatedTest at = new AnnotatedTest(); - ObjectName annotatedName = ObjectName.valueOf(":type=AnnotatedTest"); - server.registerMBean(at, annotatedName); - - testMBean(name, TestMBean.class, TEST_MBEAN_SET); - - testMBean(annotatedName, AnnotatedTest.class, ANNOTATED_MBEAN_SET); - - ObjectName memoryName = - ObjectName.valueOf(ManagementFactory.MEMORY_MXBEAN_NAME); - testMBean(memoryName, MemoryMXBean.class, MEMORY_MBEAN_SET); - - ObjectName threadName = - ObjectName.valueOf(ManagementFactory.THREAD_MXBEAN_NAME); - testMBean(threadName, ThreadMXBean.class, THREAD_MBEAN_SET); - - // Negative tests - try { - StandardMBean.findOperationMethod(null, - new MBeanOperationInfo("Test", - TestMBean.class.getDeclaredMethod("doIt"))); - throw new Exception("Expected exception not found"); - } catch (IllegalArgumentException ex) { - System.out.println("OK received expected exception " + ex); - } - try { - StandardMBean.findOperationMethod(TestMBean.class, null); - throw new Exception("Expected exception not found"); - } catch (IllegalArgumentException ex) { - System.out.println("OK received expected exception " + ex); - } - try { - StandardMBean.findAttributeAccessors(null, - new MBeanAttributeInfo("Test", "Test", - TestMBean.class.getDeclaredMethod("getState"), - TestMBean.class.getDeclaredMethod("setState", - String.class))); - throw new Exception("Expected exception not found"); - } catch (IllegalArgumentException ex) { - System.out.println("OK received expected exception " + ex); - } - try { - StandardMBean.findAttributeAccessors(TestMBean.class, null); - throw new Exception("Expected exception not found"); - } catch (IllegalArgumentException ex) { - System.out.println("OK received expected exception " + ex); - } - //Wrong operation signature - try { - StandardMBean.findOperationMethod(TestMBean.class, - new MBeanOperationInfo("FaultyTest", - FaultyTestMBean.class.getDeclaredMethod("doIt", - String.class))); - throw new Exception("Expected exception not found"); - } catch (NoSuchMethodException ex) { - System.out.println("OK received expected exception " + ex); - } - //Wrong attribute accessor - try { - StandardMBean.findAttributeAccessors(TestMBean.class, - new MBeanAttributeInfo("FaultyTest", "FaultyTest", null, - FaultyTestMBean.class.getDeclaredMethod("setEnabled", - String.class))); - throw new Exception("Expected exception not found"); - } catch (NoSuchMethodException ex) { - System.out.println("OK received expected exception " + ex); - } - //Wrong attribute type - try { - StandardMBean.findAttributeAccessors(TestMBean.class, - new MBeanAttributeInfo("State", "toto.FaultType", - "FaultyTest", true, true, false)); - throw new Exception("Expected exception not found"); - } catch (ClassNotFoundException ex) { - System.out.println("OK received expected exception " + ex); - } - //Wrong operation parameter type - try { - MBeanParameterInfo[] p = {new MBeanParameterInfo("p1", - "toto.FaultType2", "FaultyParameter") - }; - StandardMBean.findOperationMethod(TestMBean.class, - new MBeanOperationInfo("doIt", "FaultyMethod", p, "void", - 0)); - throw new Exception("Expected exception not found"); - } catch (ClassNotFoundException ex) { - System.out.println("OK received expected exception " + ex); - } - // Check that not annotated attributes are not found - try { - StandardMBean.findAttributeAccessors(AnnotatedTest.class, - new MBeanAttributeInfo("ItNot", String.class.getName(), - "FaultyTest", true, false, false)); - throw new Exception("Expected exception not found"); - } catch (NoSuchMethodException ex) { - System.out.println("OK received expected exception " + ex); - } - // Check that not annotated operations are not found - try { - StandardMBean.findOperationMethod(AnnotatedTest.class, - new MBeanOperationInfo("dontDoIt","dontDoIt",null, - Void.TYPE.getName(),0)); - throw new Exception("Expected exception not found"); - } catch (NoSuchMethodException ex) { - System.out.println("OK received expected exception " + ex); - } - // Check that wrong getter return type throws Exception - try { - StandardMBean.findAttributeAccessors(AnnotatedTest.class, - new MBeanAttributeInfo("ItAnnotated", Long.class.getName(), - "FaultyTest", true, false, false)); - throw new Exception("Expected exception not found"); - } catch (NoSuchMethodException ex) { - System.out.println("OK received expected exception " + ex); - } - // Check that wrong setter return type throws Exception - try { - StandardMBean.findAttributeAccessors(FaultyTestMBean.class, - new MBeanAttributeInfo("Wrong", String.class.getName(), - "FaultyTest", true, true, false)); - throw new Exception("Expected exception not found"); - } catch (NoSuchMethodException ex) { - System.out.println("OK received expected exception " + ex); - } - } -} diff --git a/test/javax/management/standardmbean/RegistrationTest.java b/test/javax/management/standardmbean/RegistrationTest.java deleted file mode 100644 index 9ca0c464f..000000000 --- a/test/javax/management/standardmbean/RegistrationTest.java +++ /dev/null @@ -1,91 +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. - * - * 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. - */ - -/* - * @test - * @bug 6450834 - * @summary Forward MBeanRegistration calls - * @author JF Denise - * @run main RegistrationTest - */ - -import java.io.Serializable; -import java.lang.management.ManagementFactory; -import javax.management.*; - -public class RegistrationTest { - static boolean preRegisterCalled; - static boolean postRegisterCalled; - static boolean preDeregisterCalled; - static boolean postDeregisterCalled; - - static void checkResult(boolean expected) throws Exception { - if((preRegisterCalled != expected || - postRegisterCalled != expected || - preDeregisterCalled != expected || - postDeregisterCalled != expected)) - throw new Exception("Mismatch preRegisterCalled = " - + preRegisterCalled + ", postRegisterCalled = " - + postRegisterCalled + ", preDeregisterCalled = " - + preDeregisterCalled + ", postDeregisterCalled = " - + postDeregisterCalled); - } - static class Wrapped implements MBeanRegistration,Serializable { - - public ObjectName preRegister(MBeanServer server, ObjectName name) - throws Exception { - preRegisterCalled = true; - return name; - } - - public void postRegister(Boolean registrationDone) { - postRegisterCalled = true; - } - - public void preDeregister() throws Exception { - preDeregisterCalled = true; - } - - public void postDeregister() { - postDeregisterCalled = true; - } - - } - - public static void main(String[] args) throws Exception { - StandardMBean std = new StandardMBean(new Wrapped(), - Serializable.class); - ObjectName name = ObjectName.valueOf(":type=Test"); - ManagementFactory.getPlatformMBeanServer().registerMBean(std,name); - ManagementFactory.getPlatformMBeanServer().unregisterMBean(name); - checkResult(false); - StandardMBean.Options opt = new StandardMBean.Options(); - opt.setMBeanRegistrationForwarded(true); - std = new StandardMBean(new Wrapped(), - Serializable.class, opt ); - ManagementFactory.getPlatformMBeanServer().registerMBean(std,name); - ManagementFactory.getPlatformMBeanServer().unregisterMBean(name); - checkResult(true); - System.out.println("Test OK"); - } -} -- GitLab