From ebfd9ff053b04ab379acfc0fefedee5a31b6d8a5 Mon Sep 17 00:00:00 2001 From: "Stephen D. Huston" Date: Fri, 21 Oct 2011 01:19:00 +0000 Subject: Undo bad merge from trunk - merged at wrong level. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-2519@1187150 13f79535-47bb-0310-9956-ffa450edef68 --- .../client/src/example/ConnectWithBroker.out.ok | 81 + .../example/GetMultipleResourceProperties.out.ok | 262 +++ .../src/example/GetQManResourceMembers.out.ko | 54 + .../src/example/GetQManResourceMembers.out.ok | 55 + .../example/GetResourceMetadataDescriptor.out.ok | 188 ++ .../src/example/GetResourcePropertyDocument.out.ok | 138 ++ .../src/example/GetResourcePropertyRequest.out.ok | 588 +++++ .../example/GetWsdlMetadata.out.ko.no.resources | 58 + .../client/src/example/GetWsdlMetadata.out.ok | 1968 +++++++++++++++++ .../src/example/PauseAndResumeSubscription.out.ok | 133 ++ java/management/client/src/example/README.txt | 69 + .../example/SetResourcePropertiesRequest.out.ok | 2316 ++++++++++++++++++++ .../management/example/AbstractQManExample.java | 140 ++ .../example/ConnectWithBrokerExample.java | 240 ++ .../example/ConsumerAndProducerExample.java | 293 +++ .../GetMultipleResourcePropertiesExample.java | 179 ++ .../example/GetQManResourceMembersExample.java | 93 + .../GetResourceMetadataDescriptorExample.java | 156 ++ .../GetResourcePropertyDocumentExample.java | 111 + .../example/GetResourcePropertyExample.java | 172 ++ .../management/example/GetWSDLMetadataExample.java | 156 ++ .../example/PausableSubscriptionExample.java | 88 + .../example/SetResourcePropertyExample.java | 306 +++ java/management/client/src/main/java/muse.xml | 209 ++ .../java/org/apache/qpid/management/Messages.java | 175 ++ .../java/org/apache/qpid/management/Names.java | 216 ++ .../java/org/apache/qpid/management/Protocol.java | 52 + .../BrokerAlreadyConnectedException.java | 53 + .../configuration/BrokerConnectionData.java | 280 +++ .../configuration/BrokerConnectionDataParser.java | 136 ++ .../configuration/BrokerConnectionException.java | 42 + .../management/configuration/Configuration.java | 485 ++++ .../configuration/ConfigurationException.java | 51 + .../management/configuration/Configurator.java | 240 ++ .../qpid/management/configuration/IParser.java | 44 + .../configuration/MessageHandlerMapping.java | 64 + .../management/configuration/QpidDatasource.java | 249 +++ .../apache/qpid/management/configuration/Tag.java | 54 + .../configuration/UnknownAccessCodeException.java | 53 + .../configuration/UnknownBrokerException.java | 43 + .../configuration/UnknownTypeCodeException.java | 53 + .../WorkerManagerConfigurationParser.java | 109 + .../domain/handler/base/BaseMessageHandler.java | 54 + .../base/ContentIndicationMessageHandler.java | 114 + .../domain/handler/base/IMessageHandler.java | 52 + .../handler/impl/ConfigurationMessageHandler.java | 57 + .../handler/impl/EventContentMessageHandler.java | 51 + .../impl/HeartBeatIndicationMessageHandler.java | 39 + .../handler/impl/IMethodInvocationListener.java | 41 + .../impl/InstrumentationMessageHandler.java | 57 + .../domain/handler/impl/InvocationResult.java | 157 ++ .../impl/MethodOrEventDataTransferObject.java | 68 + .../handler/impl/MethodResponseMessageHandler.java | 106 + .../domain/handler/impl/QpidDomainObject.java | 314 +++ .../domain/handler/impl/QpidDomainObjectMBean.java | 234 ++ .../handler/impl/SchemaResponseMessageHandler.java | 217 ++ .../qpid/management/domain/model/AccessMode.java | 33 + .../qpid/management/domain/model/Direction.java | 33 + .../qpid/management/domain/model/DomainModel.java | 239 ++ .../qpid/management/domain/model/IValidator.java | 38 + .../management/domain/model/InvocationEvent.java | 76 + .../qpid/management/domain/model/JmxService.java | 410 ++++ .../model/MissingFeatureAttributesException.java | 35 + .../qpid/management/domain/model/QpidArgument.java | 123 ++ .../management/domain/model/QpidAttribute.java | 105 + .../qpid/management/domain/model/QpidClass.java | 833 +++++++ .../management/domain/model/QpidClassMBean.java | 41 + .../qpid/management/domain/model/QpidEntity.java | 184 ++ .../qpid/management/domain/model/QpidEvent.java | 493 +++++ .../management/domain/model/QpidEventMBean.java | 41 + .../qpid/management/domain/model/QpidFeature.java | 86 + .../domain/model/QpidFeatureBuilder.java | 454 ++++ .../qpid/management/domain/model/QpidMethod.java | 147 ++ .../qpid/management/domain/model/QpidPackage.java | 286 +++ .../qpid/management/domain/model/QpidProperty.java | 295 +++ .../management/domain/model/QpidStatistic.java | 34 + .../model/UnableToBuildFeatureException.java | 51 + .../domain/model/ValidationException.java | 105 + .../qpid/management/domain/model/type/AbsTime.java | 44 + .../qpid/management/domain/model/type/Binary.java | 169 ++ .../qpid/management/domain/model/type/Boolean.java | 44 + .../management/domain/model/type/DeltaTime.java | 44 + .../qpid/management/domain/model/type/Double.java | 44 + .../qpid/management/domain/model/type/Float.java | 44 + .../qpid/management/domain/model/type/Int16.java | 44 + .../qpid/management/domain/model/type/Int32.java | 44 + .../qpid/management/domain/model/type/Int64.java | 44 + .../qpid/management/domain/model/type/Int8.java | 44 + .../qpid/management/domain/model/type/Map.java | 45 + .../domain/model/type/ObjectReference.java | 44 + .../qpid/management/domain/model/type/Str16.java | 44 + .../qpid/management/domain/model/type/Str8.java | 44 + .../qpid/management/domain/model/type/Type.java | 101 + .../qpid/management/domain/model/type/Uint16.java | 44 + .../qpid/management/domain/model/type/Uint32.java | 44 + .../qpid/management/domain/model/type/Uint64.java | 44 + .../qpid/management/domain/model/type/Uint8.java | 44 + .../qpid/management/domain/model/type/Uuid.java | 46 + .../domain/services/BrokerMessageListener.java | 183 ++ .../domain/services/ManagementClient.java | 249 +++ .../domain/services/MessageTokenizer.java | 152 ++ .../domain/services/MethodInvocationException.java | 50 + .../qpid/management/domain/services/QMan.java | 412 ++++ .../management/domain/services/QpidService.java | 361 +++ .../domain/services/SequenceNumberGenerator.java | 41 + .../domain/services/StartupFailureException.java | 42 + .../domain/services/UnableToComplyException.java | 31 + .../jmx/EntityLifecycleNotification.java | 147 ++ .../jmx/OperationHasBeenInvokedNotification.java | 168 ++ .../management/messages/ManagementMessage.java | 189 ++ .../messages/MethodInvocationRequestMessage.java | 161 ++ .../management/messages/SchemaRequestMessage.java | 68 + .../management/servlet/ConnectQManToBroker.java | 89 + .../management/servlet/QManLifeCycleManager.java | 79 + .../qpid/management/servlet/WSDMAdapter.java | 109 + .../qpid/management/web/action/BrokerModel.java | 100 + .../web/action/BrokersManagementAction.java | 204 ++ .../qpid/management/web/action/ConsoleAction.java | 117 + .../qpid/management/web/action/ConsoleModel.java | 158 ++ .../web/action/JmxPerspectiveAction.java | 189 ++ .../web/action/LoggingConfigurationAction.java | 114 + .../web/action/ResourcesManagementAction.java | 91 + .../action/WsdmOperationsPerspectiveAction.java | 191 ++ .../action/WsdmPropertiesPerspectiveAction.java | 185 ++ .../web/action/WsdmRmdPerspectiveAction.java | 139 ++ .../web/action/WsdmWsdlPerspectiveAction.java | 140 ++ .../java/org/apache/qpid/management/wsdm/QEmu.java | 130 ++ .../qpid/management/wsdm/QEmuInitializer.java | 95 + .../org/apache/qpid/management/wsdm/QEmuMBean.java | 48 + .../ArtifactsNotAvailableException.java | 76 + .../wsdm/capabilities/BuilderException.java | 41 + .../management/wsdm/capabilities/Constants.java | 44 + .../wsdm/capabilities/ConsumerCapability.java | 68 + .../wsdm/capabilities/DummyCapabilityBuilder.java | 86 + .../wsdm/capabilities/IArtifactBuilder.java | 82 + .../wsdm/capabilities/MBeanCapability.java | 219 ++ .../wsdm/capabilities/MBeanCapabilityBuilder.java | 549 +++++ .../wsdm/capabilities/QManAdapterCapability.java | 557 +++++ .../wsdm/capabilities/QManMessageHandler.java | 104 + .../QManMetadataExchangeCapability.java | 99 + .../qpid/management/wsdm/capabilities/Result.java | 57 + .../management/wsdm/capabilities/RmdBuilder.java | 135 ++ .../wsdm/capabilities/WSDMArtifactsDirector.java | 196 ++ .../management/wsdm/capabilities/WsArtifacts.java | 93 + .../wsdm/capabilities/WsArtifactsFactory.java | 140 ++ .../management/wsdm/capabilities/WsdlBuilder.java | 460 ++++ .../wsdm/common/EntityInstanceNotFoundFault.java | 58 + .../wsdm/common/MethodInvocationFault.java | 79 + .../wsdm/common/NoSuchAttributeFault.java | 70 + .../wsdm/common/ObjectNameIdFactory.java | 61 + .../qpid/management/wsdm/common/QManFault.java | 72 + .../wsdm/common/QManResourceIdFactory.java | 57 + .../qpid/management/wsdm/common/ThreadSession.java | 105 + .../wsdm/common/ThreadSessionManager.java | 68 + .../common/UnableToConnectWithBrokerFault.java | 86 + .../wsdm/muse/engine/WSDMAdapterEnvironment.java | 118 + .../muse/engine/WSDMAdapterIsolationLayer.java | 57 + .../wsdm/muse/resources/QManWsResource.java | 762 +++++++ .../wsdm/muse/serializer/ByteArraySerializer.java | 83 + .../wsdm/muse/serializer/DateSerializer.java | 75 + .../serializer/InvocationResultSerializer.java | 85 + .../wsdm/muse/serializer/MapSerializer.java | 134 ++ .../wsdm/muse/serializer/ObjectSerializer.java | 202 ++ .../wsdm/muse/serializer/UUIDSerializer.java | 72 + .../wsdm/notifications/LifeCycleEvent.java | 149 ++ .../wsdm/notifications/LifeCycleEventType.java | 34 + .../org/apache/qpid/qman/debug/WsdlDebugger.java | 49 + .../org/apache/qpid/qman/debug/XmlDebugger.java | 92 + .../router-entries/adapter/resource-instance-1.xml | 23 + .../consumer/resource-instance-1.xml | 23 + .../client/src/main/java/wsdl/QManAdapter.rmd | 27 + .../client/src/main/java/wsdl/QManAdapter.wsdl | 694 ++++++ .../client/src/main/java/wsdl/QManWsResource.rmd | 17 + .../client/src/main/java/wsdl/QManWsResource.wsdl | 507 +++++ .../src/main/java/wsdl/SOAP-Envelope-1_2.xsd | 181 ++ .../src/main/java/wsdl/WS-Addressing-2005_08.xsd | 169 ++ .../src/main/java/wsdl/WS-BaseFaults-1_2.xsd | 84 + .../main/java/wsdl/WS-BaseNotification-1_3.wsdl | 449 ++++ .../src/main/java/wsdl/WS-BaseNotification-1_3.xsd | 577 +++++ .../main/java/wsdl/WS-MetadataExchange-2004_09.xsd | 134 ++ .../client/src/main/java/wsdl/WS-Resource-1_2.wsdl | 54 + .../client/src/main/java/wsdl/WS-Resource-1_2.xsd | 48 + .../main/java/wsdl/WS-ResourceLifetime-1_2.wsdl | 83 + .../src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd | 130 ++ .../wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd | 325 +++ .../main/java/wsdl/WS-ResourceProperties-1_2.wsdl | 395 ++++ .../main/java/wsdl/WS-ResourceProperties-1_2.xsd | 394 ++++ .../src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl | 269 +++ .../src/main/java/wsdl/WS-ServiceGroup-1_2.xsd | 233 ++ .../main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl | 206 ++ .../client/src/main/java/wsdl/WS-Topics-1_3.xsd | 185 ++ .../src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd | 114 + .../src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd | 677 ++++++ .../client/src/main/java/wsdl/WsResource.rmd | 14 + .../src/main/java/wsdl/WsResourceFactory.wsdl | 22 + .../src/main/java/wsdl/XML-Namespace-1998.xsd | 46 + .../org/apache/qpid/management/TestConstants.java | 67 + .../configuration/ConfigurationTest.java | 181 ++ .../management/configuration/ConfiguratorTest.java | 163 ++ .../configuration/MappingParsersTest.java | 79 + .../base/ContentIndicationMessageHandlerTest.java | 59 + .../domain/model/BaseDomainModelTestCase.java | 44 + .../model/BaseQpidFeatureBuilderTestCase.java | 96 + .../management/domain/model/DomainModelTest.java | 55 + .../domain/model/OptionalPropertiesTest.java | 187 ++ .../management/domain/model/QpidClassTest.java | 408 ++++ .../management/domain/model/QpidEventTest.java | 293 +++ .../domain/model/QpidMethodBuilderTest.java | 147 ++ .../domain/model/QpidNumberPropertyTest.java | 171 ++ .../management/domain/model/QpidPackageTest.java | 53 + .../domain/model/QpidPropertyBuilderTest.java | 269 +++ .../domain/model/QpidStatisticBuilderTest.java | 159 ++ .../domain/model/QpidStringPropertyTest.java | 127 ++ .../management/domain/model/type/BinaryTest.java | 59 + .../domain/services/BrokerMessageListenerTest.java | 241 ++ .../domain/services/MessageTokenizerTest.java | 140 ++ .../management/wsdm/BaseWsDmAdapterTestCase.java | 143 ++ .../wsdm/EnhancedReflectionProxyHandler.java | 72 + .../GetMultipleResourcePropertiesTestCase.java | 125 ++ .../wsdm/GetResourcePropertiesTestCase.java | 105 + .../wsdm/GetResourcePropertyDocumentTestCase.java | 134 ++ .../wsdm/MetadataExchangeInterfaceTestCase.java | 169 ++ .../wsdm/OperationInvocationInterfaceTestCase.java | 580 +++++ .../apache/qpid/management/wsdm/ServerThread.java | 118 + .../wsdm/SetResourcePropertiesTestCase.java | 219 ++ .../wsdm/WebApplicationLifeCycleListener.java | 61 + .../qpid/management/wsdm/WsDmAdapterTest.java | 156 ++ .../capabilities/MBeanCapabilityBuilderTest.java | 335 +++ .../wsdm/capabilities/MBeanCapabilityTest.java | 204 ++ .../capabilities/QManAdapterCapabilityTest.java | 81 + .../wsdm/capabilities/RmdBuilderTest.java | 110 + .../java/org/apache/qpid/management/wsdm/web.xml | 32 + 232 files changed, 38948 insertions(+) create mode 100644 java/management/client/src/example/ConnectWithBroker.out.ok create mode 100644 java/management/client/src/example/GetMultipleResourceProperties.out.ok create mode 100644 java/management/client/src/example/GetQManResourceMembers.out.ko create mode 100644 java/management/client/src/example/GetQManResourceMembers.out.ok create mode 100644 java/management/client/src/example/GetResourceMetadataDescriptor.out.ok create mode 100644 java/management/client/src/example/GetResourcePropertyDocument.out.ok create mode 100644 java/management/client/src/example/GetResourcePropertyRequest.out.ok create mode 100644 java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources create mode 100644 java/management/client/src/example/GetWsdlMetadata.out.ok create mode 100644 java/management/client/src/example/PauseAndResumeSubscription.out.ok create mode 100644 java/management/client/src/example/README.txt create mode 100644 java/management/client/src/example/SetResourcePropertiesRequest.out.ok create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java create mode 100644 java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java create mode 100644 java/management/client/src/main/java/muse.xml create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/Messages.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/Names.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/Protocol.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java create mode 100644 java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml create mode 100644 java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml create mode 100644 java/management/client/src/main/java/wsdl/QManAdapter.rmd create mode 100644 java/management/client/src/main/java/wsdl/QManAdapter.wsdl create mode 100644 java/management/client/src/main/java/wsdl/QManWsResource.rmd create mode 100644 java/management/client/src/main/java/wsdl/QManWsResource.wsdl create mode 100644 java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl create mode 100644 java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl create mode 100644 java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl create mode 100644 java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl create mode 100644 java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl create mode 100644 java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd create mode 100644 java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl create mode 100644 java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd create mode 100644 java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd create mode 100644 java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd create mode 100644 java/management/client/src/main/java/wsdl/WsResource.rmd create mode 100644 java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl create mode 100644 java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java create mode 100644 java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml (limited to 'java/management/client/src') diff --git a/java/management/client/src/example/ConnectWithBroker.out.ok b/java/management/client/src/example/ConnectWithBroker.out.ok new file mode 100644 index 0000000000..33af477b98 --- /dev/null +++ b/java/management/client/src/example/ConnectWithBroker.out.ok @@ -0,0 +1,81 @@ + ConnectWithBrokerExample +------------------------------------------------------------------- + +This example shows how to connect QMan with a broker using +the adapter interface. + +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://romagazzarini:8080/qman/services/adapter + http://amqp.apache.org/qpid/management/qman/Connect + uuid:48bf9a1b-f814-7391-b5cf-d163de4ac068 + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + + sofia.gazzax.com + 5672 + test + a.gazzarini + p1ssw9rd + 1 + 4 + 2000 + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://www.w3.org/2005/08/addressing/fault + uuid:220bfe54-d5f4-4a04-794c-0f5d99a64567 + uuid:48bf9a1b-f814-7391-b5cf-d163de4ac068 + + http://romagazzarini:8080/qman/services/adapter + + + + + + qman:QMan + + + Unable to connect with the requested broker. Underlying exception message was null + + + + 2009-02-17T10:37:08+01:00 + + + http://romagazzarini:8080/qman/services/adapter + + sofia.gazzax.com + 5672 + test + p1ssw9rd + + + + + + +-----------------------EXAMPLE FAILURE----------- +Not well-defined exception was detected while +running the example. +org.apache.muse.ws.addressing.soap.SoapFault: Unable to connect with the requested broker. Underlying exception message was null + at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:298) + at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:232) + at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:211) + at org.apache.qpid.management.example.ConnectWithBrokerExample.executeExample(ConnectWithBrokerExample.java:146) + at org.apache.qpid.management.example.ConnectWithBrokerExample.execute(ConnectWithBrokerExample.java:97) + at org.apache.qpid.management.example.ConnectWithBrokerExample.main(ConnectWithBrokerExample.java:201) +-------------------------------------------------------- diff --git a/java/management/client/src/example/GetMultipleResourceProperties.out.ok b/java/management/client/src/example/GetMultipleResourceProperties.out.ok new file mode 100644 index 0000000000..005841488d --- /dev/null +++ b/java/management/client/src/example/GetMultipleResourceProperties.out.ok @@ -0,0 +1,262 @@ + GetMultipleResourcePropertiesExample +------------------------------------------------------------------- + +This example shows how to get properties from a +WS-Resource using one request. +First of all a request is send to WS-DM in order to get +all registered WS-Resources. +If the returned list is not empty then a GetMetadataRequest +to the first child. +The result metadata descriptor contains all property names of +the target WS-Resource. +Those names are then used for retrieving the corresponding values +using the GetMultipleResourceProperties request. + +------------------------------------------------------------------- + +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:1a72feb1-7d76-1014-66d7-cd03aeff3525 + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:783956b1-4de7-f4b6-5421-536f5f310b9a + uuid:1a72feb1-7d76-1014-66d7-cd03aeff3525 + + http://localhost:8080/qman/services/adapter + + + + + + + http://localhost:8080/qman/services/ServiceGroupEntry + + uuid:b220e2bd-0370-da4e-fc71-5e283954d319 + + + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + uuid:588288c9-8bb7-04e9-e7bf-7be1e2fe41fb + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + http://docs.oasis-open.org/wsrf/rmd-1 + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse + uuid:77c5520b-d450-5a8a-7e2b-22a1079392f2 + uuid:588288c9-8bb7-04e9-e7bf-7be1e2fe41fb + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesRequest + uuid:783fc044-58a9-e780-a2ba-5b2ac0454985 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + qman:MgmtPubInterval + qman:Name + qman:MsgTotalEnqueues + qman:Arguments + qman:VhostRef + qman:ExpireTime + qman:Durable + qman:ConsumerCount + qman:Type + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetMultipleResourceProperties/GetMultipleResourcePropertiesResponse + uuid:9a2d76dd-52ba-ac7c-74cf-4acd99708529 + uuid:783fc044-58a9-e780-a2ba-5b2ac0454985 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + 32767 + Initial Name + 9223372036854775797 + + + Key3 + 2147483647 + + + Key4 + 3.4028235E38 + + + Key1 + aStringValue + + + Key2 + -9223372036854775808 + + + 2deef1b3-d2c6-49f3-a8de-51f6a75a1a6b + 9223372036854775807 + true + -2147483638 + + + \ No newline at end of file diff --git a/java/management/client/src/example/GetQManResourceMembers.out.ko b/java/management/client/src/example/GetQManResourceMembers.out.ko new file mode 100644 index 0000000000..d6b733e430 --- /dev/null +++ b/java/management/client/src/example/GetQManResourceMembers.out.ko @@ -0,0 +1,54 @@ + GetQManResourceMembersExample Example +------------------------------------------------------------------- + +This example shows the usage of WS-DM +GetResourcePropertyRequest / Response on a +Group service. +The target resource is the WS-DM Adapter itself +and the requested property is "ws-rp:Entry". +WS-DM Adapter is a special WS-Resource (is a Group) +that acts as the main entry point for retrieving +all other managed resources. +So clients that want to deal with QMan WS-Resources +must first get resource identifiers sending +a GetResourcePropertyRequest to WS-DM Adapter +with "ws-rp:Entry" as target target property. + +------------------------------------------------------------------- + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://192.38.73.2:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:796bab33-ed59-3432-4e2c-1fadde465a25 + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +-----------------------EXAMPLE FAILURE---------------------- +org.apache.muse.ws.addressing.soap.SoapFault: No route to host: connect + at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:298) + at org.apache.muse.core.AbstractResourceClient.invoke(AbstractResourceClient.java:254) + at org.apache.muse.ws.resource.remote.WsResourceClient.getResourceProperty(WsResourceClient.java:138) + at org.apache.muse.ws.resource.sg.remote.ServiceGroupClient.getMembers(ServiceGroupClient.java:110) + at org.apache.qpid.management.example.GetQManResourceMembersExample.execute(GetQManResourceMembersExample.java:61) + at org.apache.qpid.management.example.GetQManResourceMembersExample.main(GetQManResourceMembersExample.java:133) + + +######################################################################################### + +WARNING! Unable to run this sample : port number must be a number. +------------------------------------------------------------- +Expected command line args for this sample are : + +1) host : ip or host name where QMan is running. +2) port : port number where QMan is running. +------------------------------------------------------------ \ No newline at end of file diff --git a/java/management/client/src/example/GetQManResourceMembers.out.ok b/java/management/client/src/example/GetQManResourceMembers.out.ok new file mode 100644 index 0000000000..dd75e1e490 --- /dev/null +++ b/java/management/client/src/example/GetQManResourceMembers.out.ok @@ -0,0 +1,55 @@ + GetQManResourceMembersExample Example +------------------------------------------------------------------- + +This example shows the usage of WS-DM +GetResourcePropertyRequest / Response on a +Group service. +The target resource is the WS-DM Adapter itself +and the requested property is "ws-rp:Entry". +WS-DM Adapter is a special WS-Resource (is a Group) +that acts as the main entry point for retrieving +all other managed resources. +So clients that want to deal with QMan WS-Resources +must first get resource identifiers sending +a GetResourcePropertyRequest to WS-DM Adapter +with "ws-rp:Entry" as target target property. + +------------------------------------------------------------------- + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://romagazzarini:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:024c678b-1fab-cb6a-0992-30027817fb92 + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:90b0e421-6467-a72e-a8f4-cdedb80460b6 + uuid:024c678b-1fab-cb6a-0992-30027817fb92 + + http://romagazzarini:8080/qman/services/adapter + + + + + + + +-------------------------------------------------------------------------- +QMan has at the moment 0 registered resources. +-------------------------------------------------------------------------- \ No newline at end of file diff --git a/java/management/client/src/example/GetResourceMetadataDescriptor.out.ok b/java/management/client/src/example/GetResourceMetadataDescriptor.out.ok new file mode 100644 index 0000000000..a259259228 --- /dev/null +++ b/java/management/client/src/example/GetResourceMetadataDescriptor.out.ok @@ -0,0 +1,188 @@ + GetResourceMetadataDescriptorExample +------------------------------------------------------------------- + +The example shows how to get metadata from a +WS-Resource. +A QMan WS-Resource has different kinds of metadata. +(see below) +User who wants to receive metadata of a WS-Resource +must send a GetMetadataRequesta specifying the +associated dialect. +Supported metadata that could be requested are : + +- WSDL : in this case dialect is "http://schemas.xmlsoap.org/wsdl/"; +- RDM (Resource Metadata Descriptor) : in this case dialect is "http://docs.oasis-open.org/wsrf/rmd-1 ". + +Note that this examples focuses on RDM Metadata only; +another one is dedicated to WSDL. +------------------------------------------------------------------- + +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:cdcf747a-e5fc-3762-1748-87cc2eefb18b + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:1d0d091b-8867-d765-7cc8-4898851cd783 + uuid:cdcf747a-e5fc-3762-1748-87cc2eefb18b + + http://localhost:8080/qman/services/adapter + + + + + + + http://localhost:8080/qman/services/ServiceGroupEntry + + uuid:3a2ee31e-49ed-e30a-c985-0fe49c182a75 + + + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=cbe0cada-e8ee-424c-945b-f6c42df7b011,class=queue,name=1232952196269,objectId=e2857418-b873-47b7-ab30-441ae9376529,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + uuid:ba2435fc-9172-69d8-f4be-34f7f45b26ff + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=cbe0cada-e8ee-424c-945b-f6c42df7b011,class=queue,name=1232952196269,objectId=e2857418-b873-47b7-ab30-441ae9376529,package=org.apache.qpid + + + + http://docs.oasis-open.org/wsrf/rmd-1 + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse + uuid:ceb6eb90-4910-01a9-c138-6029e6bb0836 + uuid:ba2435fc-9172-69d8-f4be-34f7f45b26ff + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=cbe0cada-e8ee-424c-945b-f6c42df7b011,class=queue,name=1232952196269,objectId=e2857418-b873-47b7-ab30-441ae9376529,package=org.apache.qpid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/example/GetResourcePropertyDocument.out.ok b/java/management/client/src/example/GetResourcePropertyDocument.out.ok new file mode 100644 index 0000000000..9d6312f2f3 --- /dev/null +++ b/java/management/client/src/example/GetResourcePropertyDocument.out.ok @@ -0,0 +1,138 @@ + GetResourcePropertyDocument +------------------------------------------------------------------- + +This example shows how to get the whole property +document from a WS-Resource. +Resource property document represents a particular +composed structural view of the resource properties +of the WS-Resource. +First of all a request is send to WS-DM in order to get +all registered WS-Resources. +the target WS-Resource. +If the returned list is not empty then a +GetResourcePropertyDocumentRequest is sent to the first child. + +------------------------------------------------------------------- + +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:50aa09f5-44e7-8bd3-7f24-49b8f0b9bf0d + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:f71342ad-2185-fdb3-393a-e9a98305effd + uuid:50aa09f5-44e7-8bd3-7f24-49b8f0b9bf0d + + http://localhost:8080/qman/services/adapter + + + + + + + http://localhost:8080/qman/services/ServiceGroupEntry + + uuid:b220e2bd-0370-da4e-fc71-5e283954d319 + + + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentRequest + uuid:e035946b-c3f5-1b24-e94a-61c674ce07b9 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourcePropertyDocument/GetResourcePropertyDocumentResponse + uuid:dafe12e4-c0a9-f872-cf1e-2a41bc291b2e + uuid:e035946b-c3f5-1b24-e94a-61c674ce07b9 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + 32767 + http://www.w3.org/TR/1999/REC-xpath-19991116 + Initial Name + + 9223372036854775797 + + + Key3 + 2147483647 + + + Key4 + 3.4028235E38 + + + Key1 + aStringValue + + + Key2 + -9223372036854775808 + + + 2deef1b3-d2c6-49f3-a8de-51f6a75a1a6b + 1232956293823 + 9223372036854775807 + true + -2147483638 + + + + \ No newline at end of file diff --git a/java/management/client/src/example/GetResourcePropertyRequest.out.ok b/java/management/client/src/example/GetResourcePropertyRequest.out.ok new file mode 100644 index 0000000000..4fa0ab3b8d --- /dev/null +++ b/java/management/client/src/example/GetResourcePropertyRequest.out.ok @@ -0,0 +1,588 @@ + GetResourcePropertyExample +------------------------------------------------------------------- + +This example shows how to get the property value +from a WS-Resource. +First of all a request is send to WS-DM in order to get +all registered WS-Resources. +If the returned list is not empty then a GetMetadataRequest +to the first child. +The result metadata descriptor contains all properties of +the target WS-Resource. +For each of them a GetResourcePropertyRequest is sent + in order to get its value. + +------------------------------------------------------------------- + +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:e581b9cb-04a9-a87f-7763-dcf227ed7f8b + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:27bab9a7-89aa-16a1-966b-c0aa19d3b352 + uuid:e581b9cb-04a9-a87f-7763-dcf227ed7f8b + + http://localhost:8080/qman/services/adapter + + + + + + + http://localhost:8080/qman/services/ServiceGroupEntry + + uuid:b220e2bd-0370-da4e-fc71-5e283954d319 + + + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + uuid:c5efae22-bc2f-ccdd-477c-621d4e49cd77 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + http://docs.oasis-open.org/wsrf/rmd-1 + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse + uuid:4d933676-fb60-3fae-d7b9-39324a8661fc + uuid:c5efae22-bc2f-ccdd-477c-621d4e49cd77 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:83c13239-3e37-853d-776d-3dac2729117b + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:MgmtPubInterval + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:0beb3927-6420-9877-f163-4288ea1560da + uuid:83c13239-3e37-853d-776d-3dac2729117b + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + 32767 + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:30b678da-f1fa-8120-7660-9eb86ebb76b7 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:Name + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:8343b104-1a82-212a-c84a-460cbc223327 + uuid:30b678da-f1fa-8120-7660-9eb86ebb76b7 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + Initial Name + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:795eaebd-dd48-75b0-18b3-a7e3c1fd4d5a + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:MsgTotalEnqueues + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:b6b91fd1-762b-3ae4-76c3-fe206c93b76d + uuid:795eaebd-dd48-75b0-18b3-a7e3c1fd4d5a + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + 9223372036854775797 + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:f57f0179-a31b-8607-668b-c2602838c363 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:Arguments + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:fc07cbe4-a19a-6374-c985-49fa525d3e90 + uuid:f57f0179-a31b-8607-668b-c2602838c363 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + + Key3 + 2147483647 + + + Key4 + 3.4028235E38 + + + Key1 + aStringValue + + + Key2 + -9223372036854775808 + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:5d735040-95d1-7c87-7ac9-b4a5700e0ab9 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:VhostRef + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:cdfe639c-357b-d55b-fe7d-4a203d46465c + uuid:5d735040-95d1-7c87-7ac9-b4a5700e0ab9 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + 2deef1b3-d2c6-49f3-a8de-51f6a75a1a6b + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:e3fde856-57f5-a96f-a382-5e0f4206a6fe + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:ExpireTime + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:fa290c54-bac1-62d6-701e-3b8ec2eaf817 + uuid:e3fde856-57f5-a96f-a382-5e0f4206a6fe + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + 9223372036854775807 + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:092dd5d9-c443-428c-813c-13428058b08c + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:Durable + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:1053800e-345c-abed-e352-f524c1d24afa + uuid:092dd5d9-c443-428c-813c-13428058b08c + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + true + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:bc291be9-b1d1-f668-f3c5-29647e78d6bf + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:ConsumerCount + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:7467dddf-033e-f540-241f-76ce81c0ebeb + uuid:bc291be9-b1d1-f668-f3c5-29647e78d6bf + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + -2147483638 + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:92783239-777c-27fa-cec2-ee3afecf5c32 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + qman:Type + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:af8168b4-6c13-c736-b521-f2b410541dd0 + uuid:92783239-777c-27fa-cec2-ee3afecf5c32 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=8e069b14-40ba-4d48-a2cb-b9f2bef2d404,class=queue,name=1232953394537,objectId=781f4ad7-4c96-4caa-b69d-291461cdb1fc,package=org.apache.qpid + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources b/java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources new file mode 100644 index 0000000000..6e727261f9 --- /dev/null +++ b/java/management/client/src/example/GetWsdlMetadata.out.ko.no.resources @@ -0,0 +1,58 @@ + GetWSDLMetadataExample +------------------------------------------------------------------- + +This example shows the usage of WS-DM +GetResourcePropertyRequest / Response on a +Group service. +The target resource is the WS-DM Adapter itself +and the requested property is "ws-rp:Entry". +WS-DM Adapter is a special WS-Resource (is a Group) +that acts as the main entry point for retrieving +all other managed resources. +So clients that want to deal with QMan WS-Resources +must first get resource identifiers sending +a GetResourcePropertyRequest to WS-DM Adapter +with "ws-rp:Entry" as target target property. + +------------------------------------------------------------------- + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:7f801eff-c528-91e8-33eb-3d1dd164bce7 + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:86a34968-38aa-83e8-47dd-8e86ffd8ac06 + uuid:7f801eff-c528-91e8-33eb-3d1dd164bce7 + + http://localhost:8080/qman/services/adapter + + + + + + + +----------------------------WARNING--------------------------- +Cannot proceed with the example... it seems +that there are no managed WS-Resources on QMan. +Please check QMan in order to see that it is really +connected with a broker. +------------------------------------------------------------------- diff --git a/java/management/client/src/example/GetWsdlMetadata.out.ok b/java/management/client/src/example/GetWsdlMetadata.out.ok new file mode 100644 index 0000000000..16a4c1e07e --- /dev/null +++ b/java/management/client/src/example/GetWsdlMetadata.out.ok @@ -0,0 +1,1968 @@ + GetWSDLMetadataExample +------------------------------------------------------------------- + +This example shows the usage of WS-DM +GetResourcePropertyRequest / Response on a +Group service. +The target resource is the WS-DM Adapter itself +and the requested property is "ws-rp:Entry". +WS-DM Adapter is a special WS-Resource (is a Group) +that acts as the main entry point for retrieving +all other managed resources. +So clients that want to deal with QMan WS-Resources +must first get resource identifiers sending +a GetResourcePropertyRequest to WS-DM Adapter +with "ws-rp:Entry" as target target property. + +------------------------------------------------------------------- + +Type enter to proceed. + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/adapter + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:ec4d0c03-3174-e39d-4a36-8f109056865b + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + wsrf-sg:Entry + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:0f47d614-565e-5360-8dcc-ea8e4771e4dd + uuid:ec4d0c03-3174-e39d-4a36-8f109056865b + + http://localhost:8080/qman/services/adapter + + + + + + + http://localhost:8080/qman/services/ServiceGroupEntry + + uuid:1d01b4ee-7d23-3a30-342e-62fc49984fe6 + + + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=d5b32f44-5164-4e59-8f1d-a6f8c0a8a748,class=queue,name=1232872843214,objectId=a3759467-bede-476d-8dde-169f1a652191,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + uuid:0cdb5112-09e0-ac39-06ba-393843f06e42 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=d5b32f44-5164-4e59-8f1d-a6f8c0a8a748,class=queue,name=1232872843214,objectId=a3759467-bede-476d-8dde-169f1a652191,package=org.apache.qpid + + + + http://schemas.xmlsoap.org/wsdl/ + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse + uuid:980617c8-e3a0-ebf1-8f5a-2b43d3d6d416 + uuid:0cdb5112-09e0-ac39-06ba-393843f06e42 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=d5b32f44-5164-4e59-8f1d-a6f8c0a8a748,class=queue,name=1232872843214,objectId=a3759467-bede-476d-8dde-169f1a652191,package=org.apache.qpid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To form a QName, the name of any MetadataDescriptor must be + unique within a Definitions element. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get access to the xml: attribute groups for xml:lang as declared on 'schema' + and 'documentation' below + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/example/PauseAndResumeSubscription.out.ok b/java/management/client/src/example/PauseAndResumeSubscription.out.ok new file mode 100644 index 0000000000..8a98e1d0b7 --- /dev/null +++ b/java/management/client/src/example/PauseAndResumeSubscription.out.ok @@ -0,0 +1,133 @@ +This example is demonstrating a WS-Notification scenario +when (for simplicity) QMan is at the same time consumer +and producer. + +Specifically the example shows how a requestor can create, +pause and resume a subscription. +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://romagazzarini:8080/qman/services/adapter + http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeRequest + uuid:485cc87c-660e-de43-e8fa-4ad5fffa95a6 + + http://www.w3.org/2005/08/addressing/role/anonymous + + + + + + http://romagazzarini:8080/qman/services/consumer + + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsn/bw-2/NotificationProducer/SubscribeResponse + uuid:0ee610d1-e211-95c6-a498-e1084a610c44 + uuid:485cc87c-660e-de43-e8fa-4ad5fffa95a6 + + http://romagazzarini:8080/qman/services/adapter + + + + + + http://romagazzarini:8080/qman/services/SubscriptionManager + + 282f28e6-4396-4000-a19d-87a03978e8a0 + + + 2009-02-27T13:51:56+01:00 + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://romagazzarini:8080/qman/services/SubscriptionManager + http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/PauseSubscriptionRequest + uuid:35cc80af-84ac-2456-3e1f-edc2a7f60970 + + http://www.w3.org/2005/08/addressing/role/anonymous + + 282f28e6-4396-4000-a19d-87a03978e8a0 + + + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/PauseSubscriptionResponse + uuid:bb53d38a-428c-3d90-cc45-29d5cb27a8df + uuid:35cc80af-84ac-2456-3e1f-edc2a7f60970 + + http://romagazzarini:8080/qman/services/SubscriptionManager + + 282f28e6-4396-4000-a19d-87a03978e8a0 + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://romagazzarini:8080/qman/services/SubscriptionManager + http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/ResumeSubscriptionRequest + uuid:bfb48615-905a-e472-a9ca-5483fa592f60 + + http://www.w3.org/2005/08/addressing/role/anonymous + + 282f28e6-4396-4000-a19d-87a03978e8a0 + + + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager/ResumeSubscriptionResponse + uuid:aab4cf18-3cc0-30c4-7036-009e26bb3213 + uuid:bfb48615-905a-e472-a9ca-5483fa592f60 + + http://romagazzarini:8080/qman/services/SubscriptionManager + + 282f28e6-4396-4000-a19d-87a03978e8a0 + + + + + + + + diff --git a/java/management/client/src/example/README.txt b/java/management/client/src/example/README.txt new file mode 100644 index 0000000000..5365a416e5 --- /dev/null +++ b/java/management/client/src/example/README.txt @@ -0,0 +1,69 @@ +*** QMan WS-DM examples *** + +1) DESCRIPTION +This set of examples shows QMan WS-DM interface capabilities. +Each example is articulated in the following way. +First the name of the example class with a brief description about that is printed out. For example : + + GetWSDLMetadataExample +------------------------------------------------------------------- + +This example shows the usage of WS-DM +GetResourcePropertyRequest / Response on a +Group service. +The target resource is the WS-DM Adapter itself +and the requested property is "ws-rp:Entry". +WS-DM Adapter is a special WS-Resource (is a Group) +that acts as the main entry point for retrieving +all other managed resources. +So clients that want to deal with QMan WS-Resources +must first get resource identifiers sending +a GetResourcePropertyRequest to WS-DM Adapter +with "ws-rp:Entry" as target target property. + +------------------------------------------------------------------- + +Type enter to proceed. + +When you're ready type enter to proceed. Now the example runs and all the exchanged +SOAP messages are printed out on the screen. +If you want, we shipped (under sample_messages folder) several files containing those messages. + +A general note concerning examples...they are all written using java language so what you see is the +"java" usage of WS-DM client API. +The most important thing that you should keep in mind is that what is expected (on QMan side) is a SOAP WS-DM +compliant message so on top of that you don't need to use those java API but feel free to produce those messages +in your preferred way (by hand or using another programming language). + +Another thing : the examples contain a lot of code duplication because each of them is took as independent as possible. +The general idea is that you open an example source file and in the executeExample(...) method you should have a quick +idea of how things are working. +Also, as mentioned before, we provided, under the sample_messages folder, the messages that are part of each example conversation. +Remember : these messages are important, not the way / language you use to produce them. + +2) HOW TO RUN + +2.1) Java +You need JDK 1.5 or higher in order to run and / or compile the examples. + +2.2) Dependencies +You need to set / update the CLASSPATH environment variable with libraries found under $QMAN_HOME/app/qman/WEB-INF/lib. +After that you should be able to run one the shipped examples: + +> java org.apache.qpid.management.example.GetMultipleResourcePropertiesExample +> java org.apache.qpid.management.example.GetQManResourceMembersExample +> java org.apache.qpid.management.example.GetResourceMetadataDescriptorExample +> java org.apache.qpid.management.example.GetResourcePropertyDocumentExample +> java org.apache.qpid.management.example.GetResourcePropertyExample +> java org.apache.qpid.management.example.GetWSDLMetadataExample +> java org.apache.qpid.management.example.SetResourcePropertyExample + +Where + is the host (ip or hostname) where QMan is running; + is the port number where QMan is running; + +2.3) Qpid +You must have a running C++ broker with management enabled. + +2.4) QMan +You must have QMan WS-DM up, running and connected with the broker above. \ No newline at end of file diff --git a/java/management/client/src/example/SetResourcePropertiesRequest.out.ok b/java/management/client/src/example/SetResourcePropertiesRequest.out.ok new file mode 100644 index 0000000000..1f346afa4e --- /dev/null +++ b/java/management/client/src/example/SetResourcePropertiesRequest.out.ok @@ -0,0 +1,2316 @@ + SetResourcePropertyExample +------------------------------------------------------------------- + +This example shows how to change the state of a WS-Resource. +That means a SetResourcePropertyRequest is sent to that +WS-Resource. +First of all a request is send to WS-DM in order to get all +registered WS-Resources. +If the returned list is not empty then two GetMetadataRequests +(one for WSDL and one for RDM) are sent to the first child. +The result metadata descriptors are used for determine : + +1) WS-Resource property names; +2) Modifiability (read-only, read-write +3) Datatype; +------------------------------------------------------------------- + +So a SetResourcePropertyRequest can be sent in order +to change the WS-Resource state. +The example is looking for a property that has one of the +following datatype : + +1) String (xsd:string) +2) Long (xsd:long) +3) Integer (xsd:integer or xsd:int) +4) Double (xsd:double) +5) Float (xsd:float) +6) Short (xsd:short) + +After the update / insert request has been sent, a +GetResourcePropertiesRequest is made again +in order to see if the state has changed correctly. + +Type enter to proceed... + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + uuid:d026718c-2724-d3bf-fd5b-3c6bf4cd5a8c + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + http://docs.oasis-open.org/wsrf/rmd-1 + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse + uuid:dba8d7ab-83a6-16e1-03cc-48edc672a325 + uuid:d026718c-2724-d3bf-fd5b-3c6bf4cd5a8c + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + uuid:11581af1-04af-05cd-7215-103cad6a316c + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + http://schemas.xmlsoap.org/wsdl/ + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadataResponse + uuid:785964d4-9a81-784f-d68a-60de63223094 + uuid:11581af1-04af-05cd-7215-103cad6a316c + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To form a QName, the name of any MetadataDescriptor must be + unique within a Definitions element. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get access to the xml: attribute groups for xml:lang as declared on 'schema' + and 'documentation' below + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:103f564f-7008-8456-042f-095a092444f9 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + qman:MgmtPubInterval + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:b78625a8-af2f-b542-8001-d7e81d3de1c9 + uuid:103f564f-7008-8456-042f-095a092444f9 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + 32767 + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest + uuid:0b80a9ca-9e02-1d6b-c0e0-8ceb8560ee6e + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + 12 + + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse + uuid:ae67ff51-e1c1-f2c3-5243-d54905f3907b + uuid:0b80a9ca-9e02-1d6b-c0e0-8ceb8560ee6e + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:0dca61e4-072f-3091-0f38-9a967f14666a + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + qman:MgmtPubInterval + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:84399474-c5b1-8738-f410-fd86face1599 + uuid:0dca61e4-072f-3091-0f38-9a967f14666a + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + 12 + + + + +---------------------------------------------------------------------------------- +Resource has been correctly updated. +---------------------------------------------------------------------------------- +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:8be37e48-b3a5-0e4a-aea3-eda3aad58418 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + qman:Type + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:b92c8851-d071-204f-6506-3706694cf32e + uuid:8be37e48-b3a5-0e4a-aea3-eda3aad58418 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest + uuid:7917abf6-5c85-7e25-4515-b7f60cd32c39 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + This is a string. + + + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesResponse + uuid:0b895a1f-39e5-8739-d9d7-390c5f2eb445 + uuid:7917abf6-5c85-7e25-4515-b7f60cd32c39 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + + + +[CLIENT TRACE] SOAP envelope contents (outgoing): + + + + http://localhost:8080/qman/services/QManWsResource + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyRequest + uuid:930f39a4-0114-03bd-9921-105579fb4213 + + http://www.w3.org/2005/08/addressing/role/anonymous + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + qman:Type + + + +[CLIENT TRACE] SOAP envelope contents (incoming): + + + + http://www.w3.org/2005/08/addressing/role/anonymous + http://docs.oasis-open.org/wsrf/rpw-2/GetResourceProperty/GetResourcePropertyResponse + uuid:3d3f04ab-3171-da69-08b5-2e74927ee981 + uuid:930f39a4-0114-03bd-9921-105579fb4213 + + http://localhost:8080/qman/services/QManWsResource + + Q-MAN: brokerID=0ef67394-e34a-4bff-b0bf-88cf359ba1a0,class=queue,name=1232966356552,objectId=894cddd3-b893-4e2f-94d2-2489f72cbdd6,package=org.apache.qpid + + + + + + This is a string. + + + + +---------------------------------------------------------------------------------- +Resource has been correctly updated. +---------------------------------------------------------------------------------- diff --git a/java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java b/java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java new file mode 100644 index 0000000000..ffa96635a8 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/AbstractQManExample.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import java.io.IOException; +import java.net.URI; + +import org.apache.muse.ws.addressing.EndpointReference; + +/** + * Common interface for all QMan related examples. + * + * @author Andrea Gazzarini + */ +public abstract class AbstractQManExample +{ + final static String LINE_SEPARATOR = System.getProperty("line.separator","\n"); + protected final static String PREFIX = "qman"; + + /** + * Prints out the expected command line of this sample and after that exits. + */ + static void printUsageAndExit(String reason) + { + StringBuilder builder = new StringBuilder(); + builder.append("WARNING! Unable to run this sample : ") + .append(reason) + .append(LINE_SEPARATOR) + .append("-------------------------------------------------------------") + .append(LINE_SEPARATOR) + .append("Expected command line args for this sample are :") + .append(LINE_SEPARATOR) + .append(LINE_SEPARATOR) + .append("1) host : ip or host name where QMan is running.") + .append(LINE_SEPARATOR) + .append("2) port : port number where QMan is running.") + .append(LINE_SEPARATOR) + .append("------------------------------------------------------------"); + System.out.println(builder); + System.exit(1); + } + + /** + * Prints out a description of this example. + */ + abstract void printOutExampleDescription(); + + /** + * Executes this example. + * Note that this is just a template method used to avoid code duplication + * (printOutExampleDescription() line) so in order to see how the example + * works you should have a look at the concrete implementation of + * executeExample(String host, int port). + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + */ + void execute(String [] arguments) + { + if (arguments.length != 2){ + printUsageAndExit("invalid command line was given."); + } + + try + { + // 1) Parses command line arguments... + String host = arguments[0]; + int port = Integer.parseInt(arguments[1]); + + printOutExampleDescription(); + + waitForUserInput("Type enter to proceed..."); + + executeExample(host, port); + + } catch(NumberFormatException exception) + { + printUsageAndExit("port number must be a number."); + } catch(Exception exception) + { + System.out.println("-----------------------EXAMPLE FAILURE-----------"); + System.out.println("Not well-defined exception was detected while"); + System.out.println("running the example."); + exception.printStackTrace(System.out); + System.out.println("--------------------------------------------------------"); + } + } + + protected void waitForUserInput(String message) throws IOException { + System.out.println(message); + System.in.read(); + } + + /** + * Each concrete implementor must define here how the example works. + * So, on top of that, user who wants to see how to use a specific feature + * should have a look at the concrete implementation of this method.. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception{}; + + /** + * Returns the endpoint reference of the adapter service. + * + * @param host ip or host name where the service is running. + * @param port the port number of the server where the service is running. + * @return the endpoint reference of the adapter service. + */ + EndpointReference getAdapterEndpointReference(String host, int port) + { + URI address = URI.create( + "http://"+ + host+ + ":"+ + port+ + "/qman/services/adapter"); + return new EndpointReference(address); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java b/java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java new file mode 100644 index 0000000000..153f0f66d5 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/ConnectWithBrokerExample.java @@ -0,0 +1,240 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; + +/** + * This example shows how to connect QMan with a broker using the adapter interface. + * As you can see the interface is very simple and requests you the following parameters : + * + *
    + *
  • hostname : the host (hostname or ip) where the broker is running;
  • + *
  • port : the port number of the running broker;
  • + *
  • virtual host : the name of the virtual host;
  • + *
  • username : the username that will be used for estabilshing connection.
  • + *
  • password : the password that will be used for estabilshing connection.
  • + *
  • initial pool capacity : the initial size of broker connection pool.
  • + *
  • maximum pool capacity : the max allowed size of broker connection pool.
  • + *
  • maximum wait timeout : the max wait timeout for retrieving connections.
  • + *
+ * + * @author Andrea Gazzarini + */ +public class ConnectWithBrokerExample extends AbstractQManExample +{ + + /** + * Executes the connect example. + * Although not specified explicitly, the input array MUST contains in the following order : + * + *
    + *
  • host : the hostname where QMan is running;
  • + *
  • port : the port number where QMan is running;
  • + *
  • qpid host : the host name where QPid is running;
  • + *
  • qpid port : the port number where Qpid is running;
  • + *
  • virtual host : the virtual host name;
  • + *
  • username : the username that will be used for estabilshing connection.
  • + *
  • password : the password that will be used for estabilshing connection.
  • + *
  • initial pool capacity : the initial size of broker connection pool.
  • + *
  • maximum pool capacity : the max allowed size of broker connection pool.
  • + *
  • maximum wait timeout : the max wait timeout for retrieving connections.
  • + *
+ * + * Note that this example differs from the others (and therefore is overriding the execute() method) because + * in this case we are not using the "standard" WSRF interface but instead an additional custom + * "operation" on a WS-Resource. + * + * @param arguments the commadn line arguments. + */ + void execute(String [] arguments) + { + if (arguments.length != 10){ + printUsageAndExit("invalid command line was given."); + } + + try + { + // 1) Parses command line arguments... + String host = arguments[0]; + int port = Integer.parseInt(arguments[1]); + String qpidHost = arguments[2]; + int qpidPort = Integer.parseInt(arguments[3]); + String virtualHost = arguments[4]; + String username = arguments[5]; + String password = arguments[6]; + int initPoolCapacity = Integer.parseInt(arguments[7]); + int maxPoolCapacity = Integer.parseInt(arguments[8]); + long maxWaitTimeout = Long.parseLong(arguments[9]); + + printOutExampleDescription(); + + waitForUserInput("Type enter to proceed..."); + + executeExample( + host, + port, + qpidHost, + qpidPort, + virtualHost, + username, + password, + initPoolCapacity, + maxPoolCapacity, + maxWaitTimeout); + + } catch(NumberFormatException exception) + { + printUsageAndExit("Unable to run the example. Please ensure that all numeric values are correctly supplied."); + } catch(Exception exception) + { + System.out.println("-----------------------EXAMPLE FAILURE-----------"); + System.out.println("Not well-defined exception was detected while"); + System.out.println("running the example."); + exception.printStackTrace(System.out); + System.out.println("--------------------------------------------------------"); + } + } + + /** + * Connects QMan with a broker. + * + *@param host the hostname where QMan is running; + *@param port the port number where QMan is running; + *@param qpidHost the host name where QPid is running; + *@param qpidPort the port number where Qpid is running; + *@param virtualHost the virtual host name; + *@param username the username that will be used for estabilshing connection. + *@param password the password that will be used for estabilshing connection. + *@param initPoolCapacity the initial size of broker connection pool. + *@param maxPoolCapacity the max allowed size of broker connection pool. + *@param maxWaitTimeout the max wait timeout for retrieving connections. + * + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port, String qpidHost, int qpidPort, String virtualHost, String username, String password, int initPoolCapacity, int maxPoolCapacity, long maxWaitTimeout) throws Exception + { + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + WsResourceClient adapterClient = new WsResourceClient(adapterEndpointReference); + adapterClient.setTrace(true); + + // 2) Creates the Adapter service client... + adapterClient.invoke( + getProxyHandler(), + new Object[]{ + qpidHost, + qpidPort, + username, + password, + virtualHost, + initPoolCapacity, + maxPoolCapacity, + maxWaitTimeout}); + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("This example shows how to connect QMan with a broker using"); + System.out.println("the adapter interface."); + System.out.println(); + } + + /** + * A proxy handler is a module needed in order to make a capability + * service invocation. + * It contains logic to serialize and deserialize request, response, input and + * output parameters during a web service invocation. + * + * @return a proxy handler. + */ + private ProxyHandler getProxyHandler() + { + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction("http://amqp.apache.org/qpid/management/qman/Connect"); + handler.setRequestName(new QName("http://amqp.apache.org/qpid/management/qman", "Connect", PREFIX)); + handler.setRequestParameterNames(new QName[]{ + new QName("http://amqp.apache.org/qpid/management/qman", "host", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "port", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "username", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "password", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "virtualHost", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "initialPoolCapacity", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "maxPoolCapacity", PREFIX), + new QName("http://amqp.apache.org/qpid/management/qman", "maxWaitTimeout", PREFIX)}); + handler.setResponseName(new QName("http://amqp.apache.org/qpid/management/qman", "ConnectResponse", PREFIX)); + handler.setReturnType(null); + return handler; + } + + public static void main(String[] arguments) + { + new ConnectWithBrokerExample().execute(arguments); + } + + static void printUsageAndExit(String reason) + { + StringBuilder builder = new StringBuilder(); + builder.append("WARNING! Unable to run this sample : ") + .append(reason) + .append(LINE_SEPARATOR) + .append("-------------------------------------------------------------") + .append(LINE_SEPARATOR) + .append("Expected command line args for this sample are :") + .append(LINE_SEPARATOR) + .append(LINE_SEPARATOR) + .append("1) host : ip or host name where QMan is running.") + .append(LINE_SEPARATOR) + .append("2) port : port number where QMan is running.") + .append(LINE_SEPARATOR) + .append("3) qpid host : port number where Qpid is running.") + .append(LINE_SEPARATOR) + .append("4) qpid port : port number where Qpid is running.") + .append(LINE_SEPARATOR) + .append("5) virtual host : virtual host name.") + .append(LINE_SEPARATOR) + .append("6) username : port number where QMan is running.") + .append(LINE_SEPARATOR) + .append("7) password : port number where QMan is running.") + .append(LINE_SEPARATOR) + .append("8) initial pool capacity : port number where QMan is running.") + .append(LINE_SEPARATOR) + .append("9) max pool capacity : port number where QMan is running.") + .append(LINE_SEPARATOR) + .append("10) max wait timeout : port number where QMan is running.") + .append(LINE_SEPARATOR) + + .append("------------------------------------------------------------"); + System.out.println(builder); + System.exit(1); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java b/java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java new file mode 100644 index 0000000000..42587d78ff --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/ConsumerAndProducerExample.java @@ -0,0 +1,293 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import java.net.URI; +import java.util.Date; + +import org.apache.muse.util.xml.XPathUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.notification.impl.FilterCollection; +import org.apache.muse.ws.notification.impl.MessagePatternFilter; +import org.apache.muse.ws.notification.impl.ProducerPropertiesFilter; +import org.apache.muse.ws.notification.impl.TopicFilter; +import org.apache.muse.ws.notification.remote.NotificationProducerClient; +import org.apache.qpid.management.Names; + +/** + * This example is demonstrating a WS-Notification scenario + * when (for simplicity) QMan is at the same time consumer + * and producer. + * + * Basically we have (on producer side) two topics : one for + * lifecycle events of object instance (objects created & removed) + * and another one for lifecycle of event (events created). + * + * On consumer side there are many options that you can use in + * order to made a sunscription : + * + *
    + *
  • you could be an observer of all messages (all topics);
  • + *
  • you could be an observer of one specific topic;
  • + *
  • + * you could be an observer of all messages that match + * a condition expressed in XPath; + *
  • + *
+ * + * All those options are provided with or withour a termination time. + * A subscription with a termination time will have a predefined expiry + * date while if there's no termination the subscription will never expire. + * + * @author Andrea Gazzarini + * + */ +public class ConsumerAndProducerExample extends AbstractQManExample +{ + @Override + void executeExample(String host, int port) throws Exception + { + // This is QMan... + URI producerURI = URI.create("http://"+host+":"+port+"/qman/services/adapter"); + + // ...and this is QMan too! Note that it has an hidden consumer capability that is used in + // order to run successfully this example... + URI consumerURI = URI.create("http://"+host+":"+port+"/qman/services/consumer"); + + EndpointReference producerEPR = new EndpointReference(producerURI); + EndpointReference consumerEPR = new EndpointReference(consumerURI); + + // Example 1 : all messages on all topics without termination time. + subscribeAllMessagesWithoutTerminationTime(producerEPR,consumerEPR); + + // Example 2 : all messages on all topics with termination time. + subscribeAllMessagesWithTerminationTime(producerEPR,consumerEPR); + + // Example 3: Topic filter without termination time. + topicSubscriptionWithoutTerminationTime(producerEPR,consumerEPR); + + // Example 4: Topic filter with termination time. + topicSubscriptionWithTerminationTime(producerEPR,consumerEPR); + + // Example 5: a MessageFilter is installed in order to listen only for connection events + // (connections created or removed). The subscription never expire. + allMessagesWithMessageFilterWithoutTerminationTime(producerEPR,consumerEPR); + + // Example 6: a MessageFilter is installed in order to listen only for connection events + // (connections created or removed). The subscription will expire in 10 seconds. + allMessagesWithMessageFilterAndTerminationTime(producerEPR,consumerEPR); + + // Example 7 : a subscription with more than one filter. + complexSubscription(producerEPR, consumerEPR); + } + + /** + * Makes a subscription on all topics / all messages without an expiry date. + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void subscribeAllMessagesWithoutTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + null, // Filter, if null that means "all messages" + null); // Termination Time : if null the subscription will never expire. + } + + /** + * Makes a subscription on all topics / all messages with 10 seconds as termination time. + * The subscription will expire after 10 seconds. + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void subscribeAllMessagesWithTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + null, // Filter, if null that means "all messages" + new Date(System.currentTimeMillis() + 10000)); // Termination Time + } + + /** + * Makes a subscription on a specifc topic without an expiry date. + * Only messages published on the given topic will be delivered to the given consumer. + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void topicSubscriptionWithoutTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + TopicFilter filter = new TopicFilter(Names.EVENTS_LIFECYLE_TOPIC_NAME); + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + filter, // Topic Filter + null); // Termination Time : if null the subscription will never expire. + } + + /** + * Makes a subscription on a specifc topic with an expiry date. + * Only messages published on the given topic will be delivered to the given consumer. + * The subscription will end after 10 seconds + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void topicSubscriptionWithTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + TopicFilter filter = new TopicFilter(Names.EVENTS_LIFECYLE_TOPIC_NAME); + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + filter, // Topic Filter + new Date(System.currentTimeMillis() + 10000)); // Termination Time + } + + /** + * Makes a subscription on all topics with a message filter without an expiry date. + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void allMessagesWithMessageFilterWithoutTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + // Applying this filter will result in a subscription that wll be notified only when a "connection" + // object is created or removed + MessagePatternFilter filter= new MessagePatternFilter( + "/wsnt:NotificationMessage/wsnt:Message/qman:LifeCycleEvent/qman:Resource/qman:Name/text()='connection'", // expression (XPath) + XPathUtils.NAMESPACE_URI); // Dialect : the only supported dialect is XPath 1.0 + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + filter, // Message Filter + null); // Termination Time : if null the subscription will never expire. + } + + /** + * Makes a subscription on all topics with a message filter and an expiry date. + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void allMessagesWithMessageFilterAndTerminationTime(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + // Applying this filter will result in a subscription that wll be notified only when a "connection" + // object is created or removed + MessagePatternFilter filter= new MessagePatternFilter( + "/wsnt:NotificationMessage/wsnt:Message/qman:LifeCycleEvent/qman:Resource/qman:Name/text()='connection'", // expression (XPath) + XPathUtils.NAMESPACE_URI); // Dialect : the only supported dialect is XPath 1.0 + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + filter, // Message Filter + new Date(System.currentTimeMillis() + 10000)); // Termination Time + } + + /** + * Makes a subscription on a specifc topic with an expiry date. + * Only messages published on the given topic will be delivered to the given consumer. + * The subscription will end after 10 seconds + * + * @param producer the producer endpoint reference. + * @param consumer the consumer endpoint reference . + * @throws SoapFault when the subscription cannot be made. + */ + private void complexSubscription(EndpointReference producer, EndpointReference consumer) throws SoapFault + { + NotificationProducerClient producerClient = new NotificationProducerClient(producer); + producerClient.setTrace(true); + + FilterCollection filter = new FilterCollection(); + + TopicFilter topicFilter = new TopicFilter(Names.EVENTS_LIFECYLE_TOPIC_NAME); + MessagePatternFilter messageFilter= new MessagePatternFilter( + "/wsnt:NotificationMessage/wsnt:Message/qman:LifeCycleEvent/qman:Resource/qman:Name/text()='connection'", // expression (XPath) + XPathUtils.NAMESPACE_URI); // Dialect : the only supported dialect is XPath 1.0 + + ProducerPropertiesFilter producerFilter = new ProducerPropertiesFilter( + "boolean(/*/MgtPubInterval > 100 and /*/MsgTotalEnqueues > 56272)", + XPathUtils.NAMESPACE_URI); + + filter.addFilter(topicFilter); + filter.addFilter(messageFilter); + filter.addFilter(producerFilter); + + producerClient.subscribe( + consumer, // Consumer Endpoint reference + filter, // Topic Filter + new Date(System.currentTimeMillis() + 10000)); // Termination Time + } + + @Override + void printOutExampleDescription() + { + System.out.println("This example is demonstrating a WS-Notification scenario "); + System.out.println("when (for simplicity) QMan is at the same time consumer "); + System.out.println("and producer."); + System.out.println(); + System.out.println("Basically we have (on producer side) two topics : one for"); + System.out.println("lifecycle events of object instance (objects created & removed) "); + System.out.println("and another one for lifecycle of event (events created)."); + System.out.println(); + System.out.println("On consumer side there are many options that you can use in"); + System.out.println("order to made a sunscription :"); + System.out.println(); + System.out.println("- you could be an observer of all messages (all topics);"); + System.out.println("- you could be an observer of one specific topic;"); + System.out.println("- you could be an observer of all messages that match a condition expressed in XPath;"); + System.out.println(); + System.out.println("All those options are provided with or withour a termination time."); + System.out.println("A subscription with a termination time will have a predefined expiry"); + System.out.println("date while if there's no termination the subscription will never expire."); + } + + public static void main(String[] args) + { + new ConsumerAndProducerExample().execute(new String[]{"localhost","8080"}); + } +} diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java new file mode 100644 index 0000000000..413222a79d --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/GetMultipleResourcePropertiesExample.java @@ -0,0 +1,179 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.w3c.dom.Element; + +/** + * This example shows how to get properties from a WS-Resource using one request. + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then a GetMetadataRequest is sent to the + * first child. + * The result metadata descriptor contains all properties names of the target WS-Resource. + * Those names are then used for retrieving the corresponding values. + * + * @author Andrea Gazzarini + */ +public class GetMultipleResourcePropertiesExample extends AbstractQManExample +{ + + /** + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then a GetMetadataRequest is sent to the + * first child. + * The result metadata descriptor contains all properties names of the target WS-Resource. + * Those names are then used for retrieving the corresponding values. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Adapter service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference); + adapterClient.setTrace(true); + + // 3) Retrieves the all registered members (QMan WS-Resources) + WsResourceClient [] resources = adapterClient.getMembers(); + + // Sanity check : we cannot proceed if there are no WS-Resources. + if (resources.length == 0) + { + System.out.println("----------------------------WARNING---------------------------"); + System.out.println("Cannot proceed with the example... it seems"); + System.out.println("that there are no managed WS-Resources on QMan."); + System.out.println("Please check QMan in order to see that it is really"); + System.out.println("connected with a broker."); + System.out.println("-------------------------------------------------------------------"); + System.exit(0); + } + + // 4) Creates a proxy handler for service invocation. + ProxyHandler metadataProxyHandler = createProxyHandler(); + + // 5) ..and invokes the GetMetadata on the first member. + WsResourceClient wsResourceClient = resources[0]; + wsResourceClient.setTrace(true); + + // Dialect is RDM for this example + String dialect = "http://docs.oasis-open.org/wsrf/rmd-1"; + Object [] inputParameters = {dialect}; + + // RDM is the first element of the returned array. + // The first element is a wsx:Metadata containing all resource properties. + Element [] metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters); + Element resourceMetadataDescriptor = metadata[0]; + + // 6) using XPath navigates xml in order to get the list of all properties. + Element [] properties = XmlUtils.findInSubTree( + resourceMetadataDescriptor, + new QName("http://docs.oasis-open.org/wsrf/rmd-1","Property","wsrmd")); + List names = new ArrayList(); + + for (Element property : properties) + { + + String attributeName = property.getAttribute("name"); // = qman: + + // For this example we are only interested on qman namespace related properties... + if (attributeName.startsWith("qman")) + { + String attributeNameWithoutPrefix = attributeName.replaceFirst("qman:", ""); // = + + names.add(new QName( + "http://amqp.apache.org/qpid/management/qman", + attributeNameWithoutPrefix, + "qman")); + } + } + + QName [] qnames = names.toArray(new QName[names.size()]); + + // 7) Send a GetMultipleResourcePropertiesRequest. + // We do nothing with the returned value(s) because it / they + // has / have already printed out (wsResourceClient.setTrace(true)) + @SuppressWarnings("unused") + Element [] values = wsResourceClient.getMultipleResourceProperties(qnames); + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("This example shows how to get properties from a"); + System.out.println("WS-Resource using one request. "); + System.out.println("First of all a request is send to WS-DM in order to get"); + System.out.println("all registered WS-Resources."); + System.out.println("If the returned list is not empty then a GetMetadataRequest"); + System.out.println("to the first child."); + System.out.println("The result metadata descriptor contains all property names of"); + System.out.println("the target WS-Resource."); + System.out.println("Those names are then used for retrieving the corresponding values"); + System.out.println("using the GetMultipleResourceProperties request."); + System.out.println(); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + } + + /** + * A proxy handler is a module needed in order to make a capability + * service invocation. + * It contains logic to serialize and deserialize request, response, input and + * output parameters during a web service invocation. + * + * @return a proxy handler. + */ + private ProxyHandler createProxyHandler() + { + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX)); + handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)}); + handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX)); + handler.setReturnType(Element[].class); + return handler; + } + + public static void main(String[] arguments) + { + new GetMultipleResourcePropertiesExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java new file mode 100644 index 0000000000..f74a44ab57 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/GetQManResourceMembersExample.java @@ -0,0 +1,93 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; + +/** + * An example demonstrating the usage of GetResourcePropertyRequest/Response on + * the WS-DM Adapter. + * + * @author Andrea Gazzarini + */ +public class GetQManResourceMembersExample extends AbstractQManExample +{ + /** + * Looks for memebers of QMan group requesting ws-rp:Entry property to + * WS-DM Adapter resource service. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + // 1) Creates an endpoint reference of the adapter service... + EndpointReference serviceEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(serviceEndpointReference); + adapterClient.setTrace(true); + + // 3) Invokes the service. + WsResourceClient [] resources = adapterClient.getMembers(); + + String result = (resources.length != 0) + ? ("QMan has at the moment "+resources.length+" registered resources.") + : "It seems that there are no managed resource on QMan side..."; + + System.out.println("--------------------------------------------------------------------------"); + System.out.println(result); + System.out.println("--------------------------------------------------------------------------"); + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("This example shows the usage of WS-DM "); + System.out.println("GetResourcePropertyRequest / Response on a "); + System.out.println("Group service."); + System.out.println("The target resource is the WS-DM Adapter itself "); + System.out.println("and the requested property is \"wsrf-sg:Entry\"."); + System.out.println("WS-DM Adapter is a special WS-Resource (is a Group)"); + System.out.println("that acts as the main entry point for retrieving"); + System.out.println("all other managed resources."); + System.out.println("So clients that want to deal with QMan WS-Resources"); + System.out.println("must first get resource identifiers sending"); + System.out.println("a GetResourcePropertyRequest to WS-DM Adapter "); + System.out.println("with \"wsrf-sg:Entry\" as target target property."); + System.out.println(); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + } + + public static void main(String[] arguments) + { + new GetQManResourceMembersExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java new file mode 100644 index 0000000000..84befc01e4 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/GetResourceMetadataDescriptorExample.java @@ -0,0 +1,156 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.w3c.dom.Element; + +/** + * This example shows how to get metadata from a WS-Resource. + * The service supports different kinds of metadata. + * User who wants to receive metadata of a WS-Resource must + * send a GetMetadataRequesta specifying the requested dialect. + * + * Supported metadata that could be requested are + * + *
    + *
  • + * WSDL : requested using "http://schemas.xmlsoap.org/wsdl/" as dialect.. + *
  • + *
  • + * RDM (Resource Metadata Descriptor) : requested using "http://docs.oasis-open.org/wsrf/rmd-1 "as dialect. + *
  • + *
+ * + * Note that this example focuses on RDM Metadata only; another example is dedicated to WSDL. + * + * @author Andrea Gazzarini + */ +public class GetResourceMetadataDescriptorExample extends AbstractQManExample +{ + + /** + * First, sends a request to WS-DM Adapter in order to get the list of managed resources. + * If the list is not empty, then takes the first member and sends it a GetMetadataRequest + * in order to get its RDM. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Adapter service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference); + adapterClient.setTrace(true); + + // 3) Retrieves the all registered members (QMan WS-Resources) + WsResourceClient [] resources = adapterClient.getMembers(); + + // Sanity check : we cannot proceed if there are no WS-Resources. + if (resources.length == 0) + { + System.out.println("----------------------------WARNING---------------------------"); + System.out.println("Cannot proceed with the example... it seems"); + System.out.println("that there are no managed WS-Resources on QMan."); + System.out.println("Please check QMan in order to see that it is really"); + System.out.println("connected with a broker."); + System.out.println("-------------------------------------------------------------------"); + System.exit(0); + } + + // 4) Creates a proxy handler for service invocation. + ProxyHandler metadataProxyHandler = createProxyHandler(); + + // 5) ..and invokes the GetMetadata on the first member. + WsResourceClient firstMember = resources[0]; + firstMember.setTrace(true); + + // Dialect is RDM for this example + String dialect = "http://docs.oasis-open.org/wsrf/rmd-1"; + Object [] inputParameters = {dialect}; + + // WSDL is the first element of the returned array. We don't need to print out it here + // because at this point it should have been already printed out (line 96 : firstMember.setTrace(true)) + @SuppressWarnings("unused") + Element [] metadata = (Element[]) firstMember.invoke(metadataProxyHandler, inputParameters); + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("The example shows how to get metadata from a"); + System.out.println("WS-Resource."); + System.out.println("A QMan WS-Resource has different kinds of metadata."); + System.out.println("(see below)"); + System.out.println("User who wants to receive metadata of a WS-Resource"); + System.out.println("must send a GetMetadataRequesta specifying the"); + System.out.println("associated dialect."); + System.out.println("Supported metadata that could be requested are : "); + System.out.println(); + System.out.println("- WSDL : in this case dialect is \"http://schemas.xmlsoap.org/wsdl/\";"); + System.out.println("- RDM (Resource Metadata Descriptor) : in this case dialect is \"http://docs.oasis-open.org/wsrf/rmd-1 \"."); + System.out.println(); + System.out.println("Note that this examples focuses on RDM Metadata only;"); + System.out.println("another one is dedicated to WSDL."); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + } + + /** + * A proxy handler is a module needed in order to make a capability + * service invocation. + * It contains logic to serialize and deserialize request, response, input and + * output parameters during a web service invocation. + * + * @return a proxy handler. + */ + private ProxyHandler createProxyHandler() + { + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX)); + handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)}); + handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX)); + handler.setReturnType(Element[].class); + return handler; + } + + public static void main(String[] arguments) + { + new GetResourceMetadataDescriptorExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java new file mode 100644 index 0000000000..56ce81358d --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyDocumentExample.java @@ -0,0 +1,111 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.w3c.dom.Element; + +/** + * This example shows how to get the whole property document from a WS-Resource. + * Resource property document represents a particular composed structural view of + * the resource properties of the WS-Resource. + * Let's say that It is a way to get all-in-once the state of the WS-Resource. + * + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then a GetResourcePropertyDocumentRequest is + * sent to the first child. + * + * @author Andrea Gazzarini + */ +public class GetResourcePropertyDocumentExample extends AbstractQManExample +{ + + /** + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then a GetResourcePropertyDocumentRequest is + * sent to the first child. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Adapter service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference); + adapterClient.setTrace(true); + + // 3) Retrieves the all registered members (QMan WS-Resources) + WsResourceClient [] resources = adapterClient.getMembers(); + + // Sanity check : we cannot proceed if there are no WS-Resources. + if (resources.length == 0) + { + System.out.println("----------------------------WARNING---------------------------"); + System.out.println("Cannot proceed with the example... it seems"); + System.out.println("that there are no managed WS-Resources on QMan."); + System.out.println("Please check QMan in order to see that it is really"); + System.out.println("connected with a broker."); + System.out.println("-------------------------------------------------------------------"); + System.exit(0); + } + + // 4) ..and invokes the GetMetadata on the first member. + WsResourceClient wsResourceClient = resources[0]; + wsResourceClient.setTrace(true); + + @SuppressWarnings("unused") + Element resourcePropertyDocument = wsResourceClient.getResourcePropertyDocument(); + } + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("This example shows how to get the whole property"); + System.out.println("document from a WS-Resource."); + System.out.println("Resource property document represents a particular "); + System.out.println("composed structural view of the resource properties"); + System.out.println("of the WS-Resource."); + System.out.println("First of all a request is send to WS-DM in order to get"); + System.out.println("all registered WS-Resources."); + System.out.println("the target WS-Resource."); + System.out.println("If the returned list is not empty then a"); + System.out.println("GetResourcePropertyDocumentRequest is sent to the first child."); + System.out.println(); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + } + + public static void main(String[] arguments) + { + new GetResourcePropertyDocumentExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java new file mode 100644 index 0000000000..28ed1c7925 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/GetResourcePropertyExample.java @@ -0,0 +1,172 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.w3c.dom.Element; + +/** + * This example shows how to get the property value from a WS-Resource. + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then a GetMetadataRequest is sent to the + * first child. + * The result metadata descriptor contains all properties of the target WS-Resource. + * For each of them a GetResourcePropertyRequest is sent in order to get its value. + * + * @author Andrea Gazzarini + */ +public class GetResourcePropertyExample extends AbstractQManExample +{ + + /** + * First, sends a request to WS-DM Adapter in order to get the list of managed resources. + * If the list is not empty, then takes the first member and sends it a GetMetadataRequest + * in order to get its WSDL. + * After that, for each property contained in ResourceMetadataDescriptorm (RDM) a + * GetResourcePropertyRequest is sent in order to get its value. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Adapter service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference); + adapterClient.setTrace(true); + + // 3) Retrieves the all registered members (QMan WS-Resources) + WsResourceClient [] resources = adapterClient.getMembers(); + + // Sanity check : we cannot proceed if there are no WS-Resources. + if (resources.length == 0) + { + System.out.println("----------------------------WARNING---------------------------"); + System.out.println("Cannot proceed with the example... it seems"); + System.out.println("that there are no managed WS-Resources on QMan."); + System.out.println("Please check QMan in order to see that it is really"); + System.out.println("connected with a broker."); + System.out.println("-------------------------------------------------------------------"); + System.exit(0); + } + + // 4) Creates a proxy handler for service invocation. + ProxyHandler metadataProxyHandler = createProxyHandler(); + + // 5) ..and invokes the GetMetadata on the first member. + WsResourceClient wsResourceClient = resources[0]; + wsResourceClient.setTrace(true); + + // Dialect is RDM for this example + String dialect = "http://docs.oasis-open.org/wsrf/rmd-1"; + Object [] inputParameters = {dialect}; + + // RDM is the first element of the returned array. + // The first element is a wsx:Metadata containing all resource properties. + Element [] metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters); + Element resourceMetadataDescriptor = metadata[0]; + + // 6) using XPath navigates xml in order to get the list of all properties. + Element [] properties = XmlUtils.findInSubTree( + resourceMetadataDescriptor, + new QName("http://docs.oasis-open.org/wsrf/rmd-1","Property","wsrmd")); + + for (Element property : properties) + { + + String attributeName = property.getAttribute("name"); // = qman: + + // For this example we are only interested on qman namespace related properties... + if (attributeName.startsWith("qman")) + { + String attributeNameWithoutPrefix = attributeName.replaceFirst("qman:", ""); // = + + // 7) Send a GetResourcePropertyRequest for the given attribute. + // We do nothing with the returned value(s) because it / they + // has / have already printed out (wsResourceClient.setTrace(true)) + @SuppressWarnings("unused") + Element [] values = wsResourceClient.getResourceProperty( + new QName( + "http://amqp.apache.org/qpid/management/qman", + attributeNameWithoutPrefix, + "qman")); + } + } + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("This example shows how to get the property value"); + System.out.println("from a WS-Resource."); + System.out.println("First of all a request is send to WS-DM in order to get"); + System.out.println("all registered WS-Resources."); + System.out.println("If the returned list is not empty then a GetMetadataRequest"); + System.out.println("to the first child."); + System.out.println("The result metadata descriptor contains all properties of"); + System.out.println("the target WS-Resource."); + System.out.println("For each of them a GetResourcePropertyRequest is sent"); + System.out.println(" in order to get its value."); + System.out.println(); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + } + + /** + * A proxy handler is a module needed in order to make a capability + * service invocation. + * It contains logic to serialize and deserialize request, response, input and + * output parameters during a web service invocation. + * + * @return a proxy handler. + */ + private ProxyHandler createProxyHandler() + { + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX)); + handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)}); + handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX)); + handler.setReturnType(Element[].class); + return handler; + } + + public static void main(String[] arguments) + { + new GetResourcePropertyExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java b/java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java new file mode 100644 index 0000000000..ecda6e8fb1 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/GetWSDLMetadataExample.java @@ -0,0 +1,156 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.w3c.dom.Element; + +/** + * This example shows how to get metadata from a WS-Resource. + * The service supports different kinds of metadata. + * User who wants to receive metadata of a WS-Resource must + * send a GetMetadataRequesta specifying the requested dialect. + * + * Supported metadata that could be requested are + * + *
    + *
  • + * WSDL : requested using "http://schemas.xmlsoap.org/wsdl/" as dialect.. + *
  • + *
  • + * RDM (Resource Metadata Descriptor) : requested using "http://docs.oasis-open.org/wsrf/rmd-1 "as dialect. + *
  • + *
+ * + * Note that this example focuses on WSDL Metadata only; another example is dedicated to RDM. + * + * @author Andrea Gazzarini + */ +public class GetWSDLMetadataExample extends AbstractQManExample +{ + + /** + * First, sends a request to WS-DM Adapter in order to get the list of managed resources. + * If the list is not empty, then takes the first member and sends it a GetMetadataRequest + * in order to get its WSDL. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Adapter service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference); + adapterClient.setTrace(true); + + // 3) Retrieves the all registered members (QMan WS-Resources) + WsResourceClient [] resources = adapterClient.getMembers(); + + // Sanity check : we cannot proceed if there are no WS-Resources. + if (resources.length == 0) + { + System.out.println("----------------------------WARNING---------------------------"); + System.out.println("Cannot proceed with the example... it seems"); + System.out.println("that there are no managed WS-Resources on QMan."); + System.out.println("Please check QMan in order to see that it is really"); + System.out.println("connected with a broker."); + System.out.println("-------------------------------------------------------------------"); + System.exit(0); + } + + // 4) Creates a proxy handler for service invocation. + ProxyHandler metadataProxyHandler = createProxyHandler(); + + // 5) ..and invokes the GetMetadata on the first member. + WsResourceClient firstMember = resources[0]; + firstMember.setTrace(true); + + // Dialect is WSDL for this example + String dialect = "http://schemas.xmlsoap.org/wsdl/"; + Object [] inputParameters = {dialect}; + + // WSDL is the first element of the returned array. We don't need to print out it here + // because at this point it should have been already printed out (line 96 : firstMember.setTrace(true)) + @SuppressWarnings("unused") + Element [] metadata = (Element[]) firstMember.invoke(metadataProxyHandler, inputParameters); + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("The example shows how to get metadata from a"); + System.out.println("WS-Resource."); + System.out.println("A QMan WS-Resource has different kinds of metadata."); + System.out.println("(see below)"); + System.out.println("User who wants to receive metadata of a WS-Resource"); + System.out.println("must send a GetMetadataRequesta specifying the"); + System.out.println("associated dialect."); + System.out.println("Supported metadata that could be requested are : "); + System.out.println(); + System.out.println("- WSDL : in this case dialect is \"http://schemas.xmlsoap.org/wsdl/\";"); + System.out.println("- RDM (Resource Metadata Descriptor) : in this case dialect is \"http://docs.oasis-open.org/wsrf/rmd-1 \"."); + System.out.println(); + System.out.println("Note that this examples focuses on WSDL Metadata only;"); + System.out.println("another one is dedicated to RDM."); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + } + + /** + * A proxy handler is a module needed in order to make a capability + * service invocation. + * It contains logic to serialize and deserialize request, response, input and + * output parameters during a web service invocation. + * + * @return a proxy handler. + */ + private ProxyHandler createProxyHandler() + { + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX)); + handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)}); + handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX)); + handler.setReturnType(Element[].class); + return handler; + } + + public static void main(String[] arguments) + { + new GetWSDLMetadataExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java b/java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java new file mode 100644 index 0000000000..01a27a16f9 --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/PausableSubscriptionExample.java @@ -0,0 +1,88 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import java.net.URI; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.notification.remote.NotificationProducerClient; +import org.apache.muse.ws.notification.remote.SubscriptionClient; + +/** + * This example is demonstrating a WS-Notification scenario + * when (for simplicity) QMan is at the same time consumer + * and producer. + * + * Specifically the example shows how a requestor can create, pause and resume + * a subscription. + * + * @author Andrea Gazzarini + * + */ +public class PausableSubscriptionExample extends AbstractQManExample +{ + @Override + void executeExample(String host, int port) throws Exception + { + // This is QMan... + URI producerURI = URI.create("http://"+host+":"+port+"/qman/services/adapter"); + + // ...and this is QMan too! Note that it has an hidden consumer capability that is used in + // order to run successfully this example... + URI consumerURI = URI.create("http://"+host+":"+port+"/qman/services/consumer"); + + EndpointReference producerEPR = new EndpointReference(producerURI); + EndpointReference consumerEPR = new EndpointReference(consumerURI); + + NotificationProducerClient producerClient = new NotificationProducerClient(producerEPR); + producerClient.setTrace(true); + + // 1) Creates a subscription and gets the corresponding reference. + SubscriptionClient subscriptionClient = producerClient.subscribe( + consumerEPR, // Consumer Endpoint reference + null, // Filter, if null that means "all messages" + null); // Termination Time : if null the subscription will never expire. + subscriptionClient.setTrace(true); + + + // 2) Pauses the subscription. + subscriptionClient.pauseSubscription(); + + // 3) Resumes the subscription. + subscriptionClient.resumeSubscription(); + } + + @Override + void printOutExampleDescription() + { + System.out.println("This example is demonstrating a WS-Notification scenario "); + System.out.println("when (for simplicity) QMan is at the same time consumer "); + System.out.println("and producer."); + System.out.println(); + System.out.println("Specifically the example shows how a requestor can create,"); + System.out.println("pause and resume a subscription."); + } + + public static void main(String[] args) + { + new PausableSubscriptionExample().execute(new String[]{"romagazzarini","8080"}); + } +} diff --git a/java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java b/java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java new file mode 100644 index 0000000000..8aed3101ff --- /dev/null +++ b/java/management/client/src/example/org/apache/qpid/management/example/SetResourcePropertyExample.java @@ -0,0 +1,306 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.example; + +import java.lang.reflect.Array; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.w3c.dom.Element; + +/** + * This example shows how to change the state of a WS-Resource. That means + * a SetResourcePropertyRequest is sent to that WS-Resource. + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then two GetMetadataRequests are sent to the + * first child (one for WSDL and one for RDM). + * The result metadata descriptors are the used to determine : + * + *
What are names of WS-Resouce properties + *
Their modifiability (read-only or read-write) + *
Their type + * + * So a SetResourcePropertyRequest can be sent in order to change the WS-Resource state. + * The example is looking for a property that has one of the following datatype : + * + *
    + *
  • String
  • + *
  • Long
  • + *
  • Integer
  • + *
  • Short
  • + *
  • Double
  • + *
  • Float
  • + *
+ * + * After the update / insert request has been sent, a GetResourcePropertiesRequest is made + * again in order to see if the state has changed correctly. + * + * @author Andrea Gazzarini + */ +public class SetResourcePropertyExample extends AbstractQManExample +{ + /** + * First of all a request is send to WS-DM in order to get all registered WS-Resources. + * If the returned list is not empty then two GetMetadataRequests are sent to the + * first child (one for WSDL and one for RDM). + * The result metadata descriptors are the used to determine : + * + *
What are names of WS-Resouce properties + *
Their modifiability (read-only or read-write) + *
Their type + * + * So a SetResourcePropertyRequest can be sent in order to change the WS-Resource state. + * The example is looking for a property that has one of the following datatype : + * + *
    + *
  • String
  • + *
  • Long
  • + *
  • Integer
  • + *
  • Short
  • + *
  • Double
  • + *
  • Float
  • + *
+ * + * After the update / insert request has been sent, a GetResourcePropertiesRequest is made + * again in order to see if the state has changed correctly. + * + * @param host the host where QMan is running. + * @param port the port where QMan is running. + * @throws Exception when the example fails (not at application level). + */ + void executeExample(String host, int port) throws Exception + { + // 1) Creates an endpoint reference of the adapter service... + EndpointReference adapterEndpointReference = getAdapterEndpointReference(host, port); + + // 2) Creates the Adapter service client... + ServiceGroupClient adapterClient = new ServiceGroupClient(adapterEndpointReference); + adapterClient.setTrace(false); + + // 3) Retrieves the all registered members (QMan WS-Resources) + WsResourceClient [] resources = adapterClient.getMembers(); + + // Sanity check : we cannot proceed if there are no WS-Resources. + if (resources.length == 0) + { + System.out.println("----------------------------WARNING---------------------------"); + System.out.println("Cannot proceed with the example... it seems"); + System.out.println("that there are no managed WS-Resources on QMan."); + System.out.println("Please check QMan in order to see that it is really"); + System.out.println("connected with a broker."); + System.out.println("-------------------------------------------------------------------"); + System.exit(0); + } + + // 4) Creates a proxy handler for service invocation. + ProxyHandler metadataProxyHandler = createProxyHandler(); + + // 5) ..and invokes the GetMetadata on the first member. + WsResourceClient wsResourceClient = resources[0]; + wsResourceClient.setTrace(true); + + // Resource Metadata Descriptor + String dialect = "http://docs.oasis-open.org/wsrf/rmd-1"; + Object [] inputParameters = {dialect}; + + // RDM is the first element of the returned array. + // The first element is a wsx:Metadata containing all resource properties. + Element [] metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters); + Element resourceMetadataDescriptor = metadata[0]; + + // 6) Now we need WSDL in order to catch datatypes + dialect = "http://schemas.xmlsoap.org/wsdl/"; + inputParameters = new Object[]{dialect}; + metadata = (Element[]) wsResourceClient.invoke(metadataProxyHandler, inputParameters); + Element wsdl = metadata[0]; + + //7) Defines sample values used for update property. + Map sampleValues = new HashMap(); + sampleValues.put("xsd:string","This is a string."); + sampleValues.put("xsd:integer",new Integer(12345)); + sampleValues.put("xsd:int",new Integer(54321)); + sampleValues.put("xsd:long",new Integer(12345)); + sampleValues.put("xsd:double",new Double(12345.6d)); + sampleValues.put("xsd:float",new Float(123.4f)); + sampleValues.put("xsd:short",new Short((short)12)); + + // 8) using XPath navigates xml in order to get the list of all properties. + Element [] properties = XmlUtils.findInSubTree( + resourceMetadataDescriptor, + new QName("http://docs.oasis-open.org/wsrf/rmd-1","Property","wsrmd")); + + Element [] wsdlElements = XmlUtils.findInSubTree( + wsdl, + new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + + // Did we find at least one writable property? + boolean atLeastOnePropertyHasBeenFound = false; + + for (Element property : properties) + { + // Sanity check : if the property is read-only then proceed with next + // property. + if (!"read-write".equals(property.getAttribute("modifiability"))) + { + continue; + } + + String attributeName = property.getAttribute("name"); // = qman: + + // For this example we are only interested on qman namespace related properties... + if (attributeName.startsWith("qman")) + { + String attributeNameWithoutPrefix = attributeName.replaceFirst("qman:", ""); // = + + for (Element wsdlElement : wsdlElements) + { + String name = wsdlElement.getAttribute("name"); + String type = wsdlElement.getAttribute("type"); + if ((name != null) && (attributeNameWithoutPrefix.equals(name)) && (type != null)) + { + Object newValue = sampleValues.get(type); + if (newValue != null) + { + atLeastOnePropertyHasBeenFound = true; + + inputParameters = new Object[] {newValue}; + + // 9) Makes a GetResourcePropertiesRequest in order to get the current value. + QName propertyQName = new QName( + "http://amqp.apache.org/qpid/management/qman", + name, + "qman"); + + // The returned value is really an array because property shoudl be a multi-value property. + // So in order to get its value we need to extract the first value. + Object currentValue = wsResourceClient.getPropertyAsObject(propertyQName,newValue.getClass()); + + // 10a) If the property is not set (value is null) then an "Insert" request must be sent. + if (currentValue == null || Array.getLength(currentValue) == 0) + { + wsResourceClient.insertResourceProperty(propertyQName,inputParameters); + } + // 10b) If the property is not null then an "Update" request must be sent. + else + { + wsResourceClient.updateResourceProperty(propertyQName,inputParameters); + } + + // 11) Let's query again the resource using GetResourceProperties in order to ensure the + // previous property has been properly updated. + currentValue = wsResourceClient.getPropertyAsObject(propertyQName,newValue.getClass()); + + String resultMessage = (newValue.equals(Array.get(currentValue, 0))) + ? "Resource has been correctly updated." + : "Something was wrong : resource seems not to be properly updated."; + + System.out.println("----------------------------------------------------------------------------------"); + System.out.println(resultMessage); + System.out.println("----------------------------------------------------------------------------------"); + + // Let's stop...one property is enough for this example :) + break; + } + } + } + if (!atLeastOnePropertyHasBeenFound) + { + System.out.println("----------------------------------------------------------------------------------"); + System.out.println("WARNING : This example wasn't able to run because no writable "); + System.out.println("property has been found on the target WS-Resource."); + System.out.println("----------------------------------------------------------------------------------"); + } + } + } + } + + /** + * Prints out a description of this example. + */ + void printOutExampleDescription() + { + System.out.println(" "+getClass().getSimpleName()+" "); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("This example shows how to change the state of a WS-Resource."); + System.out.println("That means a SetResourcePropertyRequest is sent to that"); + System.out.println("WS-Resource."); + System.out.println("First of all a request is send to WS-DM in order to get all"); + System.out.println("registered WS-Resources."); + System.out.println("If the returned list is not empty then two GetMetadataRequests"); + System.out.println("(one for WSDL and one for RDM) are sent to the first child."); + System.out.println("The result metadata descriptors are used for determine :"); + System.out.println(); + System.out.println("1) WS-Resource property names;"); + System.out.println("2) Modifiability (read-only, read-write"); + System.out.println("3) Datatype;"); + System.out.println("-------------------------------------------------------------------"); + System.out.println(); + System.out.println("So a SetResourcePropertyRequest can be sent in order"); + System.out.println("to change the WS-Resource state."); + System.out.println("The example is looking for a property that has one of the"); + System.out.println("following datatype :"); + System.out.println(); + System.out.println("1) String (xsd:string)"); + System.out.println("2) Long (xsd:long)"); + System.out.println("3) Integer (xsd:integer or xsd:int)"); + System.out.println("4) Double (xsd:double)"); + System.out.println("5) Float (xsd:float)"); + System.out.println("6) Short (xsd:short)"); + System.out.println(); + System.out.println("After the update / insert request has been sent, a "); + System.out.println("GetResourcePropertiesRequest is made again"); + System.out.println("in order to see if the state has changed correctly."); + System.out.println(); + } + + /** + * A proxy handler is a module needed in order to make a capability + * service invocation. + * It contains logic to serialize and deserialize request, response, input and + * output parameters during a web service invocation. + * + * @return a proxy handler. + */ + private ProxyHandler createProxyHandler() + { + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + handler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", PREFIX)); + handler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", PREFIX)}); + handler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", PREFIX)); + handler.setReturnType(Element[].class); + return handler; + } + + public static void main(String[] arguments) + { + new SetResourcePropertyExample().execute(arguments); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/muse.xml b/java/management/client/src/main/java/muse.xml new file mode 100644 index 0000000000..29a1c02e0c --- /dev/null +++ b/java/management/client/src/main/java/muse.xml @@ -0,0 +1,209 @@ + + + + + + java.lang.Object + org.apache.qpid.management.wsdm.muse.serializer.ObjectSerializer + + + java.util.Map + org.apache.qpid.management.wsdm.muse.serializer.MapSerializer + + + java.util.HashMap + org.apache.qpid.management.wsdm.muse.serializer.MapSerializer + + + java.util.UUID + org.apache.qpid.management.wsdm.muse.serializer.UUIDSerializer + + + org.apache.qpid.management.wsdm.capabilities.Result + org.apache.qpid.management.wsdm.muse.serializer.InvocationResultSerializer + + + java.util.Date + org.apache.qpid.management.wsdm.muse.serializer.DateSerializer + + + org.apache.muse.ws.resource.impl.WsResourceRouter + + log/muse.log + SEVERE + + + org.apache.muse.core.routing.RouterFilePersistence + router-entries + + + + consumer + + wsdl/WS-BaseNotification-1_3.wsdl + wsntw:NotificationConsumer + + org.apache.qpid.management.wsdm.common.QManResourceIdFactory + org.apache.muse.core.SimpleResource + + http://docs.oasis-open.org/wsn/bw-2/NotificationConsumer + org.apache.muse.ws.notification.impl.SimpleNotificationConsumer + + + http://amqp.apache.org/qpid/management/qman/consumer + org.apache.qpid.management.wsdm.capabilities.ConsumerCapability + + + + SubscriptionManager + + wsdl/WS-BaseNotification-1_3.wsdl + wsntw:SubscriptionManager + + org.apache.qpid.management.wsdm.common.QManResourceIdFactory + org.apache.muse.ws.resource.impl.SimpleWsResource + + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + org.apache.muse.ws.metadata.impl.SimpleMetadataExchange + + + http://docs.oasis-open.org/wsrf/rpw-2/Get + org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability + + + http://docs.oasis-open.org/wsn/bw-2/SubscriptionManager + org.apache.muse.ws.notification.impl.SimpleSubscriptionManager + + trace-notifications + true + + + + http://docs.oasis-open.org/wsrf/rlw-2/ImmediateResourceTermination + org.apache.muse.ws.resource.lifetime.impl.SimpleImmediateTermination + + + http://docs.oasis-open.org/wsrf/rlw-2/ScheduledResourceTermination + org.apache.muse.ws.resource.lifetime.impl.SimpleScheduledTermination + + + validate-wsrp-schema + false + + + + adapter + + wsdl/QManAdapter.wsdl + qman:QManAdapterPortType + + org.apache.qpid.management.wsdm.common.QManResourceIdFactory + org.apache.muse.ws.resource.impl.SimpleWsResource + + http://amqp.apache.org/qpid/management/qman + org.apache.qpid.management.wsdm.capabilities.QManAdapterCapability + + + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + org.apache.muse.ws.metadata.impl.SimpleMetadataExchange + + + http://docs.oasis-open.org/wsrf/rpw-2/Get + org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability + + + http://docs.oasis-open.org/wsrf/rpw-2/Query + org.apache.muse.ws.resource.properties.query.impl.SimpleQueryCapability + + + http://docs.oasis-open.org/wsrf/sgw-2/ServiceGroup + org.apache.muse.ws.resource.sg.impl.SimpleServiceGroup + + + http://docs.oasis-open.org/wsn/bw-2/NotificationProducer + org.apache.muse.ws.notification.impl.SimpleNotificationProducer + + + validate-wsrp-schema + false + + + + QManWsResource + + + wsdl/QManWsResource.wsdl + qman:QManWsResourcePortType + + org.apache.qpid.management.wsdm.common.ObjectNameIdFactory + org.apache.qpid.management.wsdm.muse.resources.QManWsResource + + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + org.apache.qpid.management.wsdm.capabilities.QManMetadataExchangeCapability + + + http://docs.oasis-open.org/wsrf/rpw-2/Get + org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability + + + http://docs.oasis-open.org/wsrf/rpw-2/Query + org.apache.muse.ws.resource.properties.query.impl.SimpleQueryCapability + + + http://docs.oasis-open.org/wsrf/rpw-2/Set + org.apache.muse.ws.resource.properties.set.impl.SimpleSetCapability + + + http://docs.oasis-open.org/wsrf/rpw-2/Put + org.apache.muse.ws.resource.properties.set.impl.SimpleSetCapability + + + + ServiceGroupEntry + + /wsdl/WS-ServiceGroupEntry-1_2.wsdl + wsrf-sgw:ServiceGroupEntryPortType + + org.apache.qpid.management.wsdm.common.QManResourceIdFactory + org.apache.muse.ws.resource.impl.SimpleWsResource + + http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata + org.apache.muse.ws.metadata.impl.SimpleMetadataExchange + + + http://docs.oasis-open.org/wsrf/rpw-2/Get + org.apache.muse.ws.resource.properties.get.impl.SimpleGetCapability + + + http://docs.oasis-open.org/wsrf/sgw-2/ServiceGroupEntry + org.apache.muse.ws.resource.sg.impl.SimpleEntry + + + validate-wsrp-schema + false + + + diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Messages.java b/java/management/client/src/main/java/org/apache/qpid/management/Messages.java new file mode 100644 index 0000000000..4f84128fb3 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/Messages.java @@ -0,0 +1,175 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management; + +/** + * Enumerative interfaces containing all QMan messages. + * + * @author Andrea Gazzarini + */ +public interface Messages +{ + // MESSAGES + String EVENT_SEVERITY_ATTRIBUTE_DESCRIPTION = "Severity level for this event."; + String EVENT_TIMESTAMP_ATTRIBUTE_DESCRIPTION = "Current timestamp of this event."; + String ACTION_NOT_SUPPORTED="Action %s not supported by resource %s."; + + // INFO + String QMAN_000001_STARTING_QMAN = " : Starting Q-Man..."; + String QMAN_000002_READING_CONFIGURATION = " : Reading Q-Man configuration..."; + String QMAN_000003_CREATING_MANAGEMENT_CLIENTS = " : Creating management client(s)..."; + String QMAN_000004_MANAGEMENT_CLIENT_CONNECTED = " : Management client for broker %s successfully connected."; + String QMAN_000005_TYPE_MAPPING_CONFIGURED = " : Type mapping : code = %s associated to %s (validator class is %s)"; + String QMAN_000006_ACCESS_MODE_MAPPING_CONFIGURED = " : Access Mode mapping : code = %s associated to %s"; + String QMAN_000007_MANAGEMENT_HANDLER_MAPPING_CONFIGURED = " : Management Queue Message Handler Mapping : opcode = %s associated with %s"; + String QMAN_000008_METHOD_REPLY_HANDLER_MAPPING_CONFIGURED = " : Method-Reply Queue Message Handler Mapping : opcode = %s associated with %s"; + String QMAN_000009_BROKER_DATA_CONFIGURED = " : Broker configuration %s: %s"; + String QMAN_000010_INCOMING_SCHEMA = " : Incoming schema for %s::%s.%s"; + String QMAN_000011_SHUTDOWN_INITIATED = " : The shutdown sequence has been initiated for management client connected with broker %s"; + String QMAN_000012_MANAGEMENT_CLIENT_SHUT_DOWN = " : Management client connected with broker %s shut down successfully."; + String QMAN_000013_METHOD_REPLY_CONSUMER_INSTALLED = " : Method-reply queue consumer has been successfully installed and bound on broker %s."; + String QMAN_000014_MANAGEMENT_CONSUMER_INSTALLED =" : Management queue consumer has been successfully installed and bound on broker %s."; + String QMAN_000015_MANAGEMENT_QUEUE_DECLARED = " : Management queue with name %s has been successfully declared and bound on broker %s."; + String QMAN_000016_METHOD_REPLY_QUEUE_DECLARED = " : Method-reply queue with name %s has been successfully declared and bound on broker %s."; + String QMAN_000017_CONSUMER_HAS_BEEN_REMOVED = " : Consumer %s has been removed from broker %s."; + String QMAN_000018_QUEUE_UNDECLARED = " : Queue %s has been removed from broker %s."; + String QMAN_000019_QMAN_STARTED = " : Q-Man open for e-business."; + String QMAN_000020_SHUTTING_DOWN_QMAN = " : Shutting down Q-Man..."; + String QMAN_000021_SHUT_DOWN = " : Q-Man shut down."; + String QMAN_000022_NO_BROKER_CONFIGURED = " : Q-Man has no configured broker : in order to connect with a running one use Q-Man Administration interface."; + String QMAN_000023_QMAN_REGISTERED_AS_MBEAN = " : Q-Man service is now available on MBeanServer."; + + String QMAN_000026_WSDM_ADAPTER_STARTS = " : Initializing WS-DM Adapter Environment..."; + String QMAN_000027_WSDM_ADAPTER_STARTED = " : WS-DM Adapter ready for incoming requests."; + String QMAN_000028_TEST_MODULE_NOT_FOUND = " : Qpid emulator not found. Test notifications are disabled."; + String QMAN_000029_DEFAULT_URI = " : Default URI will be set to %s"; + String QMAN_000030_RESOURCE_HAS_BEEN_CREATED = " : New resource instance has been created and registered. Resource id is %s"; + String QMAN_000031_RESOURCE_HAS_BEEN_REMOVED = " : WS-Resource %s has been removed"; + String QMAN_000032_EVENTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED = " : Events lifecycle topic has been created with name %s"; + String QMAN_000033_OBJECTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED = " : Objects lifecycle topic has been created with name %s"; + String QMAN_000034_UNCLASSIFIED_LIFECYCLE_TOPIC_HAS_BEEN_CREATED = " : Unclassified object types lifecycle topic has been created with name %s"; + String QMAN_000035_WORK_MANAGER_POOL_SIZE = " : Work Manager thread pool size : %s"; + String QMAN_000036_WORK_MANAGER_MAX_POOL_SIZE = " : Work Manager thread pool max size : %s"; + String QMAN_000037_WORK_MANAGER_KEEP_ALIVE_TIME = " : Work Manager keep alive time : %s"; + + // DEBUG + String QMAN_200001_INCOMING_MESSAGE_HAS_BEEN_RECEIVED = " : New incoming message has been received. Message content is %s"; + String QMAN_200002_OPCODE_HANDLER_ASSOCIATION = " : \"%s\" opcode is associated to handler %s"; + String QMAN_200003_MESSAGE_FORWARDING = " : Incoming message with \"%s\" as opcode will be forwarded to %s for processing."; + String QMAN_200004_MANAGEMENT_QUEUE_NAME = " : Management queue name : %s"; + String QMAN_200005_METHOD_REPLY_QUEUE_NAME = " : Method-reply queue name : %s"; + String QMAN_200006_QPID_CONNECTION_RELEASED = " : Connection %s returned to the pool."; + String QMAN_200007_TEST_CONNECTION_ON_RESERVE = " : Test connection on reserve. Is valid? %s"; + String QMAN_200008_CONNECTION_DESTROYED = " : Connection has been destroyed."; + String QMAN_200009_CONNECTION_DESTROY_FAILURE = " : Unable to destroy a connection object."; + String QMAN_200010_EVENT_MBEAN_REGISTERED = " : Event instance %s::%s::%s successfully registered with MBean Server with name %s"; + String QMAN_200011_OBJECT_MBEAN_REGISTERED = " : Object instance %s::%s::%s:%s successfully registered with MBean Server with name %s"; + String QMAN_200012_OBJECT_MBEAN_UNREGISTERED = " : Object instance %s::%s::%s:%s successfully unregistered from MBean Server. Name was %s"; + String QMAN_200013_ARGUMENT_VALUE_ENCODED = " : Encoded value %S for argument %s. Type is %s"; + String QMAN_200014_INCOMING_INSTRUMENTATION_DATA = " : Incoming instrumentation data for %s::%s.%s.%s"; + String QMAN_200015_INCOMING_CONFIGURATION_DATA = " : Incoming configuration data for %s::%s.%s.%s"; + String QMAN_200016_PROPERTY_DEFINITION_HAS_BEEN_BUILT = " : Property definition for %s::%s.%s has been built."; + String QMAN_200017_STATISTIC_DEFINITION_HAS_BEEN_BUILT = " : Statistic definition for %s::%s.%s has been built."; + String QMAN_200018_OPTIONAL_PROPERTIES_INFO = " : Class %s::%s.%s has %s optional properties."; + String QMAN_200019_EVENT_ARGUMENT_DEFINITION_HAS_BEEN_BUILT = " : Event argument definition for %s::%s.%s has been built."; + String QMAN_200020_ENTITY_DEFINITION_HAS_BEEN_BUILT = " : Entity definition has been built (without schema) for %s::%s.%s"; + String QMAN_200021_INCOMING_EVENT_DATA = " : Incoming data for event %s::%s.%s"; + String QMAN_200022_VALIDATOR_INSTALLED = " : Validator %s for type %s successfully installed."; + String QMAN_200023_VALIDATOR_NOT_FOUND = " : No validator was found for type %s. The default (empty) validator will be used."; + String QMAN_200024_MANAGEMENT_MESSAGE_HAS_BEEN_SENT = " : Message has been sent to management exchange. Message content : %s"; + String QMAN_200025_SUBSCRIPTION_DECLARED = " : New subscription between queue %s and destination %s has been declared."; + String QMAN_200026_SUBSCRIPTION_REMOVED = " : Subscription named %s has been removed from remote broker."; + String QMAN_200027_QUEUE_DECLARED = " : New queue with name %s has been declared."; + String QMAN_200028_QUEUE_REMOVED= " : New queue with name %s has been undeclared."; + String QMAN_200029_BINDING_DECLARED = " : New binding with %s as routing key has been declared between queue %s and exchange %s."; + String QMAN_200030_BINDING_REMOVED = " : Binding with %s as routing key has been removed between queue %s and exchange %s."; + String QMAN_200031_COMPOUND_MESSAGE_CONTAINS = " : Incoming compound message contains %s message(s)."; + String QMAN_200032_COMMAND_MESSAGE_ROUTING_KEY = " : Command message routing key : %s"; + String QMAN_200033_CAPABILITY_CLASS_HAS_BEEN_ADDED = " : Capability has been added to this resource. Class is %s while URI is %s."; + String QMAN_200034_RMD_NAME = " : Resource Metadata Descriptor name is %s."; + String QMAN_200035_RMD_PATH = " : Resource Metadata Descriptor path is %s."; + String QMAN_200036_ADDITIONAL_RMD_PROPERTY = " : Additional RMD property : %s"; + String QMAN_200037_RMD = " : Resource Metadata Descriptor : %s"; + String QMAN_200038_WSRP = " : WS Resource Properties fragment : %s"; + String QMAN_200039_DEBUG_JMX_NOTIFICATION = " : %s"; + String QMAN_200040_WS_ARTIFACTS_CACHED = " : WS Artifacts has been stored on cache with the following id : %s"; + String QMAN_200041_INCOMING_OBJECT_NAME_AND_DERIVED_KEY = " : Incoming object name : %s, derived search key : %s"; + String QMAN_200042_REMOVING_RESOURCE = " : WS-Resource %s is going to be removed"; + String QMAN_200043_GENERATED_ACCESSOR_METHOD = " : Generated accessor method for %s : %s"; + String QMAN_200044_GENERATED_METHOD = " : Generated method for %s : %s"; + + // WARNING + String QMAN_300001_MESSAGE_DISCARDED = " : No handler has been configured for processing messages with \"%s\" as opcode. Message will be discarded."; + String QMAN_300002_UNKNOWN_SEQUENCE_NUMBER = " : Unable to deal with incoming message because it contains a unknown sequence number (%s)."; + String QMAN_300003_BROKER_ALREADY_CONNECTED = " : Unable to enlist given broker connection data : QMan is already connected with broker %s"; + String QMAN_300004_INVALID_CONFIGURATION_FILE = " : The given configuration file (%s) is not valid (it doesn't exist or cannot be read)"; + String QMAN_300005_QEMU_INITIALIZATION_FAILURE = " : Unable to initialize QEmu module and therefore emulation won't be enabled..."; + + String QMAN_300006_OS_MBEAN_FAILURE = " : Unable to retrieve Operating System properties. No values will be displayed for underlying Operation System."; + String QMAN_300007_RUNTIME_MBEAN_FAILURE = " : Unable to retrieve Runtime Environment properties. No values will be displayed."; + + // ERROR + String QMAN_100001_BAD_MAGIC_NUMBER_FAILURE = " : Message processing failure : incoming message contains a bad magic number (%s) and therefore will be discaded."; + String QMAN_100002_MESSAGE_READ_FAILURE = " : Message I/O failure : unable to read byte message content and therefore it will be discarded."; + String QMAN_100003_MESSAGE_PROCESS_FAILURE = " : Message processing failure : unknown exception; see logs for more details."; + String QMAN_100004_HANDLER_INITIALIZATION_FAILURE = " : Message handler configured for opcode %s thrown an exception in initialization and therefore will be discarded."; + String QMAN_100005_CLASS_SCHEMA_PROCESSING_FAILURE = " : Q-Man was unable to process the schema response message."; + String QMAN_100006_EVENT_SCHEMA_PROCESSING_FAILURE = " : Q-Man was unable to process the schema response message."; + String QMAN_100007_UNABLE_TO_CONNECT_WITH_BROKER = " : Unable to connect with broker located on %s. This broker will be ignored."; + + + String QMAN_100010_METHOD_INVOCATION_RESULT_FAILURE = " : an exception occurred while storing the result of a method invocation. Sequence number was %s"; + String QMAN_100011_UNKNOWN_CLASS_KIND = " : Unknwon class kind : %s)."; + String QMAN_100012_SCHEMA_MESSAGE_PROCESSING_FAILURE = " : Q-Man was unable to process the schema response message."; + String QMAN_100013_MBEAN_REGISTRATION_FAILURE = " : Unable to unregister object instance %s."; + String QMAN_100014_ATTRIBUTE_DECODING_FAILURE = " : Unable to decode value for attribute %s"; + String QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST = " : Unable to send a schema request schema for %s.%s"; + String QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE = " : Unable to decode value for %s::%s::%s"; + String QMAN_100017_UNABLE_TO_CONNECT = ": Cannot connect to broker %s on %s"; + String QMAN_100018_UNABLE_TO_STARTUP_CORRECTLY = " : Q-Man was unable to startup correctly : see logs for further details."; + String QMAN_100019_REQ_OR_RES_MALFORMED = " : Unexpected exception occurred on WSDM adapter layer : probably request or response was malformed."; + String QMAN_100020_ACTION_NOT_SUPPORTED = " : "+ACTION_NOT_SUPPORTED; + String QMAN_100021_RMD_BUID_FAILURE = " : Unable to build RDM for resource %s."; + + String QMAN_100023_BUILD_WS_ARTIFACTS_FAILURE = " : Unable to build WS artifacts."; + String QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE = " : Unable to instantiate generated capability class for %s."; + String QMAN_100025_WSRF_FAILURE = " : Resource manager raised an exception while creating capability for %s."; + String QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE = " : Exception occurred while replacing the placeholder soap address with resource actual location."; + String QMAN_100027_RESOURCE_SHUTDOWN_FAILURE = " : Shutdown failure while destroying resource %s."; + String QMAN_100029_MALFORMED_RESOURCE_URI_FAILURE = " : Unable to define URI for QMan resources using \"%s\". It violates RFC 2396"; + String QMAN_100030_JMX_CORE_STARTUP_FAILURE = " : QMan JMX core Unexpected failure while starting up."; + String QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED = " : Bad request has been received on this WS-Resource : Initialization is not possible because the resource has already been initialized."; + String QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED = " : Bad request has been received on this WS-Resource : Shutdown is not possible because the resource hasn't yet been initialized."; + String QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN = " : Bad request has been received on this WS-Resource : Shutdown is not possible because the resource has already been shutdown."; + String QMAN_100034_WSDL_SCHEMA_SECTION_NOT_FOUND = " : Unable to get via XPath the schema section in WSDL."; + String QMAN_100035_RESOURCE_CAPABILITY_INVOCATION_FAILURE = " : Resource thrown a failure while invoking a capability operation."; + String QMAN_100036_TOPIC_DECLARATION_FAILURE = " : WS-DM Adapter was unable to declare events and / or objects lifecycle topic(s). As conseguence of that, QMan won't be able to correctly emit lifecycle notifications."; + + // NEW + String QMAN_100035_GET_ATTRIBUTE_FAILURE = " : Get Attribute invocation failure for attribute %s, resource %s."; + String QMAN_100036_SET_ATTRIBUTE_FAILURE = " : Set Attribute invocation failure for attribute %s, resource %s."; + String QMAN_100037_INVOKE_OPERATION_FAILURE = " : Operation Invocation failure for operation."; + String QMAN_100038_UNABLE_TO_SEND_WS_NOTIFICATION = " : Unable to send notification."; + String QMAN_100039_UNABLE_TO_CONFIGURE_PROPERLY_WORKER_MANAGER = " : Unable to properly configure WorkManager. A malformed property (NaN) was given as input parameter."; + String QMAN_100040_UNABLE_TO_LOCATE_WSRP_PROPERTIES = " : Unable to evaluate the WSRP XPath expression on resource WSDL."; + +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Names.java b/java/management/client/src/main/java/org/apache/qpid/management/Names.java new file mode 100644 index 0000000000..b60867d9ff --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/Names.java @@ -0,0 +1,216 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management; + +import javax.management.ObjectName; +import javax.xml.namespace.QName; + +/** + * Enumeration of literal strings to avoid code duplication. + */ +public abstract class Names +{ + public static final String MANAGEMENT_EXCHANGE = "qpid.management"; + public static final String MANAGEMENT_ROUTING_KEY = "console.#"; + + public static final String MANAGEMENT_QUEUE_PREFIX = "management."; + public static final String METHOD_REPLY_QUEUE_PREFIX = "reply."; + + public static final String AMQ_DIRECT_QUEUE = "amq.direct"; + public static final String AGENT_ROUTING_KEY_PREFIX = "agent."; + public static final String AGENT_ROUTING_KEY = AGENT_ROUTING_KEY_PREFIX+"1.0"; + + public static final String APPLICATION_NAME ="Q-Man"; + + // Attributes + public static final String PACKAGE = "package"; + public static final String CLASS = "class"; + public static final String EVENT = "event"; + public static final String OBJECT_ID="objectId"; + public static final String BROKER_ID = "brokerId"; + public static final String DOMAIN_NAME = "Q-MAN"; + + public static final String ARG_COUNT_PARAM_NAME = "argCount"; + public static final String DEFAULT_PARAM_NAME ="default"; + + public static final String NUMBER_VALIDATOR = "org.apache.qpid.management.domain.model.QpidProperty$NumberValidator"; + public static final String STRING_VALIDATOR = "org.apache.qpid.management.domain.model.QpidProperty$StringValidator"; + + public static final String QMAN_CONFIG_OPTION_NAME = "qman-config"; + + public static final String ADD_BROKER_OPERATION_NAME = "addBroker"; + + public static final String NOT_AVAILABLE = "N.A."; + + public static final ObjectName QPID_EMULATOR_OBJECT_NAME; + static + { + try + { + QPID_EMULATOR_OBJECT_NAME = new ObjectName( + new StringBuilder() + .append(DOMAIN_NAME) + .append(':') + .append("Name=Qpid,Type=Emulator") + .toString()); + } catch(Exception exception) + { + throw new ExceptionInInitializerError(exception); + } + } + + public static final ObjectName QMAN_OBJECT_NAME; + static + { + try + { + QMAN_OBJECT_NAME = new ObjectName( + new StringBuilder() + .append(DOMAIN_NAME) + .append(':') + .append("Name=QMan,Type=Service") + .toString()); + } catch(Exception exception) + { + throw new ExceptionInInitializerError(exception); + } + } + + // WSDM Stuff + public static final String NAMESPACE_URI = "http://amqp.apache.org/qpid/management/qman"; + public final static String PREFIX = "qman"; + + public static final String ADDRESSING_URI = "http://amqp.apache.org/qpid/management/qman/addressing"; + public static final String ADDRESSING_PREFIX = "qman-wsa"; + + public static final QName RESOURCE_ID_QNAME = new QName( + ADDRESSING_URI, + "ResourceId", + ADDRESSING_PREFIX); + + public static final QName RES_ID_QNAME = new QName( + NAMESPACE_URI, + "ResourceId", + PREFIX); + + public static final QName RESOURCE_QNAME = new QName( + NAMESPACE_URI, + "Resource", + PREFIX); + + public static final QName LIFECYCLE_EVENT_QNAME = new QName( + NAMESPACE_URI, + "LifeCycleEvent", + PREFIX); + + public static final QName PACKAGE_NAME_QNAME = new QName( + NAMESPACE_URI, + "PackageName", + PREFIX); + + public static final QName ENTITY_NAME_QNAME = new QName( + NAMESPACE_URI, + "Name", + PREFIX); + + public static final String TIMEMILLIS_ATTRIBUTE_NAME="TimeMillis"; + + public final static String QMAN_RESOURCE_NAME = "QManWsResource"; + + public final static String VALIDATE_WSRP_PARAM = "validate-wsrp-schema"; + + public static final String WEB_APP_CLASSES_FOLDER = "/WEB-INF/classes"; + + + public final static QName QMAN_RESOURCE_PORT_TYPE_NAME = new QName( + Names.NAMESPACE_URI, + "QManWsResourcePortType", + Names.PREFIX); + + public final static QName QMAN_STATUS_TEXT_NAME = new QName( + Names.NAMESPACE_URI, + "Message", + Names.PREFIX); + + public final static QName QMAN_STATUS_CODE_NAME = new QName( + Names.NAMESPACE_URI, + "ReturnCode", + Names.PREFIX); + + public final static QName QMAN_STATUS_ATTRIBUTE_NAME= new QName( + Names.NAMESPACE_URI, + "AttributeName", + Names.PREFIX); + + public final static QName OBJECTS_LIFECYLE_TOPIC_NAME= new QName( + Names.NAMESPACE_URI, + "ObjectsLifeCycleTopic", + Names.PREFIX); + + public final static QName EVENTS_LIFECYLE_TOPIC_NAME= new QName( + Names.NAMESPACE_URI, + "EventsLifeCycleTopic", + Names.PREFIX); + + public final static QName HOST_QNAME = new QName( + Names.NAMESPACE_URI, + "host", + Names.PREFIX); + + public final static QName PORT_QNAME = new QName( + Names.NAMESPACE_URI, + "port", + Names.PREFIX); + + public final static QName USERNAME_QNAME= new QName( + Names.NAMESPACE_URI, + "username", + Names.PREFIX); + + public final static QName VIRTUAL_HOST_QNAME= new QName( + Names.NAMESPACE_URI, + "virtualHost", + Names.PREFIX); + + public final static QName UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME= new QName( + Names.NAMESPACE_URI, + "UnclassifiedLifeCycleTopic", + Names.PREFIX); + + + public final static String NAME_ATTRIBUTE = "name"; + public final static String MODIFIABILITY = "modifiability"; + public final static String READ_WRITE = "read-write"; + public final static String READ_ONLY = "read-only"; + public final static String MUTABILITY = "mutability"; + public final static String MUTABLE = "mutable"; + + public final static String ENTRY = "entry"; + public final static String KEY = "key"; + public final static String VALUE = "value"; + public final static String TYPE = "type"; + public final static String XSI_TYPE = "xsi:"+TYPE; + + public final static String ADAPTER_HOST_PROPERTY_NAME = "qman.host"; + public final static String ADAPTER_PORT_PROPERTY_NAME = "qman.port"; + + +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java b/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java new file mode 100644 index 0000000000..c1b1ceb5b4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java @@ -0,0 +1,52 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management; + +/** + * Protocol defined constants. + * + * @author Andrea Gazzarini + */ +public interface Protocol +{ + String MAGIC_NUMBER = "AM2"; + + char SCHEMA_REQUEST_OPCODE = 'S'; + char SCHEMA_RESPONSE_OPCODE = Character.toLowerCase(SCHEMA_REQUEST_OPCODE); + + char OPERATION_INVOCATION_REQUEST_OPCODE = 'M'; + char OPERATION_INVOCATION_RESPONSE_OPCODE = Character.toLowerCase(OPERATION_INVOCATION_REQUEST_OPCODE); + + char INSTRUMENTATION_CONTENT_RESPONSE_OPCODE = 'i'; + char CONFIGURATION_CONTENT_RESPONSE_OPCDE = 'c'; + char EVENT_CONTENT_RESPONSE_OPCDE = 'e'; + char INSTR_AND_CONFIG_CONTENT_RESPONSE_OPCODE = 'g'; + + char HEARTBEAT_INDICATION_RESPONSE_OPCODE = 'h'; + + int CLASS = 1; + int EVENT = 2; + + String DEFAULT_QMAN_HOSTNAME = "localhost"; + int DEFAULT_QMAN_PORT_NUMBER = 8080; + + String DEFAULT_ENDPOINT_URI = "http://localhost:8080/qman/services/adapter"; +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java new file mode 100644 index 0000000000..f23bf9d25e --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerAlreadyConnectedException.java @@ -0,0 +1,53 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.configuration; + +/** + * Thrown when an attempt is made in order to connect QMan with an already connected broker. + * + * @author Andrea Gazzarini + */ +public class BrokerAlreadyConnectedException extends Exception { + + private static final long serialVersionUID = -5082431738056504669L; + + private BrokerConnectionData _connectionData; + + /** + * Builds a new exception with the given data. + * + * @param connectionData the broker connection data. + */ + public BrokerAlreadyConnectedException(BrokerConnectionData connectionData) { + this._connectionData = connectionData; + } + + /** + * Returns the connection data of the connected broker. + * + * @return the connection data of the connected broker. + */ + public BrokerConnectionData getBrokerConnectionData() + { + return _connectionData; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java new file mode 100644 index 0000000000..a64659b17c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java @@ -0,0 +1,280 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +/** + * Value object which is holding connection data for a specific broker. + * + * @author Andrea Gazzarini + */ +public class BrokerConnectionData +{ + private String _host; + private int _port; + private String _virtualHost; + private String _username; + private String _password; + private int _maxPoolCapacity; + private int _initialPoolCapacity; + private long _maxWaitTimeout; + + /** + * Builds a connection data with the given parameters. + * + * @param host the hostname where the broker is running. + * @param port the port where the broker is running. + * @param username the username for connecting with the broker. + * @param password the password for connecting with the broker. + * @param virtualHost the virtual host. + * @param initialPoolCapacity the number of connections that must be immediately opened. + * @param maxPoolCapacity the maximum number of opened connection. + * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection. + */ + public BrokerConnectionData( + String host, + int port, + String virtualHost, + String username, + String password, + int initialPoolCapacity, + int maxPoolCapacity, + long waitTimeout) { + + this._host = host; + this._port = port; + this._virtualHost = virtualHost; + this._username = username; + this._password = password; + _maxPoolCapacity = maxPoolCapacity; + _initialPoolCapacity = initialPoolCapacity; + _maxWaitTimeout = waitTimeout; + } + + /** + * Builds a new empty broker connection data object. + */ + BrokerConnectionData() + { + } + + /** + * Sets the value of host property for this connection data. + * + * @param host the host name. + */ + void setHost (String host) + { + this._host = host; + } + + /** + * Sets the value of port property for this connection data. + * + * @param port the port. + */ + void setPort (String port) + { + this._port = Integer.parseInt(port); + } + + /** + * Sets the value of virtual host property for this connection data. + * + * @param virtualHost the virtual host. + */ + void setVirtualHost (String virtualHost) + { + this._virtualHost = virtualHost; + } + + /** + * Sets the value of username property for this connection data. + * + * @param username the username. + */ + void setUsername(String username) + { + this._username = username; + } + + /** + * Sets the value of password property for this connection data. + * + * @param password the password. + */ + void setPassword(String password) + { + this._password = password; + } + + /** + * Returns the value of the host property. + * + * @return the value of the host property. + */ + public String getHost () + { + return _host; + } + + /** + * Returns the value of the port property. + * + * @return the value of the port property. + */ + public int getPort () + { + return _port; + } + + /** + * Returns the value of the virtual host property. + * + * @return the value of the virtual host property. + */ + public String getVirtualHost () + { + return _virtualHost; + } + + /** + * Returns the value of the username property. + * + * @return the value of the username property. + */ + public String getUsername () + { + return _username; + } + + /** + * Returns the value of the password property. + * + * @return the value of the password property. + */ + public String getPassword () + { + return _password; + } + + // sofia:5663@pippo/sung1 + @Override + public String toString () + { + return new StringBuilder() + .append(_host) + .append(':') + .append(_port) + .append('@') + .append(_virtualHost) + .toString(); + } + + /** + * Sets the max number of allowed connections that can be opened. + * + * @param value the max number of allowed connections that can be opened. + * @throws NumberFormatException if the given value is not a valid integer. + */ + public void setMaxPoolCapacity (String value) + { + _maxPoolCapacity = Integer.parseInt(value); + } + + /** + * Sets the max wait timeout for retrieving an available connections from the pool. + * + * @param value the max wait timeout for retrieving an available connections from the pool.. + * @throws NumberFormatException if the given value is not a valid long. + */ + public void setMaxWaitTimeout (String value) + { + this._maxWaitTimeout = Long.parseLong(value); + } + + /** + * Returns the max number of allowed connections that can be opened. + * + * @return the max number of allowed connections that can be opened. + */ + public int getMaxPoolCapacity () + { + return _maxPoolCapacity; + } + + /** + * Returns the max wait timeout for retrieving an available connections from the pool. + * + * @return the max wait timeout for retrieving an available connections from the pool. + */ + public long getMaxWaitTimeout () + { + return _maxWaitTimeout; + } + + /** + * Sets the initial connection pool capacity. + * + * @param capacity the initial connection pool capacity. + */ + public void setInitialPoolCapacity (String capacity) + { + _initialPoolCapacity = Integer.parseInt(capacity); + } + + /** + * Returns the initial connection pool capacity. + * + * @return the initial connection pool capacity. + */ + public int getInitialPoolCapacity () + { + return _initialPoolCapacity; + } + + @Override + public boolean equals(Object object) + { + if(object instanceof BrokerConnectionData) + { + try + { + BrokerConnectionData connectionData = (BrokerConnectionData) object; + return (_host.equals(connectionData._host) ) + && (_port == connectionData._port) + && (_virtualHost.equals(connectionData._virtualHost)); + } + catch (Exception exception) + { + return false; + } + } + else + { + return false; + } + } + + @Override + public int hashCode() { + return _host.hashCode()+_port+_virtualHost.hashCode(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java new file mode 100644 index 0000000000..39981dc7cb --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java @@ -0,0 +1,136 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.UUID; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.transport.util.Logger; + +/** + * Parser used for building broker connection data settings. + * The corresponding section on the configuration file is : + * + + 192.168.148.131 + 5672 + test + guest + guest + 4 + 4 + -1 + + * + * @author Andrea Gazzarini + */ +class BrokerConnectionDataParser implements IParser +{ + private final static Logger LOGGER = Logger.get(Configuration.class); + private BrokerConnectionData _connectionData = new BrokerConnectionData(); + private String _currentValue; + + /** + * Callback : the given value is the text content of the current node. + */ + public void setCurrrentAttributeValue (String value) + { + this._currentValue = value; + } + + /** + * Callback: each time the end of an element is reached this method is called. + * It's here that the built mapping is injected into the configuration. + * + 192.168.61.130 + 5673 + test + andrea + andrea + + */ + public void setCurrentAttributeName (String name) + { + switch (Tag.get(name)) + { + case HOST: + { + _connectionData.setHost(_currentValue); + break; + } + case PORT : + { + _connectionData.setPort(_currentValue); + break; + } + case VIRTUAL_HOST: + { + _connectionData.setVirtualHost(_currentValue); + break; + } + case USER : + { + _connectionData.setUsername(_currentValue); + break; + } + case MAX_POOL_CAPACITY: + { + _connectionData.setMaxPoolCapacity (_currentValue); + break; + } + case INITIAL_POOL_CAPACITY: + { + _connectionData.setInitialPoolCapacity(_currentValue); + break; + } + case MAX_WAIT_TIMEOUT: + { + _connectionData.setMaxWaitTimeout(_currentValue); + break; + } + case PASSWORD: + { + _connectionData.setPassword(_currentValue); + break; + } + case BROKER: + { + try + { + Configuration.getInstance().addBrokerConnectionData(getUUId(),_connectionData); + } catch(Exception exception) + { + LOGGER.error(exception, Messages.QMAN_100007_UNABLE_TO_CONNECT_WITH_BROKER, _connectionData); + } + _connectionData = new BrokerConnectionData(); + break; + } + } + } + + /** + * Gets an uuid in order to associate current connection data with a broker. + * @return + */ + UUID getUUId(){ + return UUID.randomUUID(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java new file mode 100644 index 0000000000..9294cf740e --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionException.java @@ -0,0 +1,42 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.configuration; + +/** + * Thrown when a connection to a broker cannot be estabilished. + * + * @author Andrea Gazzarini + */ +public class BrokerConnectionException extends Exception +{ + private static final long serialVersionUID = 8170112238862494025L; + + /** + * Builds a new exception with the given cause. + * + * @param cause the exception cause. + */ + BrokerConnectionException(Throwable cause) + { + super(cause); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java new file mode 100644 index 0000000000..ab90ec294b --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java @@ -0,0 +1,485 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.Map.Entry; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.handler.base.IMessageHandler; +import org.apache.qpid.management.domain.model.AccessMode; +import org.apache.qpid.management.domain.model.type.AbsTime; +import org.apache.qpid.management.domain.model.type.DeltaTime; +import org.apache.qpid.management.domain.model.type.ObjectReference; +import org.apache.qpid.management.domain.model.type.Str16; +import org.apache.qpid.management.domain.model.type.Str8; +import org.apache.qpid.management.domain.model.type.Type; +import org.apache.qpid.management.domain.model.type.Uint16; +import org.apache.qpid.management.domain.model.type.Uint32; +import org.apache.qpid.management.domain.model.type.Uint64; +import org.apache.qpid.management.domain.model.type.Uint8; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.ReplyTo; +import org.apache.qpid.transport.util.Logger; + +/** + * Qpid Management bridge configuration. + * Basically iy is a singleton that is holding all the configurtion data loaded at startup. + */ +public final class Configuration +{ + private final static Logger LOGGER = Logger.get(Configuration.class); + private static Configuration INSTANCE = new Configuration(); + + // Work Manager default settings + private int _poolSize = 5; + private int _maxPoolSize = 15; + private long _keepAliveTime = 5000; + + Map _typeMappings = new HashMap(); + Map _accessModes = new HashMap(); + Map _validators = new HashMap(); + + Map _brokerConnectionInfos = new HashMap(); + + Map _managementQueueHandlers = new HashMap(); + Map _methodReplyQueueHandlers = new HashMap(); + + private String _managementQueueName; + private String _methodReplyQueueName; + + private Header _headerForCommandMessages; + private DeliveryProperties _deliveryProperties = new DeliveryProperties(); + private MessageProperties _messageProperties = new MessageProperties(); + + // Private constructor. + private Configuration() + { + defineQueueNames(); + + createHeaderForCommandMessages(); + + addAccessModeMappings(); + + addTypeMappings(); + } + + + /** + * Returns the singleton instance. + * + * @return the singleton instance. + */ + public static Configuration getInstance () + { + return INSTANCE; + } + + /** + * Returns true if this configuration has at least + * one broker configured. + * + * @return true if this configuration has at least one + * broker configured. + */ + public boolean hasOneOrMoreBrokersDefined() + { + return !_brokerConnectionInfos.isEmpty(); + } + + /** + * Returns the type associated to the given code. + * + * @param code the code used as search criteria. + * @return the type associated to the given code. + * @throws UnknownTypeCodeException when the given code is not associated to any type. + */ + public Type getType(int code) throws UnknownTypeCodeException + { + Type result = _typeMappings.get(code); + if (result == null) + { + throw new UnknownTypeCodeException(code); + } + return result; + } + + /** + * Returns the access mode associated to the given code. + * + * @param code the code used as search criteria. + * @return the access mode associated to the given code. + * @throws UnknownAccessCodeException when the given code is not associated to any access mode. + */ + public AccessMode getAccessMode(int code) throws UnknownAccessCodeException + { + AccessMode result = _accessModes.get(code); + if (result == null) + { + throw new UnknownAccessCodeException(code); + } + return result; + } + + /** + * Returns the validator class name associated to the given type. + * + * @param type the type. + * @return the validator class name associated to the given type. + */ + public String getValidatorClassName (Type type) + { + return _validators.get(type); + } + + /** + * Gets from this configuration the list of known broker (I mean, only their connection data). + * + * @return the list of known broker + */ + public Set> getConnectionInfos(){ + return _brokerConnectionInfos.entrySet(); + } + + /** + * Gets from this configuration the connection data of the broker associated with the given id. + * + * @param brokerId the broker identifier. + * @return the connection data of the broker associated with the given id. + * @throws UnknownBrokerException when the given id is not associated with any broker. + */ + public BrokerConnectionData getBrokerConnectionData (UUID brokerId) throws UnknownBrokerException + { + BrokerConnectionData connectionData = _brokerConnectionInfos.get(brokerId); + if (connectionData == null) + { + throw new UnknownBrokerException(brokerId); + } + return _brokerConnectionInfos.get(brokerId); + } + + /** + * Returns the name of the management queue. + * + * @return the name of the management queue. + */ + public String getManagementQueueName() { + return _managementQueueName; + } + + /** + * Returns the name of the method-reply queue. + * + * @return the name of the method-reply queue. + */ + public String getMethodReplyQueueName() { + return _methodReplyQueueName; + } + + /** + * Returns a map containing all the configured management message handlers. + * A management message handler it is a basically a processor for a management queue incoming message associated + * with a specific opcode. + * + * @return a map containing all the configured management message handlers. + */ + public Map getManagementQueueHandlers() + { + return _managementQueueHandlers; + } + + /** + * Returns a map containing all the configured method-reply message handlers. + * A management message handler it is a basically a processor for a method-reply queue incoming message associated + * with a specific opcode. + * + * @return a map containing all the configured method-reply message handlers. + */ + public Map getMethodReplyQueueHandlers() + { + return _methodReplyQueueHandlers; + } + + /** + * Returns the message header used for sending command message on management queue. + * + * @return the message header used for sending command message on management queue. + */ + public Header getCommandMessageHeader () + { + return _headerForCommandMessages; + } + + /** + * Returns the command message properties. + * + * @return the command message properties. + */ + public MessageProperties getCommandMessageProperties () + { + return _messageProperties; + } + + /** + * Returns the command message delivery properties. + * + * @return the command message delivery properties. + */ + public DeliveryProperties getCommandDeliveryProperties () + { + return _deliveryProperties; + } + + /** + * Adds a new type mapping to this configuration. + * + * @param code the code that will be associated with the declared type. + * @param type the type. + * @param vailidatorClassName the FQN of the validator class that will be + * associated with the given type. + */ + void addTypeMapping(int code, Type type, String validatorClassName) { + _typeMappings.put(code, type); + _validators.put(type, validatorClassName); + + LOGGER.info( + Messages.QMAN_000005_TYPE_MAPPING_CONFIGURED, + code, + type, + validatorClassName); + } + + + /** + * Adds a new type mapping to this configuration. + * + * @param code the code that will be associated with the declared type. + * @param type the type. + */ + void addTypeMapping(int code, Type type) { + _typeMappings.put(code, type); + + LOGGER.info( + Messages.QMAN_000005_TYPE_MAPPING_CONFIGURED, + code, + type, + "not configured for this type."); + } + + /** + * Adds a new access mode mapping to this configuration. + * + * @param code the code that will be associated with the access mode, + * @param accessMode the accessMode. + */ + void addAccessModeMapping(int code, AccessMode accessMode){ + _accessModes.put(code, accessMode); + + LOGGER.info(Messages.QMAN_000006_ACCESS_MODE_MAPPING_CONFIGURED, code,accessMode); + } + + /** + * Adds a new management message handler to this configuration. + * The incoming mapping object will contains an opcode and the class (as a string) of the message handler that will be used + * for processing incoming messages with that opcode. + * + * @param mapping the message handler mapping. + */ + void addManagementMessageHandlerMapping (MessageHandlerMapping mapping) + { + Character opcode = mapping.getOpcode(); + IMessageHandler handler = mapping.getMessageHandler(); + _managementQueueHandlers.put(opcode, handler); + + LOGGER.info(Messages.QMAN_000007_MANAGEMENT_HANDLER_MAPPING_CONFIGURED, opcode,handler.getClass().getName()); + } + + /** + * Adds a new method-reply message handler to this configuration. + * The incoming mapping object will contains an opcode and the class (as a string) of the message handler that will be used + * for processing incoming messages with that opcode. + * + * @param mapping the message handler mapping. + */ + void addMethodReplyMessageHandlerMapping (MessageHandlerMapping mapping) + { + Character opcode = mapping.getOpcode(); + IMessageHandler handler = mapping.getMessageHandler(); + _methodReplyQueueHandlers.put(opcode, handler); + + LOGGER.info(Messages.QMAN_000008_METHOD_REPLY_HANDLER_MAPPING_CONFIGURED, opcode,handler.getClass().getName()); + } + + /** + * Adds to this configuration a new broker connection data. + * + * @param brokerId the broker identifier. + * @param connectionData the connection data. + * @throws BrokerAlreadyConnectedException when the broker is already connected. + * @throws BrokerConnectionException when a connection cannot be estabilished. + */ + void addBrokerConnectionData (UUID brokerId, BrokerConnectionData connectionData) throws BrokerAlreadyConnectedException, BrokerConnectionException + { + if (_brokerConnectionInfos.containsValue(connectionData)) + { + throw new BrokerAlreadyConnectedException(connectionData); + } + + try + { + QpidDatasource.getInstance().addConnectionPool(brokerId, connectionData); + _brokerConnectionInfos.put(brokerId,connectionData); + + LOGGER.info(Messages.QMAN_000009_BROKER_DATA_CONFIGURED,brokerId,connectionData); + } catch(Exception exception) + { + throw new BrokerConnectionException(exception); + } + + } + + /** + * Header for command messages is created once because it only contains static values. + */ + private void createHeaderForCommandMessages () + { + ReplyTo replyTo=new ReplyTo(); + replyTo.setRoutingKey(_methodReplyQueueName); + _messageProperties.setReplyTo(replyTo); + _deliveryProperties.setRoutingKey(Names.AGENT_ROUTING_KEY); + _headerForCommandMessages = new Header(_deliveryProperties, _messageProperties); + } + + /** + * Creates the name of the queues used by this service. + * This is done because if a broker should be managed by one or more management client, then each of them + * must have its own channels to communicate with. + */ + private void defineQueueNames() + { + UUID uuid = UUID.randomUUID(); + _managementQueueName = Names.MANAGEMENT_QUEUE_PREFIX+uuid; + _methodReplyQueueName = Names.METHOD_REPLY_QUEUE_PREFIX+uuid; + + LOGGER.debug(Messages.QMAN_200004_MANAGEMENT_QUEUE_NAME,_managementQueueName); + LOGGER.debug(Messages.QMAN_200005_METHOD_REPLY_QUEUE_NAME,_methodReplyQueueName); + } + + /** + * Returns the worker manager thread pool size. + * + * @return the worker manager thread pool size. + */ + public int getWorkerManagerPoolSize() + { + return _poolSize; + } + + /** + * Sets the size of the worker manager thread pool. + * + * @param poolSize the size of the worker manager thread pool. + */ + void setWorkerManagerPoolSize(int poolSize) + { + this._poolSize = poolSize; + } + + /** + * Returns the maximum size of the worker manager + * thread pool size. + * + * @return the max size of the worker manager thread pool. + */ + public int getWorkerManagerMaxPoolSize() + { + return _maxPoolSize; + } + + /** + * Sets the maximum size of the worker manager + * thread pool size. + * + * @param maxPoolSize the max size of the worker manager thread pool. + */ + void setWorkerManagerMaxPoolSize(int maxPoolSize) + { + this._maxPoolSize = maxPoolSize; + } + + /** + * Returns the max amount of time that an excess thread + * can be idle before purging from the pool. + * + * @return the max keep alive time. + */ + public long getWorkerManagerKeepAliveTime() + { + return _keepAliveTime; + } + + /** + * Sets the max amount of time that an excess thread + * can be idle before purging from the pool. + * + * @param keepAliveTime the max keep alive time. + */ + void setWorkerManagerKeepAliveTime(long keepAliveTime) + { + this._keepAliveTime = keepAliveTime; + } + + /** + * Configures access mode mappings. + * An access mode mapping is an association between a code and an access mode. + */ + private void addAccessModeMappings() { + addAccessModeMapping(1,AccessMode.RC); + addAccessModeMapping(2,AccessMode.RW); + addAccessModeMapping(3,AccessMode.RO); + } + + /** + * Configures type mappings. + * A type mapping is an association between a code and a management type. + */ + private void addTypeMappings() + { + addTypeMapping(1,new Uint8(),Names.NUMBER_VALIDATOR); + addTypeMapping(2,new Uint16(),Names.NUMBER_VALIDATOR); + addTypeMapping(3,new Uint32(),Names.NUMBER_VALIDATOR); + addTypeMapping(4,new Uint64(),Names.NUMBER_VALIDATOR); + addTypeMapping(6,new Str8(),Names.STRING_VALIDATOR); + addTypeMapping(7,new Str16(),Names.STRING_VALIDATOR); + addTypeMapping(8,new AbsTime()); + addTypeMapping(9,new DeltaTime()); + addTypeMapping(10,new ObjectReference()); + addTypeMapping(11,new org.apache.qpid.management.domain.model.type.Boolean()); + addTypeMapping(14,new org.apache.qpid.management.domain.model.type.Uuid()); + addTypeMapping(15,new org.apache.qpid.management.domain.model.type.Map()); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java new file mode 100644 index 0000000000..6eed515e11 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +/** + * Thrown when a problem is encountered during building the configuration. + * + * @author Andrea Gazzarini + */ +public class ConfigurationException extends Exception +{ + private static final long serialVersionUID = 8238481177714286259L; + + public ConfigurationException(String msg) + { + super(msg); + } + + /** + * Builds a new ConfigurationException with the given cause. + * + * @param exception the exception cause. + */ + public ConfigurationException(Exception exception) + { + super(exception); + } + + public ConfigurationException(String msg,Exception exception) + { + super(msg,exception); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java new file mode 100644 index 0000000000..fe44c6aff7 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java @@ -0,0 +1,240 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.UUID; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.EventContentMessageHandler; +import org.apache.qpid.management.domain.handler.impl.HeartBeatIndicationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler; +import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler; +import org.apache.qpid.transport.util.Logger; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Director used for coordinating the build process of configuration. + * This is the only component which has a read-write permission on Configuration object. + */ +public class Configurator extends DefaultHandler +{ + private final static Logger LOGGER = Logger.get(Configurator.class); + + /** + * Default (empty) parser used when there's no need to process data (non relevant elements). + */ + final static IParser DEFAULT_PARSER = new IParser() { + + public void setCurrrentAttributeValue (String value) + { + } + + public void setCurrentAttributeName (String name) + { + } + }; + + IParser _brokerConfigurationParser = new BrokerConnectionDataParser(); + IParser _workerManagerConfigurationParser = new WorkerManagerConfigurationParser(); + IParser _currentParser = DEFAULT_PARSER; + + /** + * Delegates the processing to the current parser. + */ + @Override + public void characters (char[] ch, int start, int length) throws SAXException + { + String value = new String(ch,start,length).trim(); + if (value.length() != 0) { + _currentParser.setCurrrentAttributeValue(value); + } + } + + /** + * Here is defined what parser needs to be used for processing the current data. + */ + @Override + public void startElement (String uri, String localName, String name, Attributes attributes) throws SAXException + { + switch(Tag.get(name)) + { + case BROKERS : + { + _currentParser = _brokerConfigurationParser; + break; + } + case WORK_MANAGER : + { + _currentParser = _workerManagerConfigurationParser; + break; + } + } + } + + @Override + public void endElement (String uri, String localName, String name) throws SAXException + { + _currentParser.setCurrentAttributeName(name); + } + + /** + * Builds whole configuration. + * + * @throws ConfigurationException when the build fails. + */ + public void configure() throws ConfigurationException + { + BufferedReader reader = null; + try + { + String initialConfigFileName = System.getProperty(Names.QMAN_CONFIG_OPTION_NAME); + if (initialConfigFileName != null && initialConfigFileName.trim().length() != 0) + { + File initialConfigurationFile = new File(initialConfigFileName); + if (initialConfigurationFile.canRead()) + { + SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); + reader = new BufferedReader( + new InputStreamReader( + new FileInputStream(initialConfigFileName))); + InputSource source = new InputSource(reader); + parser.parse(source, this); + } else { + LOGGER.warn( + Messages.QMAN_300004_INVALID_CONFIGURATION_FILE, + initialConfigFileName); + } + } + + addMandatoryManagementMessageHandlers(); + addMandatoryMethodReplyMessageHandlers(); + } catch (Exception exception) + { + throw new ConfigurationException(exception); + } finally + { + try + { + reader.close(); + } catch (Exception ignore) + { + } + } + } + + /** + * Creates and return a value object (BrokerConnectionData) with the given parameters. + * Note that that object will be stored on configuration and it could be used to set a connection with the broker. + * This happens when the "initialPoolCapacity" is greater than 0 : in this case the caller is indicatinf that it wants to open + * one or more connections immediately at startup and therefore Q-Man will try to do that. + * + * @param host the hostname where the broker is running. + * @param port the port where the broker is running. + * @param username the username for connecting with the broker. + * @param password the password for connecting with the broker. + * @param virtualHost the virtual host. + * @param initialPoolCapacity the number of the connection that must be immediately opened. + * @param maxPoolCapacity the maximum number of opened connection. + * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection. + * @return the value object containing the data above. + * @throws BrokerAlreadyConnectedException when the broker is already connected. + * @throws BrokerConnectionException when a connection cannot be estabilished. + */ + public BrokerConnectionData createAndReturnBrokerConnectionData( + UUID brokerId, + String host, + int port, + String username, + String password, + String virtualHost, + int initialPoolCapacity, + int maxPoolCapacity, + long maxWaitTimeout) throws BrokerAlreadyConnectedException, BrokerConnectionException + { + BrokerConnectionData data = new BrokerConnectionData( + host, + port, + virtualHost, + username, + password, + initialPoolCapacity, + maxPoolCapacity, + maxWaitTimeout); + Configuration.getInstance().addBrokerConnectionData(brokerId, data); + return data; + } + + /** + * Configures the mandatory management message handlers. + */ + void addMandatoryMethodReplyMessageHandlers () + { + Configuration.getInstance().addMethodReplyMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.OPERATION_INVOCATION_RESPONSE_OPCODE, + new MethodResponseMessageHandler())); + + Configuration.getInstance().addMethodReplyMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.SCHEMA_RESPONSE_OPCODE, + new SchemaResponseMessageHandler())); + } + + /** + * Configures the mandatory management message handlers. + */ + void addMandatoryManagementMessageHandlers () + { + Configuration.getInstance().addManagementMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.INSTRUMENTATION_CONTENT_RESPONSE_OPCODE, + new InstrumentationMessageHandler())); + + Configuration.getInstance().addManagementMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.CONFIGURATION_CONTENT_RESPONSE_OPCDE, + new ConfigurationMessageHandler())); + + Configuration.getInstance().addManagementMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.EVENT_CONTENT_RESPONSE_OPCDE, + new EventContentMessageHandler())); + + Configuration.getInstance().addManagementMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.HEARTBEAT_INDICATION_RESPONSE_OPCODE, + new HeartBeatIndicationMessageHandler())); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java new file mode 100644 index 0000000000..a221686765 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/IParser.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +/** + * Interface definition for configuration parser + * Concrete implementors are responsible for parsing a specific XML part of configuration data. + * + * @author Andrea Gazzarini + */ +interface IParser +{ + /** + * Main director callback : Sets the name of the current attribute. + * + * @param name the name of the current attribute. + */ + void setCurrentAttributeName(String name); + + /** + * Main director callback : sets the value of the current attribute. + * + * @param value the value of the current attribute. + */ + void setCurrrentAttributeValue(String value); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java new file mode 100644 index 0000000000..b02fb789cc --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java @@ -0,0 +1,64 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import org.apache.qpid.management.domain.handler.base.IMessageHandler; + +/** + * Message Handler mapping used for associating an opcode with a message handler. + */ +class MessageHandlerMapping +{ + private final Character _opcode; + private final IMessageHandler _handler; + + /** + * Builds a new mapping with the given opcode and handler class. + * + * @param opcode the opcode. + * @param handlerClass the handler class. + */ + MessageHandlerMapping(Character opcode, IMessageHandler handler) + { + this._opcode = opcode; + this._handler = handler; + } + + /** + * Returns the opcode of this mapping. + * + * @return the code of this mapping. + */ + Character getOpcode () + { + return _opcode; + } + + /** + * Returns the message handler for this mapping. + * + * @return the message handler for this mapping. + */ + IMessageHandler getMessageHandler() + { + return _handler; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java new file mode 100644 index 0000000000..569a65a782 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java @@ -0,0 +1,249 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.pool.BasePoolableObjectFactory; +import org.apache.commons.pool.ObjectPool; +import org.apache.commons.pool.impl.GenericObjectPool; +import org.apache.commons.pool.impl.GenericObjectPoolFactory; +import org.apache.qpid.management.Messages; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionException; +import org.apache.qpid.transport.util.Logger; + +/** + * Qpid datasource. + * Basically it is a connection pool manager used for optimizing broker connections usage. + * + * @author Andrea Gazzarini + */ +public final class QpidDatasource +{ + private final static Logger LOGGER = Logger.get(QpidDatasource.class); + + /** + * A connection decorator used for adding pool interaction behaviour to an existing connection. + * + * @author Andrea Gazzarini + */ + class PooledConnection extends Connection + { + private final UUID _brokerId; + private boolean _valid; + + /** + * Builds a new decorator with the given connection. + * + * @param brokerId the broker identifier. + */ + private PooledConnection(UUID brokerId) + { + this._brokerId = brokerId; + _valid = true; + } + + /** + * Returns true if the underlying connection is still valid and can be used. + * + * @return true if the underlying connection is still valid and can be used. + */ + boolean isValid() + { + return _valid; + } + + void reallyClose() + { + super.close(); + } + + /** + * Returns the connection to the pool. That is, marks this connections as available. + * After that, this connection will be available for further operations. + */ + public void close() + { + try + { + pools.get(_brokerId).returnObject(this); + + LOGGER.debug(Messages.QMAN_200006_QPID_CONNECTION_RELEASED, this); + } + catch (Exception e) + { + throw new ConnectionException(e); + } + } + + public void exception(Throwable t) + { + //super.exception(t); + _valid = false; + } + } + + /** + * This is the connection factory, that is, the factory used to manage the lifecycle (create, validate & destroy) of + * the broker connection(s). + * + * @author Andrea Gazzarini + */ + class QpidConnectionFactory extends BasePoolableObjectFactory + { + private final BrokerConnectionData _connectionData; + private final UUID _brokerId; + + /** + * Builds a new connection factory with the given parameters. + * + * @param brokerId the broker identifier. + * @param connectionData the connecton data. + */ + private QpidConnectionFactory(UUID brokerId, BrokerConnectionData connectionData) + { + this._connectionData = connectionData; + this._brokerId = brokerId; + } + + /** + * Creates a new underlying connection. + */ + @Override + public Connection makeObject () throws Exception + { + PooledConnection connection = new PooledConnection(_brokerId); + connection.connect( + _connectionData.getHost(), + _connectionData.getPort(), + _connectionData.getVirtualHost(), + _connectionData.getUsername(), + _connectionData.getPassword(), + false); + return connection; + } + + /** + * Validates the underlying connection. + */ + @Override + public boolean validateObject (Object obj) + { + PooledConnection connection = (PooledConnection) obj; + boolean isValid = connection.isValid(); + + LOGGER.debug(Messages.QMAN_200007_TEST_CONNECTION_ON_RESERVE,isValid); + + return isValid; + } + + /** + * Closes the underlying connection. + */ + @Override + public void destroyObject (Object obj) throws Exception + { + try + { + PooledConnection connection = (PooledConnection) obj; + connection.reallyClose(); + + LOGGER.debug(Messages.QMAN_200008_CONNECTION_DESTROYED); + } catch (Exception exception) + { + LOGGER.debug(exception, Messages.QMAN_200009_CONNECTION_DESTROY_FAILURE); + } + } + } + + // Singleton instance. + private static QpidDatasource instance = new QpidDatasource(); + + // Each entry contains a connection pool for a specific broker. + private Map pools = new HashMap(); + + // Private constructor. + private QpidDatasource() + { + } + + /** + * Gets an available connection from the pool of the given broker. + * + * @param brokerId the broker identifier. + * @return a valid connection to the broker associated with the given identifier. + */ + public Connection getConnection(UUID brokerId) throws Exception + { + return (Connection) pools.get(brokerId).borrowObject(); + } + + /** + * Entry point method for retrieving the singleton instance of this datasource. + * + * @return the qpid datasource singleton instance. + */ + public static QpidDatasource getInstance() + { + return instance; + } + + /** + * Adds a connection pool to this datasource. + * + * @param brokerId the broker identifier that will be associated with the new connection pool. + * @param connectionData the broker connection data. + * @throws Exception when the pool cannot be created. + */ + void addConnectionPool(UUID brokerId,BrokerConnectionData connectionData) throws Exception + { + GenericObjectPoolFactory factory = new GenericObjectPoolFactory( + new QpidConnectionFactory(brokerId,connectionData), + connectionData.getMaxPoolCapacity(), + GenericObjectPool.WHEN_EXHAUSTED_BLOCK, + connectionData.getMaxWaitTimeout(),-1, + true, + false); + + ObjectPool pool = factory.createPool(); + + // Open connections at startup according to initial capacity param value. + int howManyConnectionAtStartup = connectionData.getInitialPoolCapacity(); + Object [] openStartupList = new Object[howManyConnectionAtStartup]; + + // Open... + for (int index = 0; index < howManyConnectionAtStartup; index++) + { + openStartupList[index] = pool.borrowObject(); + } + + // ...and immediately return them to pool. In this way the pooled connection has been opened. + for (int index = 0; index < howManyConnectionAtStartup; index++) + { + pool.returnObject(openStartupList[index]); + } + + pools.put(brokerId,pool); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java new file mode 100644 index 0000000000..c2b6e1e27d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/Tag.java @@ -0,0 +1,54 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.configuration; + +/** + * Configuration Tag catalogue. + * + * @author Andrea Gazzarini + */ +public enum Tag { + CONFIGURATION { @Override public String toString() { return "configuration"; }}, + BROKER { @Override public String toString() { return "broker"; }}, + HOST { @Override public String toString() { return "host"; }}, + PORT { @Override public String toString() { return "port"; }}, + MAX_POOL_CAPACITY { @Override public String toString() { return "max-pool-capacity"; }}, + MAX_WAIT_TIMEOUT { @Override public String toString() { return "max-wait-timeout"; }}, + INITIAL_POOL_CAPACITY { @Override public String toString() { return "initial-pool-capacity"; }}, + VIRTUAL_HOST { @Override public String toString() { return "virtual-host"; }}, + USER { @Override public String toString() { return "user"; }}, + PASSWORD { @Override public String toString() { return "password"; }}, + BROKERS { @Override public String toString() { return "brokers"; }}, + WORK_MANAGER { @Override public String toString() { return "work-manager"; }}, + POOL_CAPACITY { @Override public String toString() { return "pool-capacity"; }}, + KEEP_ALIVE_TIME { @Override public String toString() { return "keep-alive-time"; }}; + + /** + * Returns the enum entry associated to the given tag name. + * + * @param name the name of tag. + * @return the enum entry associated to the given tag name. + */ + public static Tag get(String name) { + return valueOf(name.replaceAll("-", "_").toUpperCase()); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java new file mode 100644 index 0000000000..b7f1c0a7ec --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +/** + * Thrown when no access mode is found in configuration associated to the given code. + * + * @author Andrea Gazzarini + */ +public class UnknownAccessCodeException extends Exception +{ + private static final long serialVersionUID = 2350963503092509119L; + private final int _code; + + /** + * Builds a new UnknownAccessCodeException with the given code. + * + * @param code the access code. + */ + UnknownAccessCodeException(int code) + { + super(String.valueOf(code)); + this._code = code; + } + + /** + * Returns the unknown code. + * + * @return the unknown code. + */ + public int getCode () + { + return _code; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java new file mode 100644 index 0000000000..5b08e09c24 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.UUID; + +/** + * Thrown when someone requests connection data for an unknown broker. + * + * @author Andrea Gazzarini + */ +public class UnknownBrokerException extends Exception +{ + private static final long serialVersionUID = 4965395428832158924L; + + /** + * Builds a new UnknownBrokerException with the given broker id. + * + * @param brokerId the broker identifier. + */ + UnknownBrokerException(UUID brokerId) + { + super(String.valueOf(brokerId)); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java new file mode 100644 index 0000000000..57005d21e5 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +/** + * Thrown when no type is found in configuration associated to the given code. + * + * @author Andrea Gazzarini + */ +public class UnknownTypeCodeException extends Exception +{ + private static final long serialVersionUID = 5440934037645111591L; + private int _code; + + /** + * Builds a new UnknownTypeCodeException with the given code. + * + * @param code the access code. + */ + UnknownTypeCodeException(int code) + { + super(String.valueOf(code)); + this._code = code; + } + + /** + * Returns the unknown code. + * + * @return the unknown code. + */ + public int getCode () + { + return _code; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java b/java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java new file mode 100644 index 0000000000..4e68b54b12 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/configuration/WorkerManagerConfigurationParser.java @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.UUID; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.transport.util.Logger; + +/** + * Parser used for building worker manager settings. + * The corresponding section of the configuration file is : + * + + 5 + 15 + 5000 + + + * + * @author Andrea Gazzarini + */ +class WorkerManagerConfigurationParser implements IParser +{ + private final static Logger LOGGER = Logger.get(Configuration.class); + private String _currentValue; + + private String _poolSizeAsString; + private String _maxPoolSizeAsString; + private String _keepAliveTimeAsString; + + /** + * Callback : the given value is the text content of the current node. + */ + public void setCurrrentAttributeValue (String value) + { + this._currentValue = value; + } + + /** + * Callback: each time the end of an element is reached + * this method is called. + */ + public void setCurrentAttributeName (String name) + { + switch (Tag.get(name)) + { + case POOL_CAPACITY: + { + _poolSizeAsString = _currentValue.trim(); + break; + } + case MAX_POOL_CAPACITY : + { + _maxPoolSizeAsString = _currentValue; + break; + } + case KEEP_ALIVE_TIME: + { + _keepAliveTimeAsString = _currentValue; + break; + } + case WORK_MANAGER: + { + Configuration configuration = Configuration.getInstance(); + try + { + configuration.setWorkerManagerPoolSize(Integer.parseInt(_poolSizeAsString)); + configuration.setWorkerManagerMaxPoolSize(Integer.parseInt(_maxPoolSizeAsString)); + configuration.setWorkerManagerKeepAliveTime(Long.parseLong(_keepAliveTimeAsString)); + } catch(Exception exception) + { + LOGGER.error(Messages.QMAN_100039_UNABLE_TO_CONFIGURE_PROPERLY_WORKER_MANAGER); + } finally { + LOGGER.info(Messages.QMAN_000035_WORK_MANAGER_POOL_SIZE,configuration.getWorkerManagerPoolSize()); + LOGGER.info(Messages.QMAN_000036_WORK_MANAGER_MAX_POOL_SIZE,configuration.getWorkerManagerMaxPoolSize()); + LOGGER.info(Messages.QMAN_000037_WORK_MANAGER_KEEP_ALIVE_TIME,configuration.getWorkerManagerKeepAliveTime()); + } + break; + } + } + } + + /** + * Gets an uuid in order to associate current connection data with a broker. + * @return + */ + UUID getUUId(){ + return UUID.randomUUID(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java new file mode 100644 index 0000000000..798e835ff4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.base; + +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.transport.util.Logger; + +/** + * Base class for all message handlers. + * A message handler is an handler for a specific type of message. + * Message type is defined by the opcode. + * + * @author Andrea Gazzarini + */ +public abstract class BaseMessageHandler implements IMessageHandler +{ + /** + * Logger used for logging. + */ + protected final Logger _logger = Logger.get(getClass()); + + /** + * Managed broker domain model. + */ + protected DomainModel _domainModel; + + /** + * Sets the broker domain model. + * + * @param domainModel the broker domain model. + */ + public void setDomainModel(DomainModel domainModel) + { + this._domainModel = domainModel; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java new file mode 100644 index 0000000000..be000e9a05 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java @@ -0,0 +1,114 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.base; + +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.transport.codec.Decoder; + +/** + * Base class for content indication message handlers. + * + * @author Andrea Gazzarini + */ +public abstract class ContentIndicationMessageHandler extends BaseMessageHandler +{ + /** + * Processes the income message. + * + * @param decoder the decoder used to parse the message. + * @param sequenceNumber the sequence number of the message. + */ + public final void process (Decoder decoder, int sequenceNumber) + { + String packageName = decoder.readStr8(); + String className = decoder.readStr8(); + Binary classHash = new Binary(decoder.readBin128()); + + long timeStampOfCurrentSample = decoder.readDatetime(); + long timeObjectWasCreated = decoder.readDatetime(); + long timeObjectWasDeleted = decoder.readDatetime(); + + Binary objectId = new Binary(decoder.readBin128()); + + if (objectHasBeenRemoved(timeObjectWasDeleted, timeStampOfCurrentSample)) + { + removeObjectInstance(packageName,className,classHash,objectId); + } else + { + updateDomainModel( + packageName, + className, + classHash, + objectId, + timeStampOfCurrentSample, + timeObjectWasCreated, + timeObjectWasDeleted, + decoder.readReaminingBytes()); + } + } + + /** + * Removes an object instance from the domain model. + * + * @param packageName the package name. + * @param className the class name. + * @param classHash the class hash. + * @param objectId the object identifier. + */ + void removeObjectInstance(String packageName, String className,Binary classHash, Binary objectId) + { + _domainModel.removeObjectInstance(packageName,className,classHash,objectId); + } + + /** + * Checks if the timestamps contained in the message indicate that the object has been removed. + * + * @param deletionTimestamp time object was deleted. + * @param now timestamp of the current message. + * @return true if the object has been removed, false otherwise. + */ + boolean objectHasBeenRemoved(long deletionTimestamp, long now) { + return (deletionTimestamp != 0) && (now > deletionTimestamp); + } + + /** + * Updates domain model with the incoming data. + * This is a template method that each concrete subclass must implement in order to update the domain model + * with the incoming data. + * + * @param packageName the name of the package. + * @param className the name of the class. + * @param objectId the object identifier. + * @param timeStampOfCurrentSample timestamp of current sample. + * @param timeObjectWasCreated time object was created. + * @param timeObjectWasDeleted time object was deleted. + * @param contentData object instance incoming data. + */ + protected abstract void updateDomainModel( + String packageName, + String className, + Binary classHash, + Binary objectId, + long timeStampOfCurrentSample, + long timeObjectWasCreated, + long timeObjectWasDeleted, + byte []contentData ); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java new file mode 100644 index 0000000000..c120334d30 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java @@ -0,0 +1,52 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.base; + +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.transport.codec.Decoder; + +/** + * Interface definition for a processor able to deal with a specific message. + * The concrete implementor must define what has to be done with the supplied (incoming) stream and the sequence + * number. + * + * @author Andrea Gazzarini. + */ +public interface IMessageHandler +{ + /** + * Processes the (incoming) stream message. + * Note that the main controller (the component that is controlling this handler) has already read the magic number and + * the sequence number so here concrete implementors must start from that point (that is, just after the sequence + * number). + * + * @param decoder the stream decoder. + * @param sequenceNumber the sequence number of the message. + */ + void process (Decoder decoder, int sequenceNumber); + + /** + * Injects the domain model into this handler. + * + * @param domainModel the domain model. + */ + void setDomainModel(DomainModel domainModel); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java new file mode 100644 index 0000000000..3158138172 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import org.apache.qpid.management.domain.handler.base.ContentIndicationMessageHandler; +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Schema Response message handler. + * This handler is responsible to process 'c'(opcode) messages sent by the management broker. + * + * @author Andrea Gazzarini + */ +public class ConfigurationMessageHandler extends ContentIndicationMessageHandler +{ + /** + * Broker domain model is going to be updated with incoming configuration data. + * + * @param packageName the name of the package. + * @param className the name of the class. + * @param objectId the object identifier. + * @param timeStampOfCurrentSample the timestamp of incoming data. + * @param timeObjectWasCreated time object was created. + * @param timeObjectWasDeleted time object was deleted. + */ + @Override + protected void updateDomainModel ( + String packageName, + String className, + Binary classHash, + Binary objectId, + long timeStampOfCurrentSample, + long timeObjectWasCreated, + long timeObjectWasDeleted, + byte[] contentData) + { + _domainModel.addConfigurationRawData(packageName,className,classHash,objectId,contentData); + } + } diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java new file mode 100644 index 0000000000..0a590d2836 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import org.apache.qpid.management.domain.handler.base.BaseMessageHandler; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.transport.codec.Decoder; + +/** + * Base class for content indication message handlers. + * + * @author Andrea Gazzarini + */ +public class EventContentMessageHandler extends BaseMessageHandler +{ + /** + * Processes the income message. + * + * @param decoder the decoder used to parse the message. + * @param sequenceNumber the sequence number of the message. + */ + public final void process (Decoder decoder, int sequenceNumber) + { + String packageName = decoder.readStr8(); + String eventName = decoder.readStr8(); + Binary eventHash = new Binary(decoder.readBin128()); + long timeStampOfCurrentSample = decoder.readDatetime(); + int severity = decoder.readUint8(); + byte[] argumentsData = decoder.readReaminingBytes(); + + _domainModel.addEventRawData(packageName, eventName, eventHash, argumentsData,timeStampOfCurrentSample,severity); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java new file mode 100644 index 0000000000..08c4f1bc5d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/HeartBeatIndicationMessageHandler.java @@ -0,0 +1,39 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.domain.handler.impl; + +import org.apache.qpid.management.domain.handler.base.BaseMessageHandler; +import org.apache.qpid.transport.codec.Decoder; + +/** + * This is the handler responsible for processing the heartbeat indication response messages. + * At the moment it simply updates the last refresh update timestamp of the domain model. + * + * @author Andrea Gazzarini. + */ +public class HeartBeatIndicationMessageHandler extends BaseMessageHandler +{ + public void process(Decoder decoder, int sequenceNumber) + { + _domainModel.updateLastRefreshDate(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java new file mode 100644 index 0000000000..4ce64dd339 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/IMethodInvocationListener.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.util.EventListener; + +import org.apache.qpid.management.domain.model.InvocationEvent; + +/** + * Listener interface used to denote a component interested in method invocation events. + * + * @author Andrea Gazzarini + */ +public interface IMethodInvocationListener extends EventListener +{ + /** + * An operation is going to be invoked on a specific object instance. + * This lets this listener to be informed about the imminent invocation. + * + * @param event the invocation event. + */ + void operationIsGoingToBeInvoked(InvocationEvent event); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java new file mode 100644 index 0000000000..e86a44f829 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import org.apache.qpid.management.domain.handler.base.ContentIndicationMessageHandler; +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Schema Response message handler. + * This handler is responsible to process 'i'(opcode) messages sent by the management broker. + * + * @author Andrea Gazzarini + */ +public class InstrumentationMessageHandler extends ContentIndicationMessageHandler +{ + /** + * Broker domain model is going to be updated with incoming instrumentation data. + * + * @param packageName the name of the package. + * @param className the name of the class. + * @param objectId the object identifier. + * @param timeStampOfCurrentSample the timestamp of incoming data. + * @param timeObjectWasCreated time object was created. + * @param timeObjectWasDeleted time object was deleted. + */ + @Override + protected void updateDomainModel ( + String packageName, + String className, + Binary classHash, + Binary objectId, + long timeStampOfCurrentSample, + long timeObjectWasCreated, + long timeObjectWasDeleted, + byte[] contentData) + { + _domainModel.addInstrumentationRawData(packageName,className,classHash,objectId,contentData); + } + } diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java new file mode 100644 index 0000000000..019fce5a50 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java @@ -0,0 +1,157 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.io.Serializable; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.qpid.management.domain.services.MethodInvocationException; + +/** + * Value object used for storing an invocation method result. + * This is done in order to accomplish multiple return value requirement. + * As we know, it's not possible to do that only with method signature and therefore this value object / struct is used. + * + * @author Andrea Gazzarini + */ +public class InvocationResult implements Serializable +{ + private static final long serialVersionUID = 2062662997326399693L; + + private final long _returnCode; + private final String _statusText; + private final byte [] _outputAndBidirectionalArgumentValues; + private Map _outputSection; + + /** + * Builds an invocation result with the given status code and status text. + * + * @param statusCode the status code. + * @param statusText the status text. + */ + InvocationResult(long statusCode, String statusText,byte [] outputAndBidirectionalArgumentValues) + { + this._returnCode = statusCode; + this._statusText = statusText; + this._outputAndBidirectionalArgumentValues = outputAndBidirectionalArgumentValues; + } + + /** + * Checks if this result contains an error return code. + * + * @return true if this result object contains an error return code. + */ + public boolean isException () + { + return _returnCode != 0; + } + + /** + * Simply throws a new MethodInvocationException. + * Usually this method is called in conjunction with the isException() method in order to raise an exception if + * the wrapped return code means that there was an error. + * + * @throws MethodInvocationException always. + */ + public void createAndThrowException() throws MethodInvocationException + { + throw new MethodInvocationException(_returnCode, _statusText); + } + + @Override + public String toString () + { + StringBuilder builder = new StringBuilder() + .append("Status code : ") + .append(_returnCode) + .append(",") + .append("Status Text : ") + .append(_statusText); + if (_outputSection != null && !_outputSection.isEmpty()) + { + builder.append(". Parameters : "); + for (Entry outputEntry : _outputSection.entrySet()) + { + builder.append(outputEntry.getKey()).append('=').append(outputEntry.getValue()); + builder.append(','); + } + } + return builder.toString(); + } + + /** + * Returns the return code of this invocation result. + * + * @return the return code of this invocation result. + */ + public long getReturnCode () + { + return _returnCode; + } + + /** + * Contains the status text of this invocation result. + * + * @return the status text of this invocation result. + */ + public String getStatusText () + { + return _statusText; + } + + /** + * Returns the output and bidirectional argument values in raw format (byte []) + * + * @return the output and bidirectional argument values in raw format (byte []) + */ + public byte [] getOutputAndBidirectionalArgumentValues() + { + return _outputAndBidirectionalArgumentValues; + } + + /** + * Sets the output section (decoded) of this invocation result. + * When an incoming message arrives, the output section (output and bidirectional argument values) are + * initially stored in raw format. + * After that, their values need to be converted. + * The final result is a map containing (for each Output or Input/Output parameter) the name of the argument as key + * and its value as value. + * + * @param output a map containing outptu and bidirectional values (not in schema order). + */ + public void setOutputSection (Map outputSection) + { + this._outputSection = outputSection; + } + + /** + * Returns the output section of this invocation result. + * The output section consists in output and bidirectional argument values. + * Note that the order of the arguments is not guaranteed. + * + * @param outputSection the output section of this invocation result; + */ + public Map getOutputSection () + { + return _outputSection; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java new file mode 100644 index 0000000000..bc6a77d804 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.util.List; +import java.util.Map; + +/** + * Simple transfer object used for holding method / event definition data. + * + * @author Andrea Gazzarini + */ +public class MethodOrEventDataTransferObject +{ + private final Map _definition; + private List> _argumentDefinitions; + + /** + * Builds a new trasfer object with the given parameters. + * + * @param definition the method definition. + * @param argumentDefinitions the arguments definitions. + */ + public MethodOrEventDataTransferObject( + Map definition, + List> argumentDefinitions) + { + this._definition = definition; + this._argumentDefinitions = argumentDefinitions; + } + + /** + * Returns the method definition. + * + * @return the method definition. + */ + public Map getDefinition() { + return _definition; + } + + /** + * Returns the arguemnts definitions. + * + * @return the arguemnts definitions. + */ + public List> getArgumentsDefinitions() + { + return _argumentDefinitions; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java new file mode 100644 index 0000000000..9c99eb09aa --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java @@ -0,0 +1,106 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.BlockingQueue; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.domain.handler.base.BaseMessageHandler; +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.management.domain.model.InvocationEvent; +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.util.Logger; + +/** + * Message handler for method response messages. + * This handler is installed on domain model as a method invocation result listener. + * When a method is going to be invoked this listener is notified with the exchange channel that will be used between it and + * the event (method invocation) source object. + * + * @author Andrea Gazzarini + * + */ +public class MethodResponseMessageHandler extends BaseMessageHandler +{ + private final static Logger LOGGER = Logger.get(MethodResponseMessageHandler.class); + + private Map> _exchangeChannels = new HashMap>(); + + /** + * This is the listener installed on domain model for method invocations. + */ + private final IMethodInvocationListener methodInvocationListener = new IMethodInvocationListener() + { + /** + * Event source callback. + * A method is going to be invoked and this method lets this listener take the exchange channel that will be used + * with the event source for synchronous communication. + * + * @param event the operation invocation event. + */ + public void operationIsGoingToBeInvoked (InvocationEvent event) + { + _exchangeChannels.put(event.getSequenceNumber(), event.getExchangeChannel()); + } + }; + + /** + * Processes the incoming message. + * + * @param decoder the decoder used for parsing incoming data. + * @param sequenceNumber the sequence number of the incoming message. + */ + public void process (Decoder decoder, int sequenceNumber) + { + InvocationResult result = new InvocationResult(decoder.readUint32(), decoder.readStr16(),decoder.readReaminingBytes()); + BlockingQueue exchangeChannel = _exchangeChannels.remove(sequenceNumber); + if (exchangeChannel != null) + { + try + { + exchangeChannel.put(result); + } catch (InterruptedException exception) + { + LOGGER.error(exception,Messages.QMAN_100010_METHOD_INVOCATION_RESULT_FAILURE,sequenceNumber); + } + } else + { + LOGGER.warn( + "Unable to deal with incoming message because it contains a unknown sequence number (%s).", + sequenceNumber); + } + } + + /** + * Sets the domain model on this handler. + * In addiction, this handler registers a method invocation listener on the domain model. + * + * @param domainModel the managed broker domain model. + */ + @Override + public void setDomainModel (DomainModel domainModel) + { + super.setDomainModel(domainModel); + domainModel.setMethodInvocationListener(methodInvocationListener); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java new file mode 100644 index 0000000000..8456b2f8ac --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObject.java @@ -0,0 +1,314 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.net.URI; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.management.domain.services.MethodInvocationException; + +/** + * This is a sample entity used on QMan test case. + * + * @author Andrea Gazzarini + */ +public class QpidDomainObject implements QpidDomainObjectMBean +{ + private UUID _vhostRef; + private String _name; + private Boolean _durable; + private Map _arguments; + private Long _msgTotalEnqueues; + private Integer _consumerCount; + private Short _mgmtPubInterval; + private Date _expireTime; + private String _type; + private byte [] _byteArray; + + /** + * Builds a new QpidDomainObject with default values for + * its properties. + */ + public QpidDomainObject() + { + _vhostRef = UUID.randomUUID(); + _name = "Initial Name"; + _durable = Boolean.TRUE; + _arguments = new HashMap(); + _arguments.put("Key1", "aStringValue"); + _arguments.put("Key2", Long.MIN_VALUE); + _arguments.put("Key3", Integer.MAX_VALUE); + _arguments.put("Key4", Double.MIN_VALUE); + _arguments.put("Key4", Float.MAX_VALUE); + + _msgTotalEnqueues = Long.MAX_VALUE-10; + _consumerCount = Integer.MIN_VALUE+10; + _mgmtPubInterval = Short.MAX_VALUE; + _expireTime = new Date(Long.MAX_VALUE); + _byteArray = new byte[]{1,2,3,5,6,7,8,7,56}; + } + + /** + * A method that is throwing an exception, everytime. + * + * @throws Exception each time the method is called. + */ + public void throwsException() throws Exception + { + throw new MethodInvocationException(-1,"KO"); + } + + /** + * Sample echo method that return an empty result object. + * That is, an object with only status code / text valorized + * (no output parameters). + * + * @return an empty result object. + */ + public InvocationResult voidWithoutArguments() + { + return new InvocationResult(0,"OK,null",null); + } + + /** + * Echo method that accepts and returns primitive type arrays. + * + * @param longs an array of long. + * @param booleans an array of boolean. + * @param doubles an array of double. + * @param floats an array of float. + * @param integers an array of int. + * @param shorts an array of short. + * @return a result object with the same input parameters (as output parameters). + */ + public InvocationResult echoWithSimpleTypeArrays( + long [] longs, + boolean [] booleans, + double [] doubles, + float [] floats, + int [] integers, + short [] shorts) + { + InvocationResult result = new InvocationResult(0,"OK",null); + Map outputParameters = new HashMap(); + outputParameters.put(long.class.getName(), longs); + outputParameters.put(boolean.class.getName(), booleans); + outputParameters.put(double.class.getName(), doubles); + outputParameters.put(float.class.getName(), floats); + outputParameters.put(int.class.getName(), integers); + outputParameters.put(short.class.getName(), shorts); + result.setOutputSection(outputParameters); + return result; + } + + /** + * Echo method that accepts and returns wrapper types. + * + * @param aLong a java.lang.Long + * @param aBoolean a java.lang.Boolean + * @param aDouble a java.lang.Double + * @param aFloat a java.lang.Float + * @param anInteger a java.lang.Integer + * @param aShort a java.lang.Short + * @param aString a java.lang.String + * @param anURI a java.net.URI + * @param aDate a java.util.Date + * @return a result object with the same given parameters (as output parameters) + */ + public InvocationResult echoWithSimpleTypes( + Long aLong, + Boolean aBoolean, + Double aDouble, + Float aFloat, + Integer anInteger, + Short aShort, + String aString, + URI anURI, + Date aDate) + { + InvocationResult result = new InvocationResult(0,"OK",null); + Map outputParameters = new HashMap(); + outputParameters.put("p1", aLong); + outputParameters.put("p2", aBoolean); + outputParameters.put("p3", aDouble); + outputParameters.put("p4", aFloat); + outputParameters.put("p5", anInteger); + outputParameters.put("p6", aShort); + outputParameters.put("p7", aString); + outputParameters.put("p8", anURI); + outputParameters.put("p9", aDate); + result.setOutputSection(outputParameters); + return result; + } + + /** + * Echo method that accepts and returns wrapper type arrays . + * + * @param longs an array of java.lang.Long + * @param booleans an array of java.lang.Boolean + * @param doubles an array of java.lang.Double + * @param floats an array of java.lang.Float + * @param integers an array of java.lang.Integer + * @param shorts an array of java.lang.Short + * @param strings an array of java.lang.String + * @param uris an array of java.net.URI + * @param dates an array of java.util.Date + * @return a result object with the same input parameters (as output parameters). + */ + public InvocationResult echoWithArrays( + Long [] longs, + Boolean [] booleans, + Double [] doubles, + Float [] floats, + Integer [] integers, + Short [] shorts, + String [] strings, + URI [] uris, + Date [] dates) + { + InvocationResult result = new InvocationResult(0,"OK",null); + Map outputParameters = new HashMap(); + outputParameters.put(Long.class.getName(), longs); + outputParameters.put(Boolean.class.getName(), booleans); + outputParameters.put(Double.class.getName(), doubles); + outputParameters.put(Float.class.getName(), floats); + outputParameters.put(Integer.class.getName(), integers); + outputParameters.put(Short.class.getName(), shorts); + outputParameters.put(String.class.getName(), strings); + outputParameters.put(URI.class.getName(), uris); + outputParameters.put(Date.class.getName(), dates); + result.setOutputSection(outputParameters); + return result; + } + + /** + * Echo method that accepts and returns a byte array. + * + * @param byteArray a byte array + * @return a result containing the input byte array (as output parameter) + */ + public InvocationResult echoWithByteArray(byte [] byteArray) + { + InvocationResult result = new InvocationResult(0,"OK",null); + Map outputParameters = new HashMap(); + outputParameters.put(byte[].class.getName(),byteArray); + result.setOutputSection(outputParameters); + return result; + } + + /** + * Echo method that accepts and returns an UUID. + * + * @param uuid a java.util.UUID. + * @return a result containing the input UUID (as output parameter) + */ + public InvocationResult echoWithUUID(UUID uuid) + { + InvocationResult result = new InvocationResult(0,"OK",null); + Map outputParameters = new HashMap(); + outputParameters.put("uuid",uuid); + result.setOutputSection(outputParameters); + return result; + } + + /** + * Echo method that accepts and returns a Map. + * + * @param map a java.util.Map. + * @return a result containing the input Map (as output parameter) + */ + public InvocationResult echoWithMap(Map map) + { + InvocationResult result = new InvocationResult(0,"OK",null); + Map outputParameters = new HashMap(); + outputParameters.put("map",map); + result.setOutputSection(outputParameters); + return result; + } + + public UUID getVhostRef() + { + return _vhostRef; + } + + public String getName() + { + return _name; + } + + public Boolean getDurable() + { + return _durable; + } + + public Map getArguments() + { + return _arguments; + } + + public Long getMsgTotalEnqueues() + { + return _msgTotalEnqueues; + } + + public Integer getConsumerCount() + { + return _consumerCount; + } + + public Date getExpireTime() + { + return _expireTime; + } + + public Short getMgmtPubInterval() + { + return _mgmtPubInterval; + } + + public void setExpireTime(Date expireTime) + { + this._expireTime = expireTime; + } + + public void setMgmtPubInterval(Short value) + { + this._mgmtPubInterval = value; + } + + public void setType(String type) + { + this._type = type; + } + + public String getType() + { + return _type; + } + + public byte[] getByteArray() + { + return _byteArray; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java new file mode 100644 index 0000000000..da585a9f43 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/QpidDomainObjectMBean.java @@ -0,0 +1,234 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.net.URI; +import java.util.Date; +import java.util.Map; +import java.util.UUID; + +/** + * Management interface for Qpid domain object. + * + * @author Andrea Gazzarini + */ +public interface QpidDomainObjectMBean +{ + /** + * A method that is throwing an exception, everytime. + * + * @throws Exception each time the method is called. + */ + void throwsException() throws Exception; + + /** + * Sample echo method that return an empty result object. + * That is, an object with only status code / text valorized + * (no output parameters). + * + * @return an empty result object. + */ + InvocationResult voidWithoutArguments(); + + /** + * Echo method that accepts and returns wrapper types. + * + * @param aLong a java.lang.Long + * @param aBoolean a java.lang.Boolean + * @param aDouble a java.lang.Double + * @param aFloat a java.lang.Float + * @param anInteger a java.lang.Integer + * @param aShort a java.lang.Short + * @param aString a java.lang.String + * @param anURI a java.net.URI + * @param aDate a java.util.Date + * @return a result object with the same given parameters (as output parameters) + */ + InvocationResult echoWithSimpleTypes( + Long aLong, + Boolean aBoolean, + Double aDouble, + Float aFloat, + Integer anInteger, + Short aShort, + String aString, + URI anURI, + Date aDate); + + /** + * Echo method that accepts and returns wrapper type arrays . + * + * @param longs an array of java.lang.Long + * @param booleans an array of java.lang.Boolean + * @param doubles an array of java.lang.Double + * @param floats an array of java.lang.Float + * @param integers an array of java.lang.Integer + * @param shorts an array of java.lang.Short + * @param strings an array of java.lang.String + * @param uris an array of java.net.URI + * @param dates an array of java.util.Date + * @return a result object with the same input parameters (as output parameters). + */ + InvocationResult echoWithArrays( + Long [] longs, + Boolean [] booleans, + Double [] doubles, + Float [] floats, + Integer [] integers, + Short [] shorts, + String [] strings, + URI [] uris, + Date [] dates); + + /** + * Echo method that accepts and returns primitive type arrays. + * + * @param longs an array of long. + * @param booleans an array of boolean. + * @param doubles an array of double. + * @param floats an array of float. + * @param integers an array of int. + * @param shorts an array of short. + * @return a result object with the same input parameters (as output parameters). + */ + InvocationResult echoWithSimpleTypeArrays( + long [] longs, + boolean [] booleans, + double [] doubles, + float [] floats, + int [] integers, + short [] shorts); + + /** + * Echo method that accepts and returns a byte array. + * + * @param byteArray a byte array + * @return a result containing the input byte array (as output parameter) + */ + InvocationResult echoWithByteArray(byte [] byteArray); + + /** + * Echo method that accepts and returns an UUID. + * + * @param uuid a java.util.UUID. + * @return a result containing the input UUID (as output parameter) + */ + InvocationResult echoWithUUID(UUID uuid); + + /** + * Echo method that accepts and returns a Map. + * + * @param map a java.util.Map. + * @return a result containing the input Map (as output parameter) + */ + InvocationResult echoWithMap(Map map); + + /** + * Returns the VHostRef property value. + * + * @return the VHostRef property value. + */ + UUID getVhostRef(); + + /** + * Returns the name property value. + * + * @return the name property value. + */ + String getName(); + + /** + * Returns the durable property value. + * + * @return the durable property value. + */ + Boolean getDurable(); + + /** + * Returns the arguments property value. + * + * @return the arguments property value. + */ + Map getArguments(); + + /** + * Returns the msgTotalEnqueues property value. + * + * @return the msgTotalEnqueues property value. + */ + Long getMsgTotalEnqueues(); + + /** + * Returns the consumerCount property value. + * + * @return the consumerCount property value. + */ + Integer getConsumerCount(); + + /** + * Returns the mgmtPubInterval property value. + * + * @return the mgmtPubInterval property value. + */ + Short getMgmtPubInterval(); + + /** + * Sets the mgmtPubInterval property value. + * + * @param the mgmtPubInterval property value. + */ + void setMgmtPubInterval(Short mgmtPubInterval); + + /** + * Returns the expireTime property value. + * + * @return the expireTime property value. + */ + Date getExpireTime(); + + /** + * Sets the expireTime property value. + * + * @return the expireTime property value. + */ + void setExpireTime(Date expireTime); + + /** + * Returns the type property value. + * + * @return the type property value. + */ + void setType(String type); + + /** + * Sets the type property value. + * + * @return the type property value. + */ + String getType(); + +// /** +// * Returns the byteArray property value. +// * +// * @return the byteArray property value. +// */ +// byte[] getByteArray(); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java new file mode 100644 index 0000000000..4564acc9d0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java @@ -0,0 +1,217 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.domain.handler.base.BaseMessageHandler; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.transport.codec.Decoder; + +/** + * Schema Response message handler. + * This handler is responsible to process 'S'(opcode) messages sent by the management broker containing the full + * schema details for a class. + * + * @author Andrea Gazzarini + */ +public class SchemaResponseMessageHandler extends BaseMessageHandler +{ + /** + * Behavioural interface for classes that are responsible to deal with schema messages. + * + * @author Andrea Gazzarini + */ + interface IProcessor + { + /** + * Processes the incoming message using the given decoder. + * + * @param decoder the decoder used for dealing with incoming message. + */ + void process(Decoder decoder); + } + + /** + * Processor responsible to deal with class schema related messages. + */ + final IProcessor _classSchemaProcessor = new IProcessor() + { + public void process(Decoder decoder) + { + try + { + String packageName = decoder.readStr8(); + String className = decoder.readStr8(); + + Binary schemaHash = new Binary(decoder.readBin128()); + + int howManyProperties = decoder.readUint16(); + int howManyStatistics = decoder.readUint16(); + int howManyMethods = decoder.readUint16(); + + _domainModel.addSchema( + packageName, + className, + schemaHash, + getAttributes(decoder, howManyProperties), + getAttributes(decoder, howManyStatistics), + getMethods(decoder, howManyMethods)); + } catch(Exception exception) + { + _logger.error(exception,Messages.QMAN_100005_CLASS_SCHEMA_PROCESSING_FAILURE); + } + } + }; + + /** + * Processor responsible to deal with class event related messages. + */ + final IProcessor _eventSchemaProcessor = new IProcessor() + { + public void process(Decoder decoder) + { + try + { + String packageName = decoder.readStr8(); + String className = decoder.readStr8(); + Binary hash = new Binary(decoder.readBin128()); + int howManyArguments = decoder.readUint16(); + + _domainModel.addEventSchema( + packageName, + className, + hash, + getAttributes(decoder, howManyArguments)); + } catch(Exception exception) + { + _logger.error(exception,Messages.QMAN_100006_EVENT_SCHEMA_PROCESSING_FAILURE); + } + } + }; + + /** + * Processes an incoming schema response. + * This will be used for building the corresponding class definition. + * + * @param decoder the decoder used for parsing the incoming stream. + * @param sequenceNumber the sequence number of the incoming message. + */ + public void process (Decoder decoder, int sequenceNumber) + { + try + { + int classKind = decoder.readUint8(); + switch(classKind) + { + case Protocol.CLASS : + { + _classSchemaProcessor.process(decoder); + break; + } + case Protocol.EVENT : + { + _eventSchemaProcessor.process(decoder); + break; + } + default : + { + _logger.error(Messages.QMAN_100011_UNKNOWN_CLASS_KIND,classKind); + } + } + } catch(Exception exception) + { + _logger.error(exception,Messages.QMAN_100012_SCHEMA_MESSAGE_PROCESSING_FAILURE); + } + } + + /** + * Reads from the incoming message stream the properties definitions. + * + * @param decoder the decoder used for decode incoming data. + * @param howManyProperties the number of properties to read. + * @return a list of maps. Each map contains a property definition. + */ + List> getAttributes(Decoder decoder,int howMany) + { + List> result = new ArrayList>(howMany); + for (int i = 0; i < howMany; i++ ) + { + result.add(decoder.readMap()); + } + return result; + } + + /** + * Reads the methods definitions from the incoming message stream. + * + * @param decoder the decoder used for decode incoming data. + * @param howManyMethods the number of methods to read. + * @return a list method definitions. + */ + List getMethods(Decoder decoder, int howManyMethods) + { + List result = new ArrayList(howManyMethods); + for (int i = 0; i < howManyMethods; i++) + { + Map method = decoder.readMap(); + int howManyArguments = (Integer) method.get(Names.ARG_COUNT_PARAM_NAME); + + List> arguments = new ArrayList>(howManyArguments); + for (int argIndex = 0; argIndex < howManyArguments; argIndex++) + { + arguments.add(decoder.readMap()); + } + result.add(new MethodOrEventDataTransferObject(method,arguments)); + } + return result; + } + + /** + * Reads the events definitions from the incoming message stream. + * + * @param decoder the decoder used for decode incoming data. + * @param howManyEvents the number of events to read. + * @return a list event definitions. + */ + List getEvents(Decoder decoder, int howManyEvents) + { + List result = new ArrayList(howManyEvents); + for (int i = 0; i < howManyEvents; i++) + { + Map method = decoder.readMap(); + int howManyArguments = (Integer) method.get(Names.ARG_COUNT_PARAM_NAME); + + List> arguments = new ArrayList>(howManyArguments); + for (int argIndex = 0; argIndex < howManyArguments; argIndex++) + { + arguments.add(decoder.readMap()); + } + result.add(new MethodOrEventDataTransferObject(method,arguments)); + } + return result; + } + } diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java new file mode 100644 index 0000000000..6d1426c122 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Enumeration for Access modes. + * + * @author Andrea Gazzarini + */ +public enum AccessMode +{ + RC { @Override public String toString() { return "Read-Create"; }}, + RO { @Override public String toString() { return "Read-Only"; }}, + RW { @Override public String toString() { return "Read-Write"; }} +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java new file mode 100644 index 0000000000..8166c35eb6 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Enumeration of allowed method argument direction codes. + * + * @author Andrea Gazzarini + */ +public enum Direction +{ + I{ @Override public String toString() { return "Input"; }}, + O{ @Override public String toString() { return "Output"; }}, + IO{ @Override public String toString() { return "Input-Output"; }}; +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java new file mode 100644 index 0000000000..5a0ebaf1f7 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java @@ -0,0 +1,239 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Broker domain model. + * This is the local representation of a remote broker domain model. + * + * @author Andrea Gazzarini + */ +public class DomainModel +{ + private final UUID _id; + + /** Here the known packages of the remote broker are stored. */ + Map _packages = new HashMap(); + + private Date _lastRefreshDate = new Date(); + + private IMethodInvocationListener _methodInvocationListener; + + /** + * Builds a new domain model with the given broker identifier. + * + * @param brokerId the broker identifier. + */ + public DomainModel(UUID brokerId) + { + this._id = brokerId; + } + + /** + * Returns the identifier of the broker associated with this domain model. + * + * @return the identifier of the broker associated with this domain model. + */ + public UUID getBrokerId() + { + return _id; + } + + /** + * Adds the specified schema to this domain model. + * + * @param packageName the package name. + * @param className the class name. + * @param classHash the class schema hash. + * @param properties the class properties. + * @param statistics the class statistics. + * @param methods the class methods. + * @throws UnableToBuildFeatureException + */ + public void addSchema( + String packageName, + String className, + Binary classHash, + List> properties, + List> statistics, + List methods) throws UnableToBuildFeatureException + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.addClassDefinition(className,classHash,properties,statistics,methods); + } + + /** + * Updates the last refresh date. + */ + public void updateLastRefreshDate() + { + this._lastRefreshDate = new Date(); + } + + /** + * Returns the last refresh date. + * + * @return the last refresh date. + */ + public Date getLastRefreshDate() + { + return _lastRefreshDate; + } + + /** + * Adds the specified schema to this domain model. + * + * @param packageName the package name. + * @param className the class name. + * @param classHash the class schema hash. + * @param properties the class properties. + * @param statistics the class statistics. + * @param methods the class methods. + * @throws UnableToBuildFeatureException + */ + public void addEventSchema( + String packageName, + String className, + Binary classHash, + List> arguments) throws UnableToBuildFeatureException + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.addEventDefinition(className,classHash,arguments); + } + + /** + * Gets the package with the specified name. + * Note that if the package doesn't exist a new one will be created and returned. + * + * @param packageName the name of the package. + * @return the package. + */ + QpidPackage getPackageByName (String packageName) + { + QpidPackage qpidPackage = _packages.get(packageName); + if (qpidPackage == null) + { + qpidPackage = new QpidPackage(packageName,this); + _packages.put(packageName, qpidPackage); + } + return qpidPackage; + } + + /** + * Returns true if a package with the specified name already exists on this domain model. + * + * @param packageName the name of the package. + * @return true if the package exists, false otherwise. + */ + boolean containsPackage (String packageName) + { + return _packages.containsKey(packageName); + } + + /** + * Adds the given instrumentation data (raw format) to this domain model. + * Note that this data is belonging to a specific object instance. + * + * @param packageName the name of the ower package. + * @param className the name of the owner class. + * @param classHash the schema hash for this class. + * @param objectId the object instance identifier. + * @param rawData the instrumentation data. + */ + public void addInstrumentationRawData (String packageName, String className,Binary classHash, Binary objectId, byte[] rawData) + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.setObjectInstanceInstrumentationRawData(className,classHash,objectId,rawData); + } + + public void addEventRawData ( + String packageName, + String eventName, + Binary eventHash, + byte[] rawData, + long currentTimestamp, + int severity) + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.setEventInstanceRawData(eventName,eventHash,rawData,currentTimestamp,severity); + } + + /** + * Adds the given configuration data (raw format) to this domain model. + * Note that this data is belonging to a specific object instance. + * + * @param packageName the name of the ower package. + * @param className the name of the owner class. + * @param classHash the schema hash for this class. + * @param objectId the object instance identifier. + * @param rawData the configuration data. + */ + public void addConfigurationRawData (String packageName, String className, Binary classHash,Binary objectId, byte[] rawData) + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.setObjectInstanceConfigurationRawData(className,classHash,objectId,rawData); + } + + /** + * Removes the object instance associated to the given parameters. + * + * @param packageName the owner package. + * @param className the class definition of the object instance. + * @param classHash the class hash + * @param objectId the object identifier. + */ + public void removeObjectInstance (String packageName, String className, Binary classHash, Binary objectId) + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.removeObjectInstance(className, classHash, objectId); + } + + /** + * Releases all the resources kept by domain model entitiies. + */ + public void releaseResources() + { + for (QpidPackage qpidPackage : _packages.values()) + { + qpidPackage.releaseResources(); + } + } + + public void setMethodInvocationListener(IMethodInvocationListener listener) + { + this._methodInvocationListener = listener; + } + + IMethodInvocationListener getMethodInvocationListener () + { + return _methodInvocationListener; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java new file mode 100644 index 0000000000..1ede559145 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java @@ -0,0 +1,38 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Interface definition for attribute validators. + * + * @author Andrea Gazzarini + */ +interface IValidator +{ + /** + * Validates the given value according to the rules definied by this validator. + * + * @param value the value be checked. + * + * @throws ValidationException when the value is violating validator's rules. + */ + void validate(Object value) throws ValidationException; +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java new file mode 100644 index 0000000000..d84a018346 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/InvocationEvent.java @@ -0,0 +1,76 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.EventObject; +import java.util.concurrent.BlockingQueue; + +import org.apache.qpid.management.domain.handler.impl.InvocationResult; + +/** + * Operation invocation event. + * This encapsulates all the information that a method invocation listener needs to know about an operation which is + * going to be invoked. + * + * @author Andrea Gazzarini + */ +public class InvocationEvent extends EventObject +{ + private static final long serialVersionUID = 240229490753008597L; + + private final int _sequenceNumber; + private final BlockingQueue _exchangeChannel; + + /** + * Builds a new invocation event with the given data. + * + * @param source the event source. + * @param sequenceNumber the sequence number of the method invocation. + * @param exchangeChannel the exchange channel for synchronous communication. + */ + InvocationEvent(Object source, int sequenceNumber, BlockingQueue exchangeChannel) + { + super(source); + this._sequenceNumber = sequenceNumber; + this._exchangeChannel = exchangeChannel; + } + + /** + * Returns the sequence number that will be / has been used for method invocation. + * + * @return the sequence number that will be / has been used for method invocation. + */ + public int getSequenceNumber() + { + return _sequenceNumber; + } + + /** + * Returns the exchange channel that will be used between event source and event listener for synchronous + * communication. + * + * @return the exchange channel that will be used for synchronous communication. + */ + public BlockingQueue getExchangeChannel() + { + return _exchangeChannel; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java new file mode 100644 index 0000000000..657d7e6210 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java @@ -0,0 +1,410 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.lang.management.ManagementFactory; +import java.util.Set; +import java.util.UUID; + +import javax.management.MBeanException; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.model.QpidClass.QManManagedObject; +import org.apache.qpid.management.domain.model.QpidEvent.QManManagedEvent; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.management.domain.services.QMan; +import org.apache.qpid.transport.util.Logger; + +/** + * A simple facade used to perform operations on Mbean server. + */ +public class JmxService +{ + private final static Logger LOGGER = Logger.get(JmxService.class); + MBeanServer _mxServer = ManagementFactory.getPlatformMBeanServer(); + + /** + * Registers QMan with the MBeanServer. + * After that QMan management interface will be JMX-exposed. + * + * @param qman QMan + * @throws MBeanException when some error occurs during registration. + */ + public void registerQManService(QMan qman) throws MBeanException + { + if (!_mxServer.isRegistered(Names.QMAN_OBJECT_NAME)) + { + try { + _mxServer.registerMBean(qman, Names.QMAN_OBJECT_NAME); + } catch (Exception exception) { + throw new MBeanException(exception); + } + } + } + + /** + * Registers an event instance with MBean server. + * + * @param eventInstance the mben event instance + * @param brokerId the broker identifier. + * @param packageName the package name. + * @param eventClassName the event class name. + * @return the object name used for registration. + */ + ObjectName registerEventInstance( + QManManagedEvent eventInstance, + UUID brokerId, + String packageName, + String eventClassName) + { + ObjectName name = createEventName(brokerId, packageName, eventClassName); + if (!_mxServer.isRegistered(name)) + { + try + { + _mxServer.registerMBean(eventInstance, name); + + LOGGER.debug( + Messages.QMAN_200010_EVENT_MBEAN_REGISTERED, + brokerId, + packageName, + eventClassName, + name); + } catch (Exception exception) + { + throw new RuntimeException(exception); + } + } + return name; +} + + /** + * Registers a pre-existing object instance as an MBean with the MBean + * server. + * + * @param instance the object instance. + * @param brokerId the broker identifier. + * @param packageName the name of the package containing this instance. + * @param className the name of the owner class of this instance. + * @param objectId the object instance identifier. + * @return the object name used for registration. + */ + ObjectName registerObjectInstance( + QManManagedObject instance, + UUID brokerId, + String packageName, + String className, + Binary objectId) + { + ObjectName name = createObjectName(brokerId, packageName, className, objectId); + if (!_mxServer.isRegistered(name)) + { + try + { + _mxServer.registerMBean(instance, name); + + LOGGER.debug( + Messages.QMAN_200011_OBJECT_MBEAN_REGISTERED, + brokerId, + packageName, + className, + objectId, + name); + } catch (Exception exception) + { + throw new RuntimeException(exception); + } + } + return name; + } + + /** + * Removes / unregisters a managed object instance from the MBean Server. + * + * @param brokerId the broker identifier. + * @param packageName the name of the package containing this instance. + * @param className the name of the owner class of this instance. + * @param objectId the object instance identifier. + * @return obejctName the obejct name used for deregistration. + */ + ObjectName unregisterObjectInstance( + UUID brokerId, + String packageName, + String className, + Binary objectId) + { + ObjectName name = createObjectName(brokerId, packageName, className, objectId); + if (_mxServer.isRegistered(name)) + { + try + { + _mxServer.unregisterMBean(name); + + LOGGER.debug( + Messages.QMAN_200012_OBJECT_MBEAN_UNREGISTERED, + brokerId, + packageName, + className, + objectId, + name); + } catch (Exception exception) + { + LOGGER.error(exception,Messages.QMAN_100013_MBEAN_REGISTRATION_FAILURE,name); + } + } + return name; + } + + /** + * Removes (unregister) all events from MBean Server. + */ + void unregisterEvents() + { + for (ObjectName name : getEventMBeans()) + { + try + { + _mxServer.unregisterMBean(name); + } catch(Exception ignore) + { + } + } + } + + @SuppressWarnings("unchecked") + Set getEventMBeans() + { + return _mxServer.queryNames(createEventSearchName(),null); + } + + /** + * Removes (unregister) all object instances from MBean Server. + */ + @SuppressWarnings("unchecked") + void unregisterObjectInstances() + { + Set names = _mxServer.queryNames(createObjectInstanceSearchName(),null); + for (ObjectName name : names) + { + try + { + _mxServer.unregisterMBean(name); + } catch(Exception ignore) + { + } + } + } + + /** + * Factory method for ObjectNames. + * + * @param brokerId the broker identifier. + * @param packageName the name of the package containing this instance. + * @param className the name of the owner class of this instance. + * @param objectId the object instance identifier. + * @return the object name built according to the given parameters. + */ + private ObjectName createObjectName(UUID brokerId, String packageName, String className, Binary objectId) + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append(Names.BROKER_ID) + .append('=') + .append(brokerId) + .append(",type=Object,") + .append(Names.PACKAGE) + .append('=') + .append(packageName) + .append(',') + .append(Names.CLASS) + .append('=') + .append(className) + .append(',') + .append(Names.OBJECT_ID) + .append('=') + .append(objectId) + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Creates an object name that will be used for searching all registered events. + * + * @return the object name that will be used for searching all registered events. + */ + ObjectName createEventSearchName() + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append('*') + .append(",type=Event") + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Creates an object name that will be used for searching all registered events. + * + * @return the object name that will be used for searching all registered events. + */ + ObjectName createClassDefinitionSearchName() + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(":Category=Schema,*") + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Creates an object name that will be used for searching all registered object instances. + * + * @return the object name that will be used for searching all registered object instances. + */ + private ObjectName createObjectInstanceSearchName() + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append('*') + .append(",type=Object") + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Factory method for ObjectNames. + * + * @param brokerId the broker identifier. + * @param packageName the name of the package containing this instance. + * @param className the name of the owner class of this instance. + * @return the object name built according to the given parameters. + */ + private ObjectName createEventName(UUID brokerId, String packageName, String className) + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append(Names.BROKER_ID) + .append('=') + .append(brokerId) + .append(",type=Event,") + .append(Names.PACKAGE) + .append('=') + .append(packageName) + .append(',') + .append(Names.CLASS) + .append('=') + .append(className) + .append(',') + .append(Names.OBJECT_ID) + .append('=') + .append(UUID.randomUUID()) + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + ObjectName createEntityDefinitionName(String packageName, String className, String type) + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append("Category=Schema,Type=") + .append(type) + .append(",package=") + .append(packageName) + .append(",name=") + .append(className) + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + public void registerEntityDefinition(ObjectName name, QpidEntity entity,String packageName, String className) + { + try + { + if (!_mxServer.isRegistered(name)) + _mxServer.registerMBean(entity, name); + _mxServer.addNotificationListener(name, Names.QMAN_OBJECT_NAME, null, null); + } catch(Exception exception) + { + throw new RuntimeException(exception); + } + } + + @SuppressWarnings("unchecked") + public void unregisterClassDefinitions() + { + Set names = _mxServer.queryNames(createClassDefinitionSearchName(),null); + for (ObjectName name : names) + { + try + { + _mxServer.unregisterMBean(name); + } catch(Exception ignore) + { + } + } + + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java new file mode 100644 index 0000000000..160054059b --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java @@ -0,0 +1,35 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.List; + +import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute; + +public class MissingFeatureAttributesException extends UnableToBuildFeatureException +{ + private static final long serialVersionUID = 671471705085787235L; + + public MissingFeatureAttributesException(List missingAttributeList) + { + super(String.valueOf(missingAttributeList)); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java new file mode 100644 index 0000000000..e126fcb8f5 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java @@ -0,0 +1,123 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.transport.codec.Encoder; +import org.apache.qpid.transport.util.Logger; + +/** + * An argument is the formal definition of a parameter belonging to a specific method / operation. + */ +class QpidArgument extends QpidProperty +{ + private final static Logger LOGGER = Logger.get(QpidArgument.class); + + private Object _defaultValue; + + private Direction _direction; + + /** + * Sets the direction of this argument. + * + * @param the direction of this argument. + */ + public void setDirection(String code) + { + this._direction = Direction.valueOf(code); + } + + /** + * Returns the direction of this argument. + * + * @return the direction of this argument. + */ + public Direction getDirection() + { + return _direction; + } + + /** + * Sets the default value of this argument. + * + * @param defaultValue the default value of this argument. + */ + public void setDefaultValue(Object defaultValue) + { + this._defaultValue = defaultValue; + } + + /** + * Returns the default value of this argument. + * + * @return the default value of this argument. + */ + public Object getDefaultValue() + { + return _defaultValue; + } + + /** + * Returns true if this is an Input argument. + * + * @return true if this is an Input argument. + */ + public boolean isInput() + { + return _direction != Direction.O; + } + + @Override + public String toString () + { + return new StringBuilder() + .append(getJavaType().getName()) + .append(' ') + .append(_name) + .append("(") + .append(_direction) + .append(")") + .toString(); + } + + /** + * Encodes the given value according to this argument type & definition. + * + * @param value the value to be encoded. + * @param encoder the encoder. + */ + public void encode(Object value,Encoder encoder) + { + _type.encode(value, encoder); + LOGGER.debug(Messages.QMAN_200013_ARGUMENT_VALUE_ENCODED,value,_name,_type); + } + + /** + * Decodes the value for this argument according to its type & definition. + * + * @param decoder the decoder + * @return the decoded value of this argument. + */ + public Object decode(org.apache.qpid.transport.codec.Decoder decoder) + { + return _type.decode(decoder); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java new file mode 100644 index 0000000000..6712a14075 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.domain.model.type.Type; +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.util.Logger; + +/** + * Layer supertype for qpid properties and statistics. + * + * @author Andrea Gazzarini + */ +class QpidAttribute extends QpidFeature +{ + private final static Logger LOGGER = Logger.get(QpidAttribute.class); + + /** feature type */ + protected Type _type; + + /** feature unit */ + protected String _unit; + + /** + * Returns the units used for numeric values (i.e. seconds, bytes, etc.) + * + * @return the units used for numeric values (i.e. seconds, bytes, etc.) + */ + String getUnit () + { + return _unit; + } + + /** + * Sets the unit for this property. + * + * @param unit the unit of this property. + */ + void setUnit (String unit) + { + this._unit = unit; + } + + /** + * Returns the java type (class) of this feature. + * + * @return the java type (class) of this feature. + */ + Class getJavaType () + { + return _type.getJavaType(); + } + + /** + * Sets the type of this feature. + * + * @param type the type of this feature. + */ + void setType (Type type) + { + this._type = type; + } + + /** + * Gets the value of this feature according to its type definition. + * + * @param decoder the decoder used to extract the value. + * @return the value of this feature according to its type definition + */ + Object decodeValue(Decoder decoder) + { + try { + return _type.decode(decoder); + } catch(RuntimeException exception) + { + LOGGER.error(exception,Messages.QMAN_100014_ATTRIBUTE_DECODING_FAILURE,this); + throw exception; + } + } + + @Override + public String toString () + { + return super.toString()+",type="+_type; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java new file mode 100644 index 0000000000..667e600668 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java @@ -0,0 +1,833 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.Map.Entry; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.InvalidAttributeValueException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanRegistration; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.ReflectionException; +import javax.management.RuntimeOperationsException; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener; +import org.apache.qpid.management.domain.handler.impl.InvocationResult; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.management.domain.services.SequenceNumberGenerator; +import org.apache.qpid.management.jmx.EntityLifecycleNotification; +import org.apache.qpid.management.jmx.OperationHasBeenInvokedNotification; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.util.Logger; + +/** + * Qpid Class definition. + * A type definition for a manageable object. + * This class is also responsible to manage incoming obejct instance data (configuration & instrumentation). + * How can we handle data before schema is injected into this class? simply we must retain that data in raw format. + * This class has 3 states : + * 1) first state is when schema is not yet injected. In this case the incoming object data is retained as is (in raw format) + * and a schema request is sent; + * 2) second state is when schema has been requested but not yet injected. The incoming object data is still retained as is + * (in raw format) + * 3) third state is when schema is injected. Each injection of data will result in an update / create / delete of + * the corresponding object instance. In addition, the first time the state change, the old retained raw data is cnverted in + * object instance(s). + */ +class QpidClass extends QpidEntity implements QpidClassMBean +{ + /** + * State interface for this class definition. + * Each state is responsible to handle the injection of the data and / or schema. + * + * @author Andrea Gazzarini + */ + interface State + { + /** + * Adds configuration data for the object instance associated to the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the raw configuration data. + */ + void addInstrumentationData (Binary objectId, byte[] rawData); + + /** + * Adds instrumentation data for the object instance associated to the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the raw instrumentation data. + */ + void addConfigurationData (Binary objectId, byte[] rawData); + + /** + * Inject the schema into this class definition. + * + * @param propertyDefinitions + * @param statisticDefinitions + * @param methodDefinitions + * @throws UnableToBuildFeatureException when it's not possibile to parse schema and build the class definition. + */ + public void setSchema ( + List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException; + }; + + /** + * This is the initial state of every qpid class. + * The class definition instance is created but its schema has not been injected. + * Incoming configuration & instrumentation data will be stored in raw format because we don't know how to + * parse it until the schema arrives. + * In addition, this state is responsible (when data arrives) to request its schema. + */ + final State _schemaNotRequested = new State() { + + /** + * Stores the incoming data in raw format and request the schema for this class. + * After that a transition to the next state is made. + * + * @param objectId the object instance identifier. + * @param rawData incoming configuration data. + */ + public synchronized void addConfigurationData (Binary objectId, byte[] rawData) + { + try + { + requestSchema(); + _state = _schemaRequestedButNotYetInjected; + } catch (Exception exception) + { + _logger.error( + exception, + Messages.QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST, + _parent.getName(), + _name); + } finally { + QManManagedObject instance = getObjectInstance(objectId,false); + instance._rawConfigurationData.add(rawData); + } + } + + /** + * Stores the incoming data in raw format and request the schema for this class. + * After that a transition to the next state is made. + * + * @param objectId the object instance identifier. + * @param rawData incoming instrumentation data. + */ + public synchronized void addInstrumentationData (Binary objectId, byte[] rawData) + { + try + { + requestSchema(); + _state = _schemaRequestedButNotYetInjected; + } catch (Exception e) + { + _logger.error( + Messages.QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST, + _parent.getName(), + _name); + } finally { + QManManagedObject instance = getObjectInstance(objectId,false); + instance._rawConfigurationData.add(rawData); + } + } + + /** + * This method only throws an illegal state exception because when a schema arrives + * this state is no longer valid. + */ + public void setSchema ( + List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException + { + throw new IllegalStateException("When a schema arrives it's not possible for this class to be in this state."); + } + }; + + /** + * This is the first state of this class definition : the schema is not yet injected so each injection of object data will be + * retained in raw format. + */ + final State _schemaRequestedButNotYetInjected = new State() + { + /** + * Stores the incoming data in raw format. + * + * @param objectId the object instance identifier. + * @param rawData incoming configuration data. + */ + public void addConfigurationData (Binary objectId, byte[] rawData) + { + QManManagedObject instance = getObjectInstance(objectId,false); + instance._rawConfigurationData.add(rawData); + } + + /** + * Stores the incoming data in raw format. + * + * @param objectId the object instance identifier. + * @param rawData incoming instrumentation data. + */ + public void addInstrumentationData (Binary objectId, byte[] rawData) + { + QManManagedObject instance = getObjectInstance(objectId,false); + instance._rawInstrumentationData.add(rawData); + } + + /** + * When a schema is injected into this defintiion the following should happen : + * 1) the incoming schema is parsed and the class definition is built; + * 2) the retained raw data is converted into object instance(s) + * 3) the internal state of this class changes; + * + * If someting is wrong during that process the schema is not built and the state don't change. + */ + public synchronized void setSchema ( + List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException + { + + MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[propertyDefinitions.size()+statisticDefinitions.size()]; + MBeanOperationInfo [] operationsMetadata = new MBeanOperationInfo[methodDefinitions.size()]; + + buildAttributes(propertyDefinitions,statisticDefinitions,attributesMetadata); + buildMethods(methodDefinitions,operationsMetadata); + + _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,operationsMetadata,null); + + EntityLifecycleNotification notification = new EntityLifecycleNotification( + EntityLifecycleNotification.SCHEMA_INJECTED_NOTIFICATION_TYPE, + _parent.getName(), + _name, + Names.CLASS, + _objectName); + + sendNotification(notification); + + // Converting stored object instances into JMX MBean and removing raw instance data. + for (Entry instanceEntry : _objectInstances.entrySet()) + { + Binary objectId = instanceEntry.getKey(); + QManManagedObject instance = instanceEntry.getValue(); + + for (Iterator iterator = instance._rawInstrumentationData.iterator(); iterator.hasNext();) + { + updateInstanceWithInstrumentationData(instance,iterator.next()); + iterator.remove(); + } + + for (Iterator iterator = instance._rawConfigurationData.iterator(); iterator.hasNext();) + { + updateInstanceWithConfigurationData(instance, iterator.next()); + iterator.remove(); + } + + registerMBean(instance,_parent.getOwnerId(),_parent.getName(),_name,objectId); + } + _state = _schemaInjected; + + } + }; + + /** + * After a schema is built into this definition this is the current state of the class. + */ + final State _schemaInjected = new State() + { + /** + * Updates the configuration state of the object instance associates with the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the configuration data (raw format). + */ + public void addConfigurationData (Binary objectId, byte[] rawData) + { + QManManagedObject instance = getObjectInstance(objectId,true); + updateInstanceWithConfigurationData(instance, rawData); + } + + /** + * Updates the instrumentation state of the object instance associates with the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the instrumentation data (raw format). + */ + public void addInstrumentationData (Binary objectId, byte[] rawData) + { + QManManagedObject instance = getObjectInstance(objectId,true); + updateInstanceWithInstrumentationData(instance, rawData); + } + + /** + * Never called when the class definition has this state. + */ + public void setSchema ( + List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException + { + throw new IllegalStateException("When a schema arrives it's not possible for this class to be in this state."); + } + }; + + /** + * MBean used for representing remote broker object instances. + * This is the core component of the QMan domain model + */ + class QManManagedObject extends QManManagedEntity implements MBeanRegistration + { + private Binary _objectId; + + // Arrays used for storing raw data before this mbean is registered to mbean server. + List _rawInstrumentationData = new ArrayList(); + List _rawConfigurationData = new ArrayList(); + + /** + * Builds a new managed object with the given object identifier. + * + * @param objectId the object identifier. + */ + QManManagedObject(Binary objectId) + { + this._objectId = objectId; + } + + /** + * Returns the value of the given attribute.s + * + * @throws AttributeNotFoundException when no attribute is found with the given name. + */ + public Object getAttribute (String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException + { + if (attributeName == null) + { + throw new RuntimeOperationsException(new IllegalArgumentException("attribute name must not be null")); + } + + if (_properties.containsKey(attributeName) || _statistics.containsKey(attributeName)) + { + return _attributes.get(attributeName); + } else + { + throw new AttributeNotFoundException(attributeName); + } + } + + /** + * Executes an operation on this object instance. + * + * @param actionName the name of the method. + * @param params the method parameters + * @param signature the method signature. + */ + public Object invoke (String actionName, Object[] params, String[] signature) throws MBeanException,ReflectionException + { + OperationHasBeenInvokedNotification notification = null; + try + { + QpidMethod method = _methods.get(actionName); + if (method != null) + { + try + { + method.validate(params); + InvocationResult result = invokeMethod(_objectId, method, params); + notification = new OperationHasBeenInvokedNotification(actionName,params,signature,result); + return result; + } catch (Exception ex) + { + MBeanException exception = new MBeanException(ex); + notification = new OperationHasBeenInvokedNotification(actionName,params,signature,exception); + throw exception; + } + } else + { + ReflectionException exception = new ReflectionException(new NoSuchMethodException(actionName)); + notification = new OperationHasBeenInvokedNotification(actionName,params,signature,exception); + throw exception; + } + } finally + { + sendNotification(notification); + } + } + + /** + * Sets the value of the given attribute on this object instance. + * + * @param attribute contains the new value of the attribute. + * @throws AttributeNotFoundException when the given attribute is not found on this object instance. + * @throws InvalidAttributeValueException when the given value is violating one attribute invariant. + */ + public void setAttribute (Attribute attribute) throws AttributeNotFoundException, + InvalidAttributeValueException, MBeanException, ReflectionException + { + QpidProperty property = _properties.get(attribute.getName()); + try + { + property.validate(attribute.getValue()); + } catch(ValidationException exception) + { + throw new InvalidAttributeValueException(exception.getMessage()); + } + throw new RuntimeException("Not yet implemented."); + } + + /** + * Sets the values of several attributes of this MBean. + * + * @param attributes a list of attributes: The identification of the attributes to be set and the values they are to be set to. + * @return The list of attributes that were set, with their new values. + */ + public AttributeList setAttributes (AttributeList attributes) + { + throw new RuntimeException("Not yet implemented."); + } + + /** + * MBean server callback after deregistration. + */ + public void postDeregister () + { + } + + /** + * After the object is registered the raw data is set to null. + * This is done because we no longer need this data : it has already been + * injected into this object instance. + * + * @param registrationDone a flag indicating if the instance has been registered to mbean server. + */ + public void postRegister (Boolean registrationDone) + { + if (registrationDone) + { + _rawConfigurationData = null; + _rawInstrumentationData = null; + } + } + + /** + * MBean server callback before deregistration. + */ + public void preDeregister () throws Exception + { + } + + /** + * MBean server callback before registration. + */ + public ObjectName preRegister (MBeanServer server, ObjectName name) throws Exception + { + return name; + } + } + + Map _properties = new HashMap(); + Map _statistics = new HashMap(); + private Map _methods = new HashMap(); + + private List _schemaOrderedProperties = new ArrayList(); + private List _schemaOrderedStatistics= new ArrayList(); + + private int _howManyPresenceBitMasks; + private BlockingQueue _exchangeChannelForMethodInvocations; + private final IMethodInvocationListener _methodInvocationListener; + + Map _objectInstances = new HashMap(); + State _state = _schemaNotRequested;; + + private final static class Log + { + private final static Logger LOGGER = Logger.get(QpidClass.class); + final static void logMethodInvocationResult(InvocationResult result) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(String.valueOf(result)); + } + } + } + + /** + * Builds a new class with the given name and package as parent. + * + * @param className the name of the class. + * @param hash the class schema hash. + * @param parentPackage the parent of this class. + */ + QpidClass(String className, Binary hash, QpidPackage parentPackage) + { + super(className,hash, parentPackage,Names.CLASS); + this._methodInvocationListener = _parent.getMethodInvocationListener(); + this._exchangeChannelForMethodInvocations = new SynchronousQueue(); + } + + /** + * Adds the configuration data for the object instance associated to the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the raw configuration data. + */ + void addInstrumentationData (Binary objectId, byte[] rawData) + { + _logger.debug( + Messages.QMAN_200014_INCOMING_INSTRUMENTATION_DATA, + _parent.getOwnerId(), + _parent.getName(), + _name, + objectId); + _state.addInstrumentationData(objectId, rawData); + } + + /** + * Adds the instrumentation data for the object instance associated to the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the raw instrumentation data. + */ + void addConfigurationData (Binary objectId, byte[] rawData) + { + _logger.debug( + Messages.QMAN_200015_INCOMING_CONFIGURATION_DATA, + _parent.getOwnerId(), + _parent.getName(), + _name, + objectId); + _state.addConfigurationData(objectId, rawData); + } + + /** + * Sets the schema for this class definition. + * A schema is basically a metadata description of all properties, statistics, methods and events of this class. + * + * @param propertyDefinitions properties metadata. + * @param statisticDefinitions statistics metadata. + * @param methodDefinitions methods metadata. + * @throws UnableToBuildFeatureException when some error occurs while parsing the incoming schema. + */ + void setSchema ( + List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException + { + _logger.info(Messages.QMAN_000010_INCOMING_SCHEMA,_parent.getOwnerId(),_parent.getName(),_name); + _state.setSchema(propertyDefinitions, statisticDefinitions, methodDefinitions); + } + + /** + * Internal method used for building attributes definitions. + * + * @param props the map contained in the properties schema. + * @param stats the map contained in the statistics schema. + * @param attributes the management metadata for attributes. + * @throws UnableToBuildFeatureException when it's not possibile to build one attribute definition. + */ + void buildAttributes ( + List> props, + List> stats, + MBeanAttributeInfo[] attributes) throws UnableToBuildFeatureException + { + int index = 0; + int howManyOptionalProperties = 0; + + for (Map propertyDefinition : props) + { + QpidFeatureBuilder builder = QpidFeatureBuilder.createPropertyBuilder(propertyDefinition); + builder.build(); + + QpidProperty property = (QpidProperty) builder.getQpidFeature(); + + howManyOptionalProperties += (property.isOptional()) ? 1 : 0; + + _properties.put(property.getName(),property); + _schemaOrderedProperties.add(property); + attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature(); + + _logger.debug( + Messages.QMAN_200016_PROPERTY_DEFINITION_HAS_BEEN_BUILT, + _parent.getName(), + _name, + property); + } + + _howManyPresenceBitMasks = (int)Math.ceil((double)howManyOptionalProperties / 8); + + _logger.debug( + Messages.QMAN_200018_OPTIONAL_PROPERTIES_INFO, + _parent.getOwnerId(), + _parent.getName(), + _name, + _howManyPresenceBitMasks); + + for (Map statisticDefinition : stats) + { + QpidFeatureBuilder builder = QpidFeatureBuilder.createStatisticBuilder(statisticDefinition); + builder.build(); + QpidStatistic statistic = (QpidStatistic) builder.getQpidFeature(); + + _statistics.put(statistic.getName(),statistic); + _schemaOrderedStatistics.add(statistic); + attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature(); + + _logger.debug( + Messages.QMAN_200017_STATISTIC_DEFINITION_HAS_BEEN_BUILT, + _parent.getName(), + _name, + statistic); + } + } + + /** + * Returns the object instance associated to the given identifier. + * Note that if the identifier is not associated to any obejct instance, a new one will be created. + * + * @param objectId the object identifier. + * @param registration a flag indicating whenever the (new ) instance must be registered with MBean server. + * @return the object instance associated to the given identifier. + */ + QManManagedObject getObjectInstance(Binary objectId, boolean registration) + { + QManManagedObject objectInstance = _objectInstances.get(objectId); + if (objectInstance == null) + { + objectInstance = new QManManagedObject(objectId); + _objectInstances.put(objectId, objectInstance); + if (registration) + { + registerMBean(objectInstance,_parent.getOwnerId(),_parent.getName(),_name,objectId); + } + } + return objectInstance; + } + + /** + * Internal method used for building method defintiions. + * + * @param definitions the properties map contained in the incoming schema. + * @param operationsMetadata + * @throws UnableToBuildFeatureException when it's not possibile to build one or more definitions. + */ + void buildMethods (List definitions, MBeanOperationInfo[] operationsMetadata) throws UnableToBuildFeatureException + { + int index = 0; + for (MethodOrEventDataTransferObject definition: definitions) + { + QpidFeatureBuilder builder = QpidFeatureBuilder.createMethodBuilder(definition); + builder.build(); + operationsMetadata [index++]= (MBeanOperationInfo) builder.getManagementFeature(); + QpidMethod method = (QpidMethod) builder.getQpidFeature(); + _methods.put(method.getName(),method); + } + } + + /** + * Header (opcode='M') + * ObjectId of target object (128 bits) + * Package name (str8) + * Class name (str8) + * Class hash (bin128) + * Method name (str8) [as defined in the schema] + * Now encode all input ("I") and i/o (IO) arguments in the order in which they are defined in the schema. + * (i.e. make one pass over the argument list and encode arguments that are either input or inptu/output). + + * @param objectId + * @param method + * @param parameters + * @throws Exception + */ + private InvocationResult invokeMethod(Binary objectId,QpidMethod method,Object [] parameters) throws Exception + { + try + { + _service.connect(); + + int sequenceNumber = SequenceNumberGenerator.getNextSequenceNumber(); + _methodInvocationListener.operationIsGoingToBeInvoked(new InvocationEvent(this,sequenceNumber,_exchangeChannelForMethodInvocations)); + _service.invoke(_parent.getName(), _name, _hash,objectId,parameters, method,sequenceNumber,objectId.getBankId(),objectId.getBrokerId()); + + InvocationResult result = _exchangeChannelForMethodInvocations.poll(5000,TimeUnit.MILLISECONDS); + + if (result == null) + { + throw new TimeoutException(); + } + + Map output = method.decodeParameters(result.getOutputAndBidirectionalArgumentValues()); + result.setOutputSection(output); + + Log.logMethodInvocationResult(result); + + if (result.isException()) + { + result.createAndThrowException(); + } + return result; + } finally + { + _service.close(); + } + } + + /** + * Updates the given obejct instance with the given incoming configuration data. + * + * @param instance the managed object instance. + * @param rawData the incoming configuration data which contains new values for instance properties. + */ + void updateInstanceWithConfigurationData(QManManagedObject instance,byte [] rawData) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(rawData)); + + byte [] presenceBitMasks = decoder.readBytes(_howManyPresenceBitMasks); + for (QpidProperty property : _schemaOrderedProperties) + { + try { + Object value = property.decodeValue(decoder,presenceBitMasks); + instance.createOrReplaceAttributeValue(property.getName(),value); + } catch(Exception ignore) { + _logger.error(Messages.QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE, _parent.getName(),_name,property.getName()); + } + } + } + + /** + * Updates the given object instance with the given incoming instrumentation data. + * + * @param instance the managed object instance. + * @param rawData the incoming instrumentation data which contains new values for instance properties. + */ + void updateInstanceWithInstrumentationData(QManManagedObject instance,byte [] rawData) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(rawData)); + + for (QpidStatistic statistic : _schemaOrderedStatistics) + { + try { + Object value = statistic.decodeValue(decoder); + instance.createOrReplaceAttributeValue(statistic.getName(),value); + } catch(Exception ignore) { + _logger.error(Messages.QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE, _parent.getName(),_name,statistic.getName()); + } + } + } + + @Override + public String toString () + { + return new StringBuilder() + .append(_parent.getOwnerId()) + .append("::") + .append(_parent.getName()) + .append('.') + .append(_name) + .toString(); + } + + /** + * Removes the object instance associated to the given identifier. + * + * @param objectId the object identifier. + */ + void removeObjectInstance (Binary objectId) + { + QManManagedObject toBeRemoved = _objectInstances.remove(objectId); + if (toBeRemoved != null) + { + ObjectName objectName = JMX_SERVICE.unregisterObjectInstance(_parent.getOwnerId(),_parent.getName(),_name,toBeRemoved._objectId); + + EntityLifecycleNotification notification = new EntityLifecycleNotification( + EntityLifecycleNotification.INSTANCE_REMOVED_NOTIFICATION_TYPE, + _parent.getName(), + _name, + Names.CLASS, + objectName); + + sendNotification(notification); + } + } + + /** + * Deregisters all the object instances and release all previously acquired resources. + */ + void releaseResources () + { + _objectInstances.clear(); + JMX_SERVICE.unregisterObjectInstances(); + JMX_SERVICE.unregisterClassDefinitions(); + _service.close(); + } + + /** + * Compose method used for registering mbean instance. + * + * @param instance the mbean instance. + * @param brokerId the broker identifier. + * @param packageName the package name. + * @param className the class name. + * @param objectId the object identifier. + */ + private void registerMBean( + QManManagedObject instance, + UUID brokerId, + String packageName, + String className, + Binary objectId) + { + ObjectName objectName = JMX_SERVICE.registerObjectInstance(instance,_parent.getOwnerId(),_parent.getName(),_name,objectId); + + EntityLifecycleNotification notification = new EntityLifecycleNotification( + EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE, + packageName, + className, + Names.CLASS, + objectName); + + sendNotification(notification); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java new file mode 100644 index 0000000000..eeb4e0e2d8 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClassMBean.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Management interface for Qpid entity class.. + */ +public interface QpidClassMBean +{ + /** + * Retruns the name of the class. + * + * @return the name of the class. + */ + String getName(); + + /** + * Returns the name of the package. + * + * @return the name of the package. + */ + String getPackageName(); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java new file mode 100644 index 0000000000..ea0acb5fd1 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java @@ -0,0 +1,184 @@ +package org.apache.qpid.management.domain.model; +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + +import java.util.HashMap; +import java.util.Map; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.DynamicMBean; +import javax.management.MBeanInfo; +import javax.management.NotificationBroadcasterSupport; +import javax.management.ObjectName; +import javax.management.RuntimeOperationsException; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.management.domain.services.QpidService; +import org.apache.qpid.management.jmx.EntityLifecycleNotification; +import org.apache.qpid.transport.util.Logger; + +/** + * Layer supertype for QMan entities. + */ +public abstract class QpidEntity extends NotificationBroadcasterSupport +{ + /** + * Layer supertype for QMan managed bean entities. + */ + abstract class QManManagedEntity implements DynamicMBean + { + // After mbean is registered with the MBean server this collection holds the mbean attribute values. + Map _attributes = new HashMap(); + + /** + * Creates or replace the given attribute. + * Note that this is not part of the management interface of this object instance and therefore will be accessible only + * from within this class. + * It is used to update directly the object attributes bypassing jmx interface. + * + * @param attributeName the name of the attribute. + * @param property newValue the new value of the attribute. + */ + void createOrReplaceAttributeValue(String attributeName, Object newValue) + { + _attributes.put(attributeName, newValue); + } + + /** + * Get the values of several attributes of the Dynamic MBean. + * + * @param attributes A list of the attributes to be retrieved. + * + * @return The list of attributes retrieved. + */ + public AttributeList getAttributes (String[] attributes) + { + if (attributes == null) + { + throw new RuntimeOperationsException(new IllegalArgumentException("Attributes array must not be null")); + } + + AttributeList result = new AttributeList(attributes.length); + for (int i = 0; i < attributes.length; i++) + { + String attributeName = attributes[i]; + try + { + result.add(new Attribute(attributeName,getAttribute(attributeName))); + } catch(Exception exception) + { + // Already logged. + } + } + return result; + } + + /** + * Returns metadata for this object instance. + */ + // Developer Note : note that this metadata is a member of the outer class definition : in that way we create + // that metadata only once and then it will be shared between all object instances (it's a readonly object) + public MBeanInfo getMBeanInfo () + { + return _metadata; + } + }; + + final Logger _logger = Logger.get(getClass()); + final static JmxService JMX_SERVICE = new JmxService(); + + final String _name; + final Binary _hash; + + final QpidPackage _parent; + MBeanInfo _metadata; + final QpidService _service; + + protected ObjectName _objectName; + + private final String _type; + + /** + * Builds a new class with the given name and package as parent. + * + * @param className the name of the class. + * @param hash the class schema hash. + * @param parentPackage the parent of this class. + */ + QpidEntity(String className, Binary hash, QpidPackage parentPackage,String type) + { + this._name = className; + this._parent = parentPackage; + this._hash = hash; + this._type = type; + this._service = new QpidService(_parent.getOwnerId()); + + _logger.debug( + Messages.QMAN_200020_ENTITY_DEFINITION_HAS_BEEN_BUILT, + _parent.getOwnerId(), + _parent.getName(), + _name); + } + + public String getName() + { + return _name; + } + + public String getPackageName() + { + return _parent.getName(); + } + + /** + * Internal method used to send a schema request for this entity. + * + * @throws Exception when the request cannot be sent. + */ + void requestSchema() throws Exception + { + + _objectName = JMX_SERVICE.createEntityDefinitionName(_parent.getName(), _name,_type); + JMX_SERVICE.registerEntityDefinition(_objectName,this,_parent.getName(),_name); + + try + { + _service.connect(); + _service.requestSchema(_parent.getName(), _name, _hash); + _service.sync(); + } finally + { + _service.close(); + } + + EntityLifecycleNotification notification = new EntityLifecycleNotification( + EntityLifecycleNotification.SCHEMA_REQUESTED_NOTIFICATION_TYPE, + _parent.getName(), + _name, + Names.CLASS, + _objectName); + sendNotification(notification); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java new file mode 100644 index 0000000000..31d8d01fc9 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java @@ -0,0 +1,493 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.InvalidAttributeValueException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.ObjectName; +import javax.management.ReflectionException; +import javax.management.RuntimeOperationsException; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.management.jmx.EntityLifecycleNotification; +import org.apache.qpid.transport.codec.BBDecoder; + +/** + * Qpid event definition. + */ +class QpidEvent extends QpidEntity implements QpidEventMBean +{ + + /** + * State interface for this event definition. + * Each state is responsible to handle the injection of the data and / or schema. + */ + interface State + { + /** + * Adds the given data for the object instance associated to the given object identifier. + * + * @param rawData the raw configuration data. + */ + void addNewEventData (byte[] rawData, long currentTimestamp, int severity); + + /** + * Inject the schema into this class definition. + * + * @param propertyDefinitions + * @param statisticDefinitions + * @param methodDefinitions + * @throws UnableToBuildFeatureException when it's not possibile to parse schema and build the class definition. + */ + public void setSchema (List> agumentDefinitions) throws UnableToBuildFeatureException; + }; + + + /** + * This is the initial state of every qpid class. + * The class definition instance is created but its schema has not been injected. + * Incoming configuration & instrumentation data will be stored in raw format because we don't know how to + * parse it until the schema arrives. + * In addition, this state is responsible (when data arrives) to request its schema. + */ + final State _schemaNotRequested = new State() { + + /** + * Stores the incoming data in raw format and request the schema for this class. + * After that a transition to the next state is made. + * + * @param objectId the object instance identifier. + * @param rawData incoming configuration data. + */ + public synchronized void addNewEventData (byte[] rawData, long currentTimestamp, int severity) + { + try + { + requestSchema(); + _state = _schemaRequestedButNotYetInjected; + } catch (Exception exception) + { + _logger.error( + exception, + Messages.QMAN_100015_UNABLE_TO_SEND_SCHEMA_REQUEST, + _parent.getName(), + _name); + } finally { + createEventInstance(rawData,currentTimestamp,severity); + } + } + + /** + * This method only throws an illegal state exception because when a schema arrives + * this state is no longer valid. + */ + public void setSchema (List> agumentDefinitions) throws UnableToBuildFeatureException + { + throw new IllegalStateException("When a schema arrives it's not possible for this event to be in this state."); + } + }; + + /** + * This is the first state of this class definition : the schema is not yet injected so each injection of object data will be + * retained in raw format. + */ + final State _schemaRequestedButNotYetInjected = new State() + { + /** + * Stores the incoming data in raw format and request the schema for this class. + * After that a transition to the next state is made. + * + * @param objectId the object instance identifier. + * @param rawData incoming configuration data. + */ + public synchronized void addNewEventData (byte[] rawData,long currentTimestamp, int severity) + { + createEventInstance(rawData,currentTimestamp, severity); + } + + /** + * When a schema is injected into this defintiion the following should happen : + * 1) the incoming schema is parsed and the class definition is built; + * 2) the retained raw data is converted into object instance(s) + * 3) the internal state of this class changes; + * + * If someting is wrong during that process the schema is not built and the state don't change. + */ + public synchronized void setSchema (List> argumentDefinitions) throws UnableToBuildFeatureException + { + MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[argumentDefinitions.size()+2]; + + buildArguments(argumentDefinitions, attributesMetadata); + + _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,null,null); + + // Converting stored object instances into JMX MBean and removing raw instance data. + for (QManManagedEvent instance : _eventInstances) + { + updateEventInstanceWithData(instance); + registerEventInstance(instance,_parent.getOwnerId(),_parent.getName(),_name); + } + _state = _schemaInjected; + + EntityLifecycleNotification notification = new EntityLifecycleNotification( + EntityLifecycleNotification.SCHEMA_INJECTED_NOTIFICATION_TYPE, + _parent.getName(), + _name, + Names.EVENT, + _objectName); + + sendNotification(notification); + } + }; + + /** + * After a schema is built into this definition this is the current state of the class. + */ + final State _schemaInjected = new State() + { + /** + * Updates the configuration state of the object instance associates with the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the configuration data (raw format). + */ + public void addNewEventData (byte[] rawData,long currentTimestamp, int severity) + { + QManManagedEvent instance = createEventInstance(rawData,currentTimestamp, severity); + updateEventInstanceWithData(instance); + registerEventInstance(instance,_parent.getOwnerId(),_parent.getName(),_name); + } + + /** + * Never called when the class definition has this state. + */ + public void setSchema (List> agumentDefinitions) throws UnableToBuildFeatureException + { + // N.A. : Schema is already injected. + } + }; + + /** + * MBean used for representing remote broker object instances. + * This is the core component of the QMan domain model + * + * @author Andrea Gazzarini + */ + class QManManagedEvent extends QManManagedEntity + { + + + // Arrays used for storing raw data before this mbean is registered to mbean server. + final byte[] _rawEventData; + final long _timestamp; + final int _severity; + + /** + * Builds a new managed object with the given object identifier. + * + * @param objectId the object identifier. + */ + private QManManagedEvent(byte [] data, long timestamp, int severity) + { + this._rawEventData = data; + this._timestamp = timestamp; + this._severity = severity; + _attributes.put(SEVERITY_ATTR_NAME, _severity); + _attributes.put(TIMESTAMP_ATTR_NAME, new Date(_timestamp)); + } + + /** + * Returns the value of the given attribute.s + * + * @throws AttributeNotFoundException when no attribute is found with the given name. + */ + public Object getAttribute (String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException + { + if (attributeName == null) + { + throw new RuntimeOperationsException(new IllegalArgumentException("Attribute name must not be null.")); + } + + if (_arguments.containsKey(attributeName) || SEVERITY_ATTR_NAME.equals(attributeName) || TIMESTAMP_ATTR_NAME.equals(attributeName)) + { + return _attributes.get(attributeName); + } else + { + throw new AttributeNotFoundException(attributeName); + } + } + + /** + * Executes an operation on this object instance. + * + * @param actionName the name of the method. + * @param params the method parameters + * @param signature the method signature. + */ + public Object invoke (String actionName, Object[] params, String[] signature) throws MBeanException,ReflectionException + { + throw new ReflectionException(new NoSuchMethodException(actionName)); + } + + /** + * Sets the value of the given attribute on this object instance. + * + * @param attribute contains the new value of the attribute. + * @throws AttributeNotFoundException when the given attribute is not found on this object instance. + * @throws InvalidAttributeValueException when the given value is violating one attribute invariant. + */ + public void setAttribute (Attribute attribute) throws AttributeNotFoundException, + InvalidAttributeValueException, MBeanException, ReflectionException + { + throw new ReflectionException(new NoSuchMethodException()); + } + + /** + * Sets the values of several attributes of this MBean. + * + * @param attributes a list of attributes: The identification of the attributes to be set and the values they are to be set to. + * @return The list of attributes that were set, with their new values. + */ + public AttributeList setAttributes (AttributeList attributes) + { + throw new RuntimeException(); + } + } + + final static String SEVERITY_ATTR_NAME = "Severity"; + final static String TIMESTAMP_ATTR_NAME = "Date"; + + private List _schemaOrderedArguments = new ArrayList(); + + Map _arguments = new HashMap(); + List _eventInstances = new LinkedList(); + State _state = _schemaNotRequested;; + + /** + * Builds a new class with the given name and package as parent. + * + * @param className the name of the class. + * @param hash the class schema hash. + * @param parentPackage the parent of this class. + */ + QpidEvent(String eventClassName, Binary hash, QpidPackage parentPackage) + { + super(eventClassName,hash,parentPackage,Names.EVENT); + } + + /** + * Adds the configuration data for the object instance associated to the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the raw configuration data. + */ + void addEventData (byte[] rawData, long currentTimestamp, int severity) + { + _logger.debug( + Messages.QMAN_200021_INCOMING_EVENT_DATA, + _parent.getOwnerId(), + _parent.getName(), + _name); + _state.addNewEventData(rawData, currentTimestamp, severity); + } + + /** + * Sets the schema for this class definition. + * A schema is basically a metadata description of all properties, statistics, methods and events of this class. + * + * @param propertyDefinitions properties metadata. + * @param statisticDefinitions statistics metadata. + * @param methodDefinitions methods metadata. + * @throws UnableToBuildFeatureException when some error occurs while parsing the incoming schema. + */ + void setSchema (List> argumentDefinitions) throws UnableToBuildFeatureException + { + _logger.info(Messages.QMAN_000010_INCOMING_SCHEMA,_parent.getOwnerId(),_parent.getName(),_name); + _state.setSchema(argumentDefinitions); + } + + /** + * Internal method used for building attributes definitions. + * + * @param props the map contained in the properties schema. + * @param stats the map contained in the statistics schema. + * @param attributes the management metadata for attributes. + * @throws UnableToBuildFeatureException when it's not possibile to build one attribute definition. + */ + void buildArguments ( + List> arguments,MBeanAttributeInfo[] attributes) throws UnableToBuildFeatureException + { + int index = 0; + + for (Map argumentDefinition : arguments) + { + // Force metadata attributes. It is needed because arguments are "similar" to properties but they + // aren't properties and then they haven't optional, index and access metadata attributes + // (mandatory for build a property definition). + argumentDefinition.put(QpidFeatureBuilder.Attribute.optional.name(),0); + argumentDefinition.put(QpidFeatureBuilder.Attribute.index.name(),1); + argumentDefinition.put(QpidFeatureBuilder.Attribute.access.name(),3); + + QpidFeatureBuilder builder = QpidFeatureBuilder.createPropertyBuilder(argumentDefinition); + builder.build(); + + QpidProperty argument = (QpidProperty) builder.getQpidFeature(); + + _arguments.put(argument.getName(),argument); + _schemaOrderedArguments.add(argument); + attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature(); + + _logger.debug( + Messages.QMAN_200019_EVENT_ARGUMENT_DEFINITION_HAS_BEEN_BUILT, + _parent.getName(), + _name, + argument); + } + + attributes[index++] = new MBeanAttributeInfo( + SEVERITY_ATTR_NAME, + Integer.class.getName(), + Messages.EVENT_SEVERITY_ATTRIBUTE_DESCRIPTION, + true, + false, + false); + + attributes[index++] = new MBeanAttributeInfo( + TIMESTAMP_ATTR_NAME, + Date.class.getName(), + Messages.EVENT_TIMESTAMP_ATTRIBUTE_DESCRIPTION, + true, + false, + false); + } + + /** + * Returns the object instance associated to the given identifier. + * Note that if the identifier is not associated to any obejct instance, a new one will be created. + * + * @param objectId the object identifier. + * @param registration a flag indicating whenever the (new ) instance must be registered with MBean server. + * @return the object instance associated to the given identifier. + */ + QManManagedEvent createEventInstance(byte [] data, long timestamp, int severity) + { + QManManagedEvent eventInstance = new QManManagedEvent(data, timestamp, severity); + _eventInstances.add(eventInstance); + return eventInstance; + } + + /** + * Updates the given obejct instance with the given incoming configuration data. + * + * @param instance the managed object instance. + * @param rawData the incoming configuration data which contains new values for instance properties. + */ + void updateEventInstanceWithData(QManManagedEvent instance) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(instance._rawEventData)); + + for (QpidProperty property : _schemaOrderedArguments) + { + try { + Object value = property.decodeValue(decoder); + instance.createOrReplaceAttributeValue(property.getName(),value); + } catch(Exception ignore) { + _logger.error(Messages.QMAN_100016_UNABLE_TO_DECODE_FEATURE_VALUE, _parent.getName(),_name,property.getName()); + } + } + } + + @Override + public String toString () + { + return new StringBuilder() + .append(_parent.getOwnerId()) + .append("::") + .append(_parent.getName()) + .append(".") + .append(_name) + .toString(); + } + + /** + * Deregisters all the object instances and release all previously acquired resources. + */ + void releaseResources () + { + _eventInstances.clear(); + JMX_SERVICE.unregisterEvents(); + JMX_SERVICE.unregisterClassDefinitions(); + _service.close(); + } + + /** + * Checks if this event definition contains event instance(s). + * + * @return true if there is one or more managed instances. + */ + boolean hasNoInstances() + { + return _eventInstances.isEmpty(); + } + + /** + * Compose method used for registering an mbean (event) instance. + * + * @param instance the mbean event. + * @param brokerId the broker identifier. + * @param packageName the package name. + * @param eventClassName the event class name. + */ + private void registerEventInstance( + QManManagedEvent instance, + UUID brokerId, + String packageName, + String eventClassName) + { + ObjectName objectName = JMX_SERVICE.registerEventInstance(instance,brokerId,packageName,eventClassName); + + EntityLifecycleNotification notification = new EntityLifecycleNotification( + EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE, + packageName, + eventClassName, + Names.EVENT, + objectName); + + sendNotification(notification); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java new file mode 100644 index 0000000000..35ba62e02c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEventMBean.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Management interface for Qpid entity class.. + */ +public interface QpidEventMBean +{ + /** + * Retruns the name of the event. + * + * @return the name of the event. + */ + String getName(); + + /** + * Returns the name of the package. + * + * @return the name of the package. + */ + String getPackageName(); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java new file mode 100644 index 0000000000..3262448bd4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Layer Supertype for all qpid management features. + */ +abstract class QpidFeature +{ + /** The name of the feature. */ + protected String _name; + + /** + * The description of the feature. + */ + protected String _description; + + /** + * Returns the description of this feature. + * + * @return the description of this feature. + */ + String getDescription () + { + return _description; + } + + /** + * Sets the description for this feature. + * + * @param description the description for this feature. + */ + void setDescription (String description) + { + this._description = description; + } + + /** + * Returns the name of the feature. + * + * @return the name of the feature. + */ + public String getName () + { + return _name; + } + + /** + * Sets the name for this feature. + * + * @param name the name of this feature. + */ + void setName (String name) + { + this._name = name; + } + + /** + * Returns the name of the feature. + * + * @return the name of the feature. + */ + @Override + public String toString () + { + return _name; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java new file mode 100644 index 0000000000..d0862c15ca --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java @@ -0,0 +1,454 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanFeatureInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; + +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.configuration.UnknownTypeCodeException; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.Names; + +/** + * A builder used to parse incoming schema message and therefore to build a feature (property, statistic, method, event) + * definition. + * In order to set up the correct state for this builder, clients must create an instance of this class + * The product of the builder will be a QpidFeature and a JMX Managemtn feature used for describing that feature in a + * JMX environment. So, for example, for building a property definition client code should be : + * + *
- QpidFeatureBuilder builder = QpidFeature.createPropertyBuilder(...); + *
- builder.build(); + *
- QpidProperty property = (QpidProperty) builder.getQpidFeature(); + *
- MBeanAttributeInfo managementAttributeInfo = (MBeanAttributeInfo)builder.getManagementFeature(); + * + *
N.B.: a builder instance is not supposed to be reused. One instance for one feature! + * + * @author Andrea Gazzarini + */ +class QpidFeatureBuilder +{ + + static enum Attribute { + name,type,access,index,optional,unit,min,max,maxlen,desc,dir,argCount; + }; + + private List _mandatoryAttributes = new ArrayList(); + + /** + * Builder state for this class. + * Each concrete implementor is a builder for a specific feature. + * using the appropriate factory method. + * + * @author Andrea Gazzarini + */ + interface State { + void build() throws UnableToBuildFeatureException; + } + + /** + * Builder used for building property definition. + */ + final State _propertyBuilder = new State() { + + /** + * Builds a property definition as well a management attribute feature. + */ + public void build () throws UnableToBuildFeatureException + { + QpidProperty property = new QpidProperty(); + try { + int optionalIndex = 0; + for (Entry propertyAttribute : _featureDefinition.entrySet()) + { + Attribute attribute = Attribute.valueOf(propertyAttribute.getKey()); + switch(attribute) + { + case name : + { + property.setName(String.valueOf(propertyAttribute.getValue())); + break; + } + case access : + { + int code = (Integer)propertyAttribute.getValue(); + property.setAccessMode(Configuration.getInstance().getAccessMode(code)); + break; + } + case unit : + { + property.setUnit(String.valueOf(propertyAttribute.getValue())); + break; + } + case min : + { + property.setMinValue((Integer)propertyAttribute.getValue()); + break; + } + case max : + { + property.setMaxValue((Integer)propertyAttribute.getValue()); + break; + } + case maxlen : + { + property.setMaxLength((Integer)propertyAttribute.getValue()); + break; + } + case desc : + { + property.setDescription(String.valueOf(propertyAttribute.getValue())); + break; + } + case type : + { + int code = (Integer) propertyAttribute.getValue(); + property.setType(Configuration.getInstance().getType(code)); + break; + } + case index : + { + break; + } + case optional : + { + int code = (Integer) propertyAttribute.getValue(); + if (code == 1) + { + property.markAsOptional(optionalIndex); + optionalIndex++; + } + break; + } + } + _mandatoryAttributes.remove(attribute); + } + } catch(Exception exception) + { + throw new UnableToBuildFeatureException(exception,property.getName()); + } + + if (!_mandatoryAttributes.isEmpty()) + { + throw new MissingFeatureAttributesException(_mandatoryAttributes); + } + + _managementFeatureInfo = new MBeanAttributeInfo( + property.getName(), + property.getJavaType().getName(), + property.getDescription(), + true, + property.getAccessMode()==AccessMode.RW, + false); + _qpidFeature = property; + } + }; + + final State _statisticBuilder = new State() + { + public void build () throws UnableToBuildFeatureException + { + QpidStatistic statistic = new QpidStatistic(); + try + { + for (Entry statisticAttribute : _featureDefinition.entrySet()) + { + Attribute attribute = Attribute.valueOf(statisticAttribute.getKey()); + switch(attribute) + { + case name : + { + statistic.setName(String.valueOf(statisticAttribute.getValue())); + break; + } + case unit : + { + statistic.setUnit(String.valueOf(statisticAttribute.getValue())); + break; + } + case desc : + { + statistic.setDescription(String.valueOf(statisticAttribute.getValue())); + break; + } + case type : + { + int code = (Integer) statisticAttribute.getValue(); + statistic.setType(Configuration.getInstance().getType(code)); + break; + } + } + _mandatoryAttributes.remove(attribute); + } + } catch(Exception exception) + { + throw new UnableToBuildFeatureException(exception,statistic.getName()); + } + + if (!_mandatoryAttributes.isEmpty()) + { + throw new MissingFeatureAttributesException(_mandatoryAttributes); + } + + _managementFeatureInfo = new MBeanAttributeInfo( + statistic.getName(), + statistic.getJavaType().getName(), + statistic.getDescription(), + true, + false, + false); + _qpidFeature = statistic; + } + }; + + /** + * Builder used for building a statistic definition. + */ + final State _argumentBuilder = new State() + { + /** + * Builds a property definition as well a management attribute feature. + */ + public void build () throws UnableToBuildFeatureException + { + QpidArgument argument = new QpidArgument(); + for (Entry argumentAttribute : _featureDefinition.entrySet()) + { + String key = argumentAttribute.getKey(); + if (Names.DEFAULT_PARAM_NAME.equals(key)) + { + argument.setDefaultValue(argumentAttribute.getValue()); + } else { + Attribute attribute = Attribute.valueOf(key); + switch (attribute) + { + case name : + { + argument.setName((String)argumentAttribute.getValue()); + break; + } + case desc : + { + argument.setDescription((String)argumentAttribute.getValue()); + break; + } + case type : + { + try + { + argument.setType(Configuration.getInstance().getType((Integer)argumentAttribute.getValue())); + break; + } catch(UnknownTypeCodeException exception) + { + throw new UnableToBuildFeatureException(exception,argument.getName()); + } + } + case dir : + { + argument.setDirection((String)argumentAttribute.getValue()); + break; + } + case unit : + { + argument.setUnit((String)argumentAttribute.getValue()); + break; + + } + } + } + } + + if (!_mandatoryAttributes.isEmpty()) + { + throw new MissingFeatureAttributesException(_mandatoryAttributes); + } + + _qpidFeature = argument; + _managementFeatureInfo = new MBeanParameterInfo( + argument.getName(), + argument.getJavaType().getName(), + argument.getDescription()); + } + }; + + final State _methodBuilder = new State() + { + public void build () throws UnableToBuildFeatureException + { + Map definition = _methodOrEventDefinition.getDefinition(); + String name = (String)definition.get(Attribute.name.name()); + if (name == null) + { + throw new MissingFeatureAttributesException(_mandatoryAttributes); + } + + QpidMethod method = new QpidMethod((String)definition.get(Attribute.name.name()),(String) definition.get(Attribute.desc.name())); + + List> args = _methodOrEventDefinition.getArgumentsDefinitions(); + + List signature = new LinkedList(); + + for (Map argumentDefinition : args) + { + QpidFeatureBuilder builder = QpidFeatureBuilder.createArgumentBuilder(argumentDefinition); + builder.build(); + + QpidArgument argument = (QpidArgument) builder.getQpidFeature(); + method.addArgument(argument); + if (argument.isInput()) + { + signature.add((MBeanParameterInfo) builder.getManagementFeature()); + } + } + + _qpidFeature = method; + _managementFeatureInfo = new MBeanOperationInfo( + method.getName(), + method.getDescription(), + (MBeanParameterInfo[])signature.toArray(new MBeanParameterInfo[signature.size()]), + void.class.getName(), + MBeanOperationInfo.ACTION); + } + }; + + final State _eventBuilder = new State() + { + public void build () throws UnableToBuildFeatureException + { + } + }; + + private MBeanFeatureInfo _managementFeatureInfo; + private QpidFeature _qpidFeature; + private final Map _featureDefinition; + private final MethodOrEventDataTransferObject _methodOrEventDefinition; + private State _state; + + static QpidFeatureBuilder createPropertyBuilder(Map propertyDefinition) + { + QpidFeatureBuilder result = new QpidFeatureBuilder(propertyDefinition); + result._state = result._propertyBuilder; + result._mandatoryAttributes.add(Attribute.name); + result._mandatoryAttributes.add(Attribute.access); + result._mandatoryAttributes.add(Attribute.type); + result._mandatoryAttributes.add(Attribute.optional); + result._mandatoryAttributes.add(Attribute.index); + return result; + } + + static QpidFeatureBuilder createStatisticBuilder(Map statisticDefinition) + { + QpidFeatureBuilder result = new QpidFeatureBuilder(statisticDefinition); + result._state = result._statisticBuilder; + result._mandatoryAttributes.add(Attribute.name); + result._mandatoryAttributes.add(Attribute.type); + return result; + } + + static QpidFeatureBuilder createEventBuilder(Map eventDefinition) + { + QpidFeatureBuilder result = new QpidFeatureBuilder(eventDefinition); + result._state = result._eventBuilder; + return result; + } + + static QpidFeatureBuilder createMethodBuilder(MethodOrEventDataTransferObject methodDefinition) + { + QpidFeatureBuilder result = new QpidFeatureBuilder(methodDefinition); + result._state = result._methodBuilder; + result._mandatoryAttributes.add(Attribute.name); + return result; + } + + private static QpidFeatureBuilder createArgumentBuilder(Map argumentDefinition) + { + QpidFeatureBuilder result = new QpidFeatureBuilder(argumentDefinition); + result._state = result._argumentBuilder; + return result; + } + + + /** + * Builds new builder with the given data. + * This constructor is used for building properties, statistics and arguments. + * + * @param definition the feature definition data. + */ + private QpidFeatureBuilder(Map definition) + { + this._featureDefinition = definition; + this._methodOrEventDefinition = null; + } + + /** + * Builds new builder with the given data. + * This constructor is used for building properties, statistics and arguments. + * + * @param definition the feature definition data. + */ + private QpidFeatureBuilder(MethodOrEventDataTransferObject definition) + { + this._featureDefinition = null; + this._methodOrEventDefinition = definition; + } + + /** + * Returns the just built qpid feature. + * + * @return the qpid feature. + */ + QpidFeature getQpidFeature() + { + return _qpidFeature; + } + + /** + * Return the jmx metadata for the built feature. + * + * @return the jmx metadata for the built feature. + */ + MBeanFeatureInfo getManagementFeature() + { + return _managementFeatureInfo; + } + + void build() throws UnableToBuildFeatureException + { + try + { + _state.build(); + } catch(UnableToBuildFeatureException exception) + { + throw exception; + } catch(Exception exception) + { + throw new UnableToBuildFeatureException(exception,"Feature name is not available for debugging."); + } + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java new file mode 100644 index 0000000000..7824ecc9a4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java @@ -0,0 +1,147 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.codec.Encoder; + + +/** + * Qpid method definition. + * An entity describing an invocation that can be made on a managed object instance. + * + * @author Andrea Gazzarini + */ +public class QpidMethod extends QpidFeature +{ + /** Argument list */ + List arguments = new LinkedList(); + + /** + * Builds a new qpid method definition with the given name and description. + * + * @param name the method name. + * @param description the method description. + */ + QpidMethod(String name, String description) + { + this._name = name; + this._description = description; + } + + /** + * Adds an argument to this method. + * + * @param argument the new argument to be added. + */ + void addArgument(QpidArgument argument) + { + arguments.add(argument); + } + + /** + * Returns a string representation of this method. + * The result format is (argType1 argName1 (Direction), argType2 argName2 (Direction), etc...) + * + * @return a string representation of this method. + */ + @Override + public String toString () + { + StringBuilder builder = new StringBuilder() + .append(_name) + .append('('); + + for (QpidArgument argument : arguments) + { + builder.append(argument).append(','); + } + + builder.append(')'); + return builder.toString(); + } + + /** + * Encodes the given parameter values according to this method arguments definitions. + * Note that only Input/Output and Input parameters are encoded. + * + * @param parameters the parameters values. + * @param encoder the encoder used for encoding. + */ + public void encodeParameters (Object[] parameters, Encoder encoder) + { + int index = 0; + for (QpidArgument argument : arguments) + { + if (argument.getDirection() != Direction.O) + { + argument.encode(parameters[index++],encoder); + } + } + } + + /** + * Decodes the given input raw according to this method arguments definitions. + * Note that only Input/Output and Output parameters are encoded. + * + * @param parameters the parameters values. + * @param encoder the encoder used for encoding. + */ + public Map decodeParameters (byte [] values) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(values)); + Map result = new HashMap(); + + for (QpidArgument argument : arguments) + { + if (argument.getDirection() != Direction.I) + { + result.put(argument.getName(),argument.decode(decoder)); + } + } + return result; + } + + /** + * Validates the given array of parameters against the constraint defined on this method's arguments. + * + * @param parameters the parameters (values) to be validated. + * @throws ValidationException when one of the supplied values is violating some constraint. + */ + public void validate (Object[] parameters) throws ValidationException + { + int index = 0; + for (QpidArgument argument : arguments) + { + if (argument.getDirection() != Direction.O) + { + argument.validate(parameters[index++]); + } + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java new file mode 100644 index 0000000000..c25a5d7d1c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java @@ -0,0 +1,286 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Qpid package definition. + * A grouping of class definitions that are related to a single software component. + * The package concept is used to extend the management schema beyond just the QPID software components. + * The name is prefixed with "Qpid" for avoiding name conficts with java.lang.Package. + * + * @author Andrea Gazzarini + */ +final class QpidPackage +{ + /** + * Qpid class identity. + * Each qpid class is uniquely identifier by its name and schema-hash. + * The schema hash is an MD5 checksum of the schema for a class. + * It is there so we can support the case where two different versions of the same class are present at the same time. + * + * @author Andrea Gazzarini + */ + class QpidClassIdentity { + final String name; + final Binary hash; + + /** + * Builds a new class identity with the given name and hash. + * + * @param name the class name. + * @param hash is an MD5 checksum of the schema of this outer class. + */ + QpidClassIdentity(String name,Binary hash) { + this.name = name; + this.hash = hash; + } + + @Override + public int hashCode () + { + return name.hashCode()+hash.hashCode(); + } + + @Override + public boolean equals (Object obj) + { + if(obj instanceof QpidClassIdentity) + { + QpidClassIdentity identity = (QpidClassIdentity) obj; + return name.equals(identity.name) && hash.equals(identity.hash); + } + else + { + return false; + } + } + } + + private String _name; + private DomainModel _parent; + private Map _classes = new HashMap(); + private Map _events = new HashMap(); + + /** + * Builds a new package with the supplied name. + * + * @param name the name of the package. + */ + QpidPackage(String name, DomainModel parent) + { + this._name = name; + this._parent = parent; + } + + /** + * Returns the identifier of the broker which contains this package. + * @return + */ + UUID getOwnerId() + { + return _parent.getBrokerId(); + } + + /** + * Returns the name of this package. + * + * @return the name of this package. + */ + String getName () + { + return _name; + } + + /** + * Adds a class definition to this package. + * The class will be added only if its definition doesn't already exists. + * + * @param className the name of the class. + * @param classHash the class schema hash. + * @param properties the properties of the class. + * @param statistics the statistics of the class. + * @param methods the methods of the class. + * @param events the events of the class. + * + * @throws UnableToBuildFeatureException when the class definition cannot be built due to a feature build failure. + */ + void addClassDefinition ( + String className, + Binary classHash, + List> properties, + List> statistics, + List methods) throws UnableToBuildFeatureException + { + getQpidClass(className,classHash,true).setSchema(properties,statistics,methods); + } + + void addEventDefinition ( + String eventClassName, + Binary classHash, + List> arguments) throws UnableToBuildFeatureException + { + getQpidEvent(eventClassName,classHash,true).setSchema(arguments); + } + + /** + * Returns true if this package contains the given class definition. + * + * @param className the name of the class. + * @return true if this package contains the class definition, false otherwise. + */ + boolean alreadyContainsClassDefinition (String className, Binary hash) + { + return _classes.containsKey(new QpidClassIdentity(className,hash)); + } + + /** + * Injects into a class the given object instance instrumentation data. + * + * @param className the of the class the injected object data belongs to. + * @param objectId the object identifier. + * @param rawData the instrumentation data (in raw format). + */ + void setObjectInstanceInstrumentationRawData (String className, Binary classHash,Binary objectId, byte[] rawData) + { + getQpidClass(className, classHash,true).addInstrumentationData(objectId,rawData); + } + + /** + * Injects into a class the given object instance configuration data. + * + * @param className the of the class the injected object data belongs to. + * @param objectId the object identifier. + * @param rawData the configuration data (in raw format). + */ + void setObjectInstanceConfigurationRawData (String className,Binary classHash, Binary objectId, byte[] rawData) + { + getQpidClass(className,classHash,true).addConfigurationData(objectId,rawData); + } + + void setEventInstanceRawData (String eventName,Binary eventHash, byte[] rawData,long currentTimestamp,int severity) + { + getQpidEvent(eventName,eventHash,true).addEventData(rawData, currentTimestamp, severity); + } + + /** + * Returns the definition of the class with given name. + * + * @param className the name of the class. + * @param hash the class hash. + * @param store a flag indicating if a just created class must be stored or not. + * @return the definition of the class with given name. + */ + QpidClass getQpidClass(String className, Binary hash, boolean store) + { + QpidClassIdentity identity = new QpidClassIdentity(className,hash); + QpidClass classDefinition = _classes.get(identity); + if (classDefinition == null) + { + classDefinition = new QpidClass(className, hash,this); + if (store) + { + _classes.put(identity,classDefinition); + } + } + return classDefinition; + } + + /** + * Returns the definition of the class with given name. + * + * @param className the name of the class. + * @param hash the class hash. + * @param store a flag indicating if a just created class must be stored or not. + * @return the definition of the class with given name. + */ + QpidEvent getQpidEvent(String className, Binary hash, boolean store) + { + QpidClassIdentity identity = new QpidClassIdentity(className,hash); + QpidEvent eventDefinition = _events.get(identity); + if (eventDefinition == null) + { + eventDefinition = new QpidEvent(className, hash,this); + if (store) + { + _events.put(identity,eventDefinition); + } + } + return eventDefinition; + } + + /** + * Returns a string representation of this class. + * That is, this method returns the simple name (not FQN) of this class. + */ + @Override + public String toString () + { + return _name; + } + + /** + * Removes the object instance associated to the given parameters. + * + * @param className the class definition of the object instance. + * @param classHash the class hash + * @param objectId the object identifier. + */ + void removeObjectInstance (String className, Binary classHash, Binary objectId) + { + QpidClass qpidClass = getQpidClass(className,classHash,false); + qpidClass.removeObjectInstance(objectId); + } + + /** + * Releases all previously acquired resources of this package. + */ + void releaseResources () + { + for (QpidClass qpidClass : _classes.values()) + { + qpidClass.releaseResources(); + } + + for (QpidEvent qpidEvent: _events.values()) + { + qpidEvent.releaseResources(); + } + } + + /** + * Returns the method invocation listener of the corresponing parent domain model. + * + * @return the method invocation listener of the corresponing parent domain model. + */ + IMethodInvocationListener getMethodInvocationListener () + { + return _parent.getMethodInvocationListener(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java new file mode 100644 index 0000000000..089b00c71c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java @@ -0,0 +1,295 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.lang.reflect.Constructor; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.domain.model.type.Type; +import org.apache.qpid.transport.util.Logger; + +/** + * Qpid property definition. + * + * @author Andrea Gazzarini + */ +class QpidProperty extends QpidAttribute +{ + private final static Logger LOGGER = Logger.get(QpidProperty.class); + + private final static int [] MASKS = {1,2,4,8,16,32,64,128}; + + /** + * Decoder interface used for decoding incomng values for this property. + * + * @author Andrea Gazzarini + */ + interface Decoder + { + Object decodeValue(org.apache.qpid.transport.codec.Decoder decoder,byte [] presenceBitMasks); + } + + /** + * Decoder used for decoding incoming values for this optional property. + */ + final Decoder _optionalPropertyDecoder = new Decoder() { + + public Object decodeValue (org.apache.qpid.transport.codec.Decoder decoder, byte[] presenceBitMasks) + { + return ((presenceBitMasks[_optionalIndex/8] & MASKS[_maskIndex]) != 0) + ? QpidProperty.this.decodeValue(decoder) + : null; + } + }; + + /** + * Decoder used for decoding incoming values for this mandatory property. + */ + final Decoder _mandatoryPropertyDecoder = new Decoder() { + + public Object decodeValue (org.apache.qpid.transport.codec.Decoder decoder, byte[] presenceBitMasks) + { + return QpidProperty.this.decodeValue(decoder); + } + }; + + + /** + * Null object used to perform a dummy validation. + * This is the default validator installed at creation time. + */ + final static IValidator EMPTY_VALIDATOR = new IValidator() + { + public void validate (Object value) throws ValidationException + { + // Nothing to do here. + } + }; + + /** + * Validator responsible for validating strings. + * At the moment the only constraint that should be applied to a string feature is the "max length" + */ + class StringValidator implements IValidator + { + public void validate (Object value) throws ValidationException + { + if ((_maxLength != Integer.MIN_VALUE) && (value != null)){ + int length = value.toString().length(); + if (length > _maxLength) { + throw new ValidationException( + ValidationException.MAX_LENGTH, + _maxLength, + _name, + length); + } + } + } + }; + + /** + * Validator responsible for validating numbers. + */ + class NumberValidator implements IValidator + { + public void validate (Object value) throws ValidationException + { + if (value != null) { + double numericValue = ((Number)value).doubleValue(); + if (_minValue != Integer.MIN_VALUE && numericValue < _minValue) { + throw new ValidationException( + ValidationException.MIN_VALUE, + _minValue, + _name, + numericValue); + } + + if (_maxValue != Integer.MIN_VALUE && numericValue > _maxValue) { + throw new ValidationException( + ValidationException.MAX_VALUE, + _maxValue, + _name, + numericValue); + } + } + } + }; + + private AccessMode _accessMode; + private int _minValue = Integer.MIN_VALUE; + private int _maxValue = Integer.MIN_VALUE; + private int _maxLength = Integer.MIN_VALUE; + + private int _optionalIndex; + private int _maskIndex; + + Decoder _decoder = _mandatoryPropertyDecoder; + + private IValidator _validator = EMPTY_VALIDATOR; + + /** + * Validates the given value according to the current validator. + * It delegates the validation to the current installed validator. + * + * @param value the value of this qpid property. + * @throws ValidationException when the given value is violating the current validator constraints. + */ + void validate(Object value) throws ValidationException { + _validator.validate(value); + } + + /** + * Sets the type of this property. + * In addition this method tries to detect if a validator has been associated with the type. + * If no validator is found then the default validator will be used; that is : no validator will be performed on this + * property. + * + * @param type the type of this property. + */ + void setType (Type type) + { + super.setType(type); + try { + Class validatorClass = Class.forName(Configuration.getInstance().getValidatorClassName(type)); + Constructor validatorConstructor = validatorClass.getDeclaredConstructor(QpidProperty.class); + _validator = (IValidator) validatorConstructor.newInstance(this); + LOGGER.debug(Messages.QMAN_200022_VALIDATOR_INSTALLED ,validatorClass.getName(), type); + } catch(Exception exception) { + _validator = EMPTY_VALIDATOR; + LOGGER.debug(Messages.QMAN_200023_VALIDATOR_NOT_FOUND , type); + } + } + + /** + * Gets the value of this property according to its type definition. + * + * @param decoder the decoder used to extract the value. + * @return the value of this feature according to its type definition + */ + Object decodeValue(org.apache.qpid.transport.codec.Decoder decoder,byte [] presenceBitMasks) + { + return _decoder.decodeValue(decoder, presenceBitMasks); + } + + /** + * Sets access mode for this property. + * + * @param accessMode the access mode for this property. + */ + void setAccessMode (AccessMode accessMode) + { + this._accessMode = accessMode; + } + + /** + * Gets the minimum allowed value for this property. + * + * @return the minimum allowed value for this property. + */ + int getMinValue () + { + return _minValue; + } + + /** + * Sets the minimum allowed value for this property. + * + * @param minValue the minimum allowed value for this property. + */ + void setMinValue (int minValue) + { + this._minValue = minValue; + } + + /** + * Gets the maximum allowed value for this property. + * + * @return the maximum allowed value for this property. + */ + int getMaxValue () + { + return _maxValue; + } + + /** + * Sets the masimum allowed value for this property. + * + * @param maxValue the maximum allowed value for this property. + */ + void setMaxValue (int maxValue) + { + this._maxValue = maxValue; + } + + /** + * Gets the max length value for this property. + * + * @return the max length value for this property. + */ + int getMaxLength () + { + return _maxLength; + } + + /** + * Sets the max length value for this property. + * + * @param maxLength the max length value for this property. + */ + void setMaxLength (int maxLength) + { + this._maxLength = maxLength; + } + + /** + * Gets the description of this property. + * + * @return the description of this property. + */ + AccessMode getAccessMode () + { + return _accessMode; + } + + /** + * Marks this property as optional. + * + * @param optional the optional attribute value for this property. + * @param index the index of this optional property + */ + void markAsOptional (int index) + { + this._optionalIndex = index; + this._maskIndex = (_optionalIndex >= 8) ? _optionalIndex-8 : _optionalIndex; + _decoder = _optionalPropertyDecoder; + } + + /** + * Returns true if this property is marked as optional. + * + * @return true if this property is marked as optional, false otherwise. + */ + boolean isOptional () + { + return _decoder == _optionalPropertyDecoder; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java new file mode 100644 index 0000000000..37a652c098 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Qpid statistic definition. + * + * A statistic is a typed member of a class which represents an instrumentation attribute of the class. + * Statistics are always read-only in nature and tend to change rapidly. + * + * @author Andrea Gazzarini + */ +class QpidStatistic extends QpidAttribute +{ + // EMPTY CLASS : Statistic metadata are all defined in superclasses. +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java new file mode 100644 index 0000000000..fc4506779b --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Thrown when a feature (property, statistic, method or event) definition cannot be built due to schema parsing errors. + * + * @author Andrea Gazzarini + */ +public class UnableToBuildFeatureException extends Exception +{ + private static final long serialVersionUID = 5180111828887602836L; + + /** + * Builds a new UnableToBuildFeatureException with the specified cause. + * + * @param exception the exception cause. + */ + UnableToBuildFeatureException(Exception exception, String featureName) + { + super( (featureName != null) ? featureName : "Feature name is not available for debugging purposes." ,exception); + } + + /** + * Builds a new UnableToBuildFeatureException with the specified message. + * + * @param message the detail message. + */ + UnableToBuildFeatureException(String message) + { + super(message); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java new file mode 100644 index 0000000000..3b117e5b9d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +/** + * Thrown when an attempt is made in order to update / change the state of an object and a constraint on that state + * is violated. + * + * @author Andrea Gazzarini + */ +public class ValidationException extends Exception +{ + private static final long serialVersionUID = -5218828669655586205L; + + public final static String MAX_LENGTH = "Max Length"; + public final static String MAX_VALUE = "Max Value"; + public final static String MIN_VALUE = "Min Value"; + + private final String _featureName; + private final Object _featureValue; + + private final Number _constraintValue; + private final String _constraintName; + + /** + * Builds a new validation exception with the specified parameters. + * + * @param constraintName the name of the violated constraint. + * @param constraintValue the value of the violated constraint. + * @param featureName the name of the violating feature. + * @param featureValue the value of the violating feature. + */ + ValidationException(String constraintName,Number constraintValue, String featureName,Object featureValue) + { + super(String.format( + "Property constraint violation : " + + "%s allowed for property %s is %s but received value was %s", + constraintName, + featureName, + constraintValue, + featureValue)); + this._constraintName = constraintName; + this._constraintValue = constraintValue; + this._featureName = featureName; + this._featureValue = featureValue; + } + + /** + * Returns the value of the violating feature. + * + * @return the value of the violating feature. + */ + public Object getFeatureValue () + { + return _featureValue; + } + + /** + * Returns the name of the violating feature. + * + * @return the name of the violating feature. + */ + public String getFeatureName() + { + return _featureName; + } + + /** + * Returns the value of the violated constraint. + * + * @return the value of the violated constraint. + */ + public Number getConstraintValue () + { + return _constraintValue; + } + + /** + * Returns the name of the violated constraint. + * + * @return the name of the violated constraint. + */ + public String getConstraintName () + { + return _constraintName; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java new file mode 100644 index 0000000000..28f5f70c04 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class AbsTime extends Type +{ + public AbsTime() + { + super(Long.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readInt64(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeInt64((Long)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java new file mode 100644 index 0000000000..95cb03b04b --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java @@ -0,0 +1,169 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.UUID; + +import org.apache.qpid.transport.codec.Encoder; + +/** + * It is a simple wrapper for a byte array (for example a 128bin). + * It is used to let QMan deal with an object instead of an array. + * + * @author Andrea Gazzarini + */ +public final class Binary implements Serializable +{ + private static final long serialVersionUID = -6865585077320637567L; + + // Marker internal (empty) interface + private interface State extends Serializable{} + + /** + * Internal state of this object used to denote the situation when the hashcode() method has never been called. + * After the hashcode has been computed this class switches the state of the outer object to the next state. + */ + State hashCodeNotYetComputed = new State() + { + private static final long serialVersionUID = 221632033761266959L; + + @Override + public int hashCode () + { + hashCode = Arrays.hashCode(_bytes); + state = hashCodeAlreadyComputed; + return hashCode; + } + }; + + /** + * Internal state of this object used to denote the situation where the hashcode() method has already been computed. + * Simply it returns the just computed value for the hashcode. + */ + State hashCodeAlreadyComputed = new State() + { + private static final long serialVersionUID = 221632033761266959L; + + @Override + public int hashCode () + { + return hashCode; + } + }; + + private final UUID uuid; + private final byte [] _bytes; + private long _first; + private int hashCode; + + /** Current state (hashcode computation). */ + State state = hashCodeNotYetComputed; + + /** + * Builds a new binary with the given byte array. + * + * @param bytes the wrapped data. + */ + public Binary(byte [] bytes) + { + this._bytes = bytes; + byte [] array = new byte [8]; + System.arraycopy(_bytes, 0, array, 0, 8); + _first = unpack64(array); + uuid = UUID.randomUUID(); + } + + @Override + public int hashCode () + { + return state.hashCode(); + } + + @Override + public boolean equals (Object obj) + { + if(obj instanceof Binary) + { + try + { + Binary binary = (Binary)obj; + return Arrays.equals(_bytes, binary._bytes); + } catch (Exception exception) + { + return false; + } + } + else + { + return false; + } + } + + /** + * Encodes the content (wrapped byte array) of this instance using the given encoder. + * + * @param encoder the encoder used to encode instance content. + */ + public void encode(Encoder encoder) + { + encoder.writeBin128(_bytes); + } + + @Override + public String toString () + { + return uuid.toString(); + } + + /** + * Returns the bank identifier derived from this object identifier. + * + * @return the bank identifier derived from this object identifier. + */ + public long getBankId() + { + return _first & 0x000000000FFFFFFF; + } + + /** + * Returns the broker identifier derived from this object identifier. + * + * @return the broker identifier derived from this object identifier. + */ + public long getBrokerId() + { + return (_first & 281474708275200L) >> 28; + } + + public final long unpack64(byte data[]) { + return ( + ((long) (data[0] & 0xff) << 56) | + ((long)(data[1] & 0xff) << 48) | + ((long)(data[2] & 0xff) << 40) | + ((long)(data[3] & 0xff) << 32) | + ((long)(data[4] & 0xff) << 24) | + ((long)(data[5] & 0xff) << 16) | + ((long)(data[6] & 0xff) << 8) | + (long) data[7] & 0xff); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java new file mode 100644 index 0000000000..c339b870ac --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Boolean extends Type +{ + public Boolean() + { + super(java.lang.Boolean.class); + } + + @Override + public Object decode (Decoder decoder) + { + return (decoder.readUint8() == 1); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUint8( ((java.lang.Boolean)value) ? (short)1 : 0 ); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java new file mode 100644 index 0000000000..a788e2f8e1 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class DeltaTime extends Type +{ + public DeltaTime() + { + super(Long.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readUint64(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUint64((Long)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java new file mode 100644 index 0000000000..d36af3d3df --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Double.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Double extends Type +{ + public Double() + { + super(java.lang.Double.class); + } + + @Override + public Object decode(Decoder decoder) + { + return decoder.readDouble(); + } + + @Override + public void encode(Object value, Encoder encoder) + { + encoder.writeDouble((java.lang.Double)value); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java new file mode 100644 index 0000000000..cb1f6e78a7 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Float.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Float extends Type +{ + public Float() + { + super(java.lang.Float.class); + } + + @Override + public Object decode(Decoder decoder) + { + return decoder.readFloat(); + } + + @Override + public void encode(Object value, Encoder encoder) + { + encoder.writeFloat((java.lang.Float)value); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java new file mode 100644 index 0000000000..f4685f0295 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int16.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Int16 extends Type +{ + public Int16() + { + super(Short.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readInt16(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeInt16((Short)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java new file mode 100644 index 0000000000..ae5be90a2d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int32.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Int32 extends Type +{ + public Int32() + { + super(Integer.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readInt32(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeInt32((Integer)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java new file mode 100644 index 0000000000..f76818344e --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int64.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Int64 extends Type +{ + public Int64() + { + super(Long.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readInt64(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeInt64((Long)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java new file mode 100644 index 0000000000..6f7c3b24d0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Int8.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Int8 extends Type +{ + public Int8() + { + super(Byte.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readInt8(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeInt8((Byte)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java new file mode 100644 index 0000000000..ef5bc7a484 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Map extends Type +{ + public Map() + { + super(java.util.Map.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readMap(); + } + + @SuppressWarnings("unchecked") + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeMap((java.util.Map)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java new file mode 100644 index 0000000000..13e1b68d26 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class ObjectReference extends Type +{ + public ObjectReference() + { + super(byte[].class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readBin128(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + ((Binary)value).encode(encoder); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java new file mode 100644 index 0000000000..42829ce176 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Str16 extends Type +{ + public Str16() + { + super(String.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readStr16(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeStr16((String)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java new file mode 100644 index 0000000000..f9b747ce6d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Str8 extends Type +{ + public Str8() + { + super(String.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readStr8(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeStr8((String)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java new file mode 100644 index 0000000000..7f92ec82b0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java @@ -0,0 +1,101 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +/** + * Layer supertype for all management "types". + * + * @author Andrea Gazzarini + */ +public abstract class Type +{ + /** Java representation of this type. */ + protected final Class javaType; + + /** + * Builds a new management type wiich wraps the given java type. + * + * @param javaType the java type. + */ + Type(Class javaType) + { + this.javaType = javaType; + } + + /** + * Returns the wrapped java type. + * + * @return the wrapped java type. + */ + public Class getJavaType () + { + return javaType; + } + + /** + * Each concrete subclass must define here how to decode incoming data according. + * + * @param decoder the decoder used to extract data. + * @return the "typed" value. + * + */ + public abstract Object decode(Decoder decoder); + + /** + * Returns a string representation of this type. + * + * @return a string representation of this type. + */ + @Override + public String toString () + { + return new StringBuilder(getClass().getName()) + .append(" (wraps ") + .append(javaType.getName()) + .append(')').toString(); + } + + /** + * Identity for types is based on wrapped java type identity. + */ + @Override + public boolean equals (Object obj) + { + return (obj instanceof Type) && getJavaType() == ((Type)obj).getJavaType(); + } + + @Override + public int hashCode () + { + return getJavaType().hashCode(); + } + + /** + * Encodes the given values according to this type definition. + * + * @param value the value to be encoded. + * @param encoder the encoder. + */ + public abstract void encode (Object value,Encoder encoder); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java new file mode 100644 index 0000000000..2d3edd41ea --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Uint16 extends Type +{ + public Uint16() + { + super(Integer.class); + } + + @Override + public Object decode (Decoder decoder) + { + return new Integer(decoder.readUint16()); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUint16((Integer)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java new file mode 100644 index 0000000000..c5fb981bb0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Uint32 extends Type +{ + public Uint32() + { + super(Long.class); + } + + @Override + public Object decode (Decoder decoder) + { + return new Long(decoder.readUint32()); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUint32((Long)value); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java new file mode 100644 index 0000000000..9182f883bf --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Uint64 extends Type +{ + public Uint64() + { + super(Long.class); + } + + @Override + public Object decode (Decoder decoder) + { + return new Long(decoder.readUint64()); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUint64((Long)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java new file mode 100644 index 0000000000..ab7e78856c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Uint8 extends Type +{ + public Uint8() + { + super(Short.class); + } + + @Override + public Object decode (Decoder decoder) + { + return new Short(decoder.readUint8()); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUint8((Short)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java new file mode 100644 index 0000000000..1b3be954d6 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import java.util.UUID; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + +public class Uuid extends Type +{ + public Uuid() + { + super(UUID.class); + } + + @Override + public Object decode (Decoder decoder) + { + return decoder.readUuid(); + } + + @Override + public void encode (Object value, Encoder encoder) + { + encoder.writeUuid((UUID)value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java new file mode 100644 index 0000000000..fc9819fce4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java @@ -0,0 +1,183 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.qpid.api.Message; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.domain.handler.base.IMessageHandler; +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.nclient.util.MessageListener; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.util.Logger; + +/** + * Message listener used for processing incoming messages. + * So it is installed as a consumer on a specific channel and when a new message arrives: + * + * 1) Performs a sanity check on the message (magic number, sequence number) + * 2) Extracts the opcode and looks for one message handler associated with that opcode. + * 3) If a message handler is found the delegates the message processing; otherwise a log message is written to indicate + * that the message will be skipped. + * + * @author Andrea Gazzarini + */ +class BrokerMessageListener implements MessageListener +{ + private final static Logger LOGGER = Logger.get(BrokerMessageListener.class); + + private static class Log + { + // Debugs the content of the incoming message. + static void debugIncomingMessage(ByteBuffer message) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(Messages.QMAN_200001_INCOMING_MESSAGE_HAS_BEEN_RECEIVED, Arrays.toString(message.array())); + } + } + + // Debugs all the configured handlers. + static void debugConfiguredHandlers (Map _handlers) + { + if (LOGGER.isDebugEnabled()) + { + for (Entry entry : _handlers.entrySet()) + { + LOGGER.debug(Messages.QMAN_200002_OPCODE_HANDLER_ASSOCIATION,entry.getKey(),entry.getValue()); + } + } + } + } + + Map _handlers = new HashMap(); + private DomainModel _domainModel; + + /** + * Builds a new message listener with the given broker domain model. + * + * @param model the managed broker domain model. + */ + BrokerMessageListener(DomainModel model) + { + this._domainModel = model; + } + + /** + * When a new message arrives this method is called. + * 1) Performs a sanity check on the message (magic number, sequence number) + * 2) Extracts the opcode and looks for one message handler associated with that opcode. + * 3) If a message handler is found the delegates the message processing; otherwise a log message is written to indicate + * that the message will be skipped. + * + * @param message the incoming message. + */ + public void onMessage (Message compoundMessage) + { + try + { + MessageTokenizer tokenizer = new MessageTokenizer(compoundMessage); + while (tokenizer.hasMoreElements()) + { + dispatch(tokenizer.nextElement()); + } + } catch(IOException exception) + { + LOGGER.error(exception,Messages.QMAN_100002_MESSAGE_READ_FAILURE); + } catch(Exception exception) + { + LOGGER.error(exception,Messages.QMAN_100003_MESSAGE_PROCESS_FAILURE); + } + } + + /** + * Configures a new handler with this listener. + * After that, each time a message arrives with the specified opcode, this handler will be responsible for + * processing. + * Note that calling this method will switch this listener to a WORKING state. + * + * @param opcode the operation code. + * @param handler the message handler. + */ + void setHandlers(Map handlers) + { + for (Entry entry : handlers.entrySet()) + { + char opcode = entry.getKey(); + IMessageHandler handler = entry.getValue(); + try + { + handler.setDomainModel(_domainModel); + _handlers.put(opcode, handler); + } catch (Exception exception) { + LOGGER.error(exception, + Messages.QMAN_100004_HANDLER_INITIALIZATION_FAILURE, + opcode); + } + } + } + + + + /** + * Dispatches the given message to the appropriate handler. + * + * @param message + * the incoming message. + * @throws IOException + * when the message content cannot be read. + */ + private void dispatch(Message message) throws IOException + { + ByteBuffer buffer = message.readData(); + + String magicNumber = new String(new byte[] {buffer.get(),buffer.get(),buffer.get()}); + if (!Protocol.MAGIC_NUMBER.equals(magicNumber)) + { + LOGGER.error(Messages.QMAN_100001_BAD_MAGIC_NUMBER_FAILURE,magicNumber); + return; + } + + char opcode = (char)buffer.get(); + + IMessageHandler handler = _handlers.get(opcode); + if (handler != null) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(buffer); + + LOGGER.debug(Messages.QMAN_200003_MESSAGE_FORWARDING,opcode,handler); + + handler.process(decoder,decoder.readSequenceNo()); + } else + { + LOGGER.warn(Messages.QMAN_300001_MESSAGE_DISCARDED,opcode); + Log.debugConfiguredHandlers(_handlers); + } + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java new file mode 100644 index 0000000000..a6f5ab90cc --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java @@ -0,0 +1,249 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +import java.util.UUID; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.configuration.BrokerConnectionData; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.transport.util.Logger; + +/** + * This is the Object representation of a management client. + * According to specification : "A software component that is separate from the messaging broker, connected to the + * management broker via an AMQP connection, which allows any software component to be managed remotely by QPID." + * + * @author Andrea Gazzarini + */ +public final class ManagementClient +{ + private final static Logger LOGGER = Logger.get(ManagementClient.class); + + private final String _managementQueueName; + private final String _methodReplyQueueName; + + private DomainModel _domainModel; + private QpidService _service; + + private final BrokerConnectionData _connectionData; + + /** + * Builds a new ManagementClient with the given identifier and connection data. + * + * @param brokerId the broker identifier. + * @param connectionData the broker connection data (host, port, etc...) + */ + ManagementClient(UUID brokerId,BrokerConnectionData connectionData) + { + _connectionData = connectionData; + _service = new QpidService(brokerId); + _domainModel = new DomainModel(brokerId); + _managementQueueName = Configuration.getInstance().getManagementQueueName(); + _methodReplyQueueName = Configuration.getInstance().getMethodReplyQueueName(); + } + + @Override + public String toString() + { + return _connectionData.toString(); + } + + /** + * Returns the connection data associated with this management client. + * + * @return the connection data associated with this management client. + */ + public BrokerConnectionData getBrokerConnectionData() + { + return _connectionData; + } + + /** + * Establishing initial communication Between Client and Broker. + * According to specification : + * "Communication is established between the management client and management agent using normal AMQP procedures. + * The client creates a connection to the broker and then establishes a session with its corresponding channel. + * Two private queues are then declared. + * A management queue is declared and bound to the qpid.management exchange with "mgmt.#" as routing key; in that + * way all management-related messages sent to the exchange will be received by this client. + * When a client successfully binds to the qpid.management exchange, the management agent schedules a schema + * broadcast to be sent to the exchange. + * The agent will publish, via the exchange, a description of the schema for all manageable objects in its control. That + * schema is therefore received by this service and it will be part of service's domain model." + * + * @throws StartupFailureException when this management client cannot perform startup operations due to an error. + */ + void estabilishFirstConnectionWithBroker() throws StartupFailureException{ + try { + connectWithBroker(); + + createAndBindMethodReplyQueue(); + createAndBindManagementQueue(); + + registerConsumerOnManagementQueue(); + registerConsumerOnMethodReplyQueue(); + + synchronize(); + } catch(Exception exception) + { + try { + _service.close(); + } catch(Exception ignore) + { + } + throw new StartupFailureException(exception); + } + } + + /** + * Shutdown procedure for this management client. + */ + void shutdown () + { + LOGGER.info(Messages.QMAN_000011_SHUTDOWN_INITIATED,_domainModel.getBrokerId()); + + removeMethodReplyConsumer(); + destroyAndUnbingMethodReplyQueue(); + + removeManagementConsumer(); + destroyAndUnbingManagementQueue(); + + _domainModel.releaseResources(); + + _service.close(); + + LOGGER.info(Messages.QMAN_000012_MANAGEMENT_CLIENT_SHUT_DOWN,_domainModel.getBrokerId()); + } + + /** + * Registers a consumer (that is, a listener) on the method-reply queue. + */ + private void registerConsumerOnMethodReplyQueue () + { + BrokerMessageListener methodReplyChannelListener = new BrokerMessageListener(_domainModel); + methodReplyChannelListener.setHandlers(Configuration.getInstance().getMethodReplyQueueHandlers()); + _service.createSubscription(_methodReplyQueueName, _methodReplyQueueName, methodReplyChannelListener); + + LOGGER.info(Messages.QMAN_000013_METHOD_REPLY_CONSUMER_INSTALLED, _domainModel.getBrokerId()); + } + + /** + * Registers a consumer (listener) on the management queue. + */ + private void registerConsumerOnManagementQueue () + { + BrokerMessageListener managementChannelListener = new BrokerMessageListener(_domainModel); + managementChannelListener.setHandlers(Configuration.getInstance().getManagementQueueHandlers()); + _service.createSubscription(_managementQueueName, _managementQueueName, managementChannelListener); + + LOGGER.info(Messages.QMAN_000014_MANAGEMENT_CONSUMER_INSTALLED, _domainModel.getBrokerId()); + } + + /** + * Declares a management queue and bound it to the "qpid.management" exchange with "mgmt.#" as routing key; + */ + private void createAndBindManagementQueue () + { + _service.declareQueue(_managementQueueName); + _service.declareBinding( + _managementQueueName, + Names.MANAGEMENT_EXCHANGE, + Names.MANAGEMENT_ROUTING_KEY); + + LOGGER.info(Messages.QMAN_000015_MANAGEMENT_QUEUE_DECLARED,_managementQueueName,_domainModel.getBrokerId()); + } + + /** + * Declares a private queue for receiving method replies (after method invocations). + * This queue is bound to the amq.direct exchange using a routing key equal to the name of the queue. + */ + private void createAndBindMethodReplyQueue () + { + _service.declareQueue(_methodReplyQueueName); + _service.declareBinding(_methodReplyQueueName, Names.AMQ_DIRECT_QUEUE, _methodReplyQueueName); + + LOGGER.info(Messages.QMAN_000016_METHOD_REPLY_QUEUE_DECLARED,_methodReplyQueueName, _domainModel.getBrokerId()); + } + + /** + * Removes the method-reply queue consumer. + */ + private void removeMethodReplyConsumer() + { + _service.removeSubscription(_methodReplyQueueName); + + LOGGER.info(Messages.QMAN_000017_CONSUMER_HAS_BEEN_REMOVED,_methodReplyQueueName,_domainModel.getBrokerId()); + } + + /** + * Unbind the method reply queue and after that destroy it from remote broker. + */ + private void destroyAndUnbingMethodReplyQueue() + { + _service.declareUnbinding(_methodReplyQueueName, Names.AMQ_DIRECT_QUEUE, _methodReplyQueueName); + _service.deleteQueue(_methodReplyQueueName); + + LOGGER.info(Messages.QMAN_000018_QUEUE_UNDECLARED,_methodReplyQueueName,_domainModel.getBrokerId()); + } + + /** + * Removes the management queue consumer. + */ + private void removeManagementConsumer() + { + _service.removeSubscription(_managementQueueName); + + LOGGER.info(Messages.QMAN_000017_CONSUMER_HAS_BEEN_REMOVED,_managementQueueName,_domainModel.getBrokerId()); + } + + /** + * Unbind the management queue and after that destroy it from remote broker. + */ + private void destroyAndUnbingManagementQueue() + { + _service.declareUnbinding(_managementQueueName, Names.MANAGEMENT_EXCHANGE, Names.MANAGEMENT_ROUTING_KEY); + _service.deleteQueue(_managementQueueName); + + LOGGER.info(Messages.QMAN_000018_QUEUE_UNDECLARED, _managementQueueName,_domainModel.getBrokerId()); + } + + /** + * Connects this client with the broker. + * + * @throws QpidException when it's not possibile to connect with the broker. + */ + private void connectWithBroker() throws Exception + { + _service.connect(); + } + + /** + * All the Management client commands are asynchronous. + * Synchronous behavior is achieved through invoking the sync method. + */ + private void synchronize() + { + _service.sync(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java new file mode 100644 index 0000000000..9275255517 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MessageTokenizer.java @@ -0,0 +1,152 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.domain.services; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.LinkedList; + +import org.apache.qpid.api.Message; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.nclient.util.ByteBufferMessage; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.util.Logger; + +/** + * The message tokenizer class allows a multi message listener to break a + * message into tokens where each token is itself a valid AMQP message. + * + * @author Andrea Gazzarini + * @see QPID-1368 + */ +class MessageTokenizer implements Enumeration +{ + private final static Logger LOGGER = Logger.get(MessageTokenizer.class); + + static byte [] MAGIC_NUMBER_BYTES; + + private LinkedList _messages = new LinkedList(); + private Iterator _iterator; + + static + { + try + { + MAGIC_NUMBER_BYTES = Protocol.MAGIC_NUMBER.getBytes("UTF-8"); + } catch(Exception exception) + { + throw new ExceptionInInitializerError(exception); + } + } + + /** + * Builds a new Message tokenizer with the given message. + * Note that if the given message is not a "compound" message this tokenizer will producer only one token; + * That is, the token is a message equals to the given message. + * + * @param compoundMessage the compound message + * @throws IOException when it's not possible to read the given message content. + */ + MessageTokenizer(Message compoundMessage) throws IOException + { + build(compoundMessage); + } + + public boolean hasMoreElements() + { + return _iterator.hasNext(); + } + + public Message nextElement() + { + return _iterator.next(); + } + + /** + * Retruns the number of the tokens produced by this tokenizer. + * + * @return the number of the tokens produced by this tokenizer. + */ + public int countTokens() + { + return _messages.size(); + } + + // Internal methods used for splitting the multi message byte array. + int indexOf(byte[] source, int startIndex) + { + int currentSourceIndex; + int currentExampleIndex; + + if (startIndex + 3 > source.length) + return -1; + + for (currentSourceIndex = startIndex; currentSourceIndex <= source.length - 3; currentSourceIndex++) + { + for (currentExampleIndex = 0; currentExampleIndex < 3; currentExampleIndex++) + { + if (source[currentSourceIndex + currentExampleIndex] != MAGIC_NUMBER_BYTES[currentExampleIndex]) + break; + } + + if (currentExampleIndex == 3) + return currentSourceIndex; + } + return -1; + } + + // Internal method used for building the tokens. + private void build(Message compoundMessage) throws IOException + { + int startIndex = 0; + int indexOfMagicNumber = 0; + + BBDecoder decoder = new BBDecoder(); + decoder.init(compoundMessage.readData()); + byte [] source = decoder.readReaminingBytes(); + + int howManyTokens = 1; + + while ((indexOfMagicNumber = indexOf(source, startIndex+1)) != -1) + { + addMessageToken(source, startIndex, (indexOfMagicNumber-startIndex)); + startIndex = indexOfMagicNumber; + howManyTokens++; + } + addMessageToken(source, startIndex, (source.length-startIndex)); + _iterator = _messages.iterator(); + + LOGGER.debug(Messages.QMAN_200031_COMPOUND_MESSAGE_CONTAINS,howManyTokens); + }; + + // Builds & adds a new "message" token + private void addMessageToken(byte [] source,int startIndex,int length) throws IOException + { + byte [] messageData = new byte[length]; + System.arraycopy(source, startIndex, messageData, 0, messageData.length); + Message message = new ByteBufferMessage(); + message.appendData(messageData); + _messages.add(message); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java new file mode 100644 index 0000000000..26fd8eee24 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/MethodInvocationException.java @@ -0,0 +1,50 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +public class MethodInvocationException extends Exception +{ + private static final long serialVersionUID = -7772343434879470351L; + private final long _returnCode; + private final String _statusText; + + public MethodInvocationException(long code, String text) + { + this._returnCode = code; + this._statusText = text; + } + + @Override + public String getMessage () + { + return String.format("Return code : \"%s, reason : \"%s\"",_returnCode,_statusText); + } + + public long getReturnCode () + { + return _returnCode; + } + + public String getStatusText () + { + return _statusText; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java new file mode 100644 index 0000000000..c4c0ce5e74 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java @@ -0,0 +1,412 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.DynamicMBean; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.Notification; +import javax.management.NotificationBroadcasterSupport; +import javax.management.NotificationListener; +import javax.management.ReflectionException; + +import org.apache.log4j.xml.DOMConfigurator; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.configuration.BrokerAlreadyConnectedException; +import org.apache.qpid.management.configuration.BrokerConnectionData; +import org.apache.qpid.management.configuration.BrokerConnectionException; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.configuration.Configurator; +import org.apache.qpid.management.domain.model.JmxService; +import org.apache.qpid.transport.util.Logger; + +/** + * Main entry point for starting Q-Man application. + */ +public class QMan extends NotificationBroadcasterSupport implements DynamicMBean, NotificationListener +{ + private final static Logger LOGGER = Logger.get(QMan.class); + private final List managementClients = new ArrayList(); + + private Configurator _configurator = new Configurator(); + private ThreadPoolExecutor _workManager; + + /** + * Starts QMan. + * @throws StartupFailureException when it's not possible to proceed with startup. + */ + public void start() throws StartupFailureException + { + LOGGER.info(Messages.QMAN_000001_STARTING_QMAN); + LOGGER.info(Messages.QMAN_000002_READING_CONFIGURATION); + + try + { + registerQManService(); + + _configurator.configure(); + + configureWorkManager(); + + LOGGER.info(Messages.QMAN_000019_QMAN_STARTED); + } catch(Exception exception) { + LOGGER.error(exception,Messages.QMAN_100018_UNABLE_TO_STARTUP_CORRECTLY ); + throw new StartupFailureException(exception); + } + } + + /** + * Connects Q-Man with a broker defined by the given parameter. + * + * @param host the hostname where the broker is running. + * @param port the port where the broker is running. + * @param username the username for connecting with the broker. + * @param password the password for connecting with the broker. + * @param virtualHost the virtual host. + * @param initialPoolCapacity the number of the connection that must be immediately opened. + * @param maxPoolCapacity the maximum number of opened connection. + * @param maxWaitTimeout the maximum amount of time that a client will wait for obtaining a connection. + * @throws MBeanException when it's not possible to connect with the broker. + */ + public void addBroker( + String host, + int port, + String username, + String password, + String virtualHost, + int initialPoolCapacity, + int maxPoolCapacity, + long maxWaitTimeout) throws BrokerAlreadyConnectedException, BrokerConnectionException + { + Configurator configurator = new Configurator(); + try { + UUID brokerId = UUID.randomUUID(); + BrokerConnectionData data = configurator.createAndReturnBrokerConnectionData( + brokerId, + host, + port, + username, + password, + virtualHost, + initialPoolCapacity, + maxPoolCapacity, + maxWaitTimeout); + createManagementClient(brokerId, data); + } catch (BrokerAlreadyConnectedException exception) + { + LOGGER.warn(Messages.QMAN_300003_BROKER_ALREADY_CONNECTED, exception.getBrokerConnectionData()); + throw exception; + } + } + + /** + * Stop Qman + */ + public void stop() + { + LOGGER.info(Messages.QMAN_000020_SHUTTING_DOWN_QMAN); + try + { + for (ManagementClient client : managementClients) + { + client.shutdown(); + } + } catch(Exception exception) + { + } + LOGGER.info(Messages.QMAN_000021_SHUT_DOWN); + } + + /** + * Creates a management client using the given data. + * + * @param brokerId the broker identifier. + * @param data the broker connection data. + */ + public void createManagementClient(UUID brokerId, BrokerConnectionData data) + { + try + { + ManagementClient client = new ManagementClient(brokerId,data); + client.estabilishFirstConnectionWithBroker(); + managementClients.add(client); + + LOGGER.info(Messages.QMAN_000004_MANAGEMENT_CLIENT_CONNECTED,brokerId); + } catch(StartupFailureException exception) { + LOGGER.error(exception, Messages.QMAN_100017_UNABLE_TO_CONNECT,brokerId,data); + } + } + + /** + * Returns the list of management clients currently handled by QMan. + * + * @return the list of management clients currently handled by QMan. + */ + public List getManagementClients() + { + return managementClients; + } + + /** + * Injects the configurator on this QMan instance. + * That configutator later will be responsible to manage the configuration. + * + * @param configurator the configurator to be injected. + */ + public void setConfigurator(Configurator configurator){ + this._configurator = configurator; + } + + /** + * Main method used for starting Q-Man. + * + * @param args the command line arguments. + */ + public static void main (String[] args) + { + if (args.length == 1) + { + String logFileName = args[0]; + DOMConfigurator.configureAndWatch(logFileName,5000); + } + + final QMan qman = new QMan(); + + Thread hook = new Thread() + { + @Override + public void run () + { + qman.stop(); + } + }; + + Runtime.getRuntime().addShutdownHook(hook); + try + { + qman.start(); + + System.out.println("Type \"q\" to quit."); + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + while ( !"q".equals(reader.readLine()) ) + { + + } + Runtime.getRuntime().removeShutdownHook(hook); + qman.stop(); + System.exit(-1); + } catch (StartupFailureException exception) + { + qman.stop(); + System.exit(-1); + } catch (IOException exception) + { + System.exit(-1); + } + } + + /** + * Not implemented for this MBean. + */ + public Object getAttribute(String attribute) + { + return null; + } + + /** + * Not implemented for this MBean. + */ + public AttributeList getAttributes(String[] attributes) + { + return null; + } + + /** + * Returns the metadata for this MBean + * + * @return the metadata for this MBean + */ + public MBeanInfo getMBeanInfo() + { + MBeanParameterInfo parameters [] = new MBeanParameterInfo[8]; + + parameters[0] = new MBeanParameterInfo( + "host", + String.class.getName(), + "The IP address or DNS name that Qpid Broker uses to listen for incoming connections."); + parameters[1] = new MBeanParameterInfo( + "port", + int.class.getName(), + "The port number that Qpid Broker uses to listen for incoming connections."); + parameters[2] = new MBeanParameterInfo( + "username", + String.class.getName(), + "The Qpid account name used in the physical connection."); + parameters[3] = new MBeanParameterInfo( + "password", + String.class.getName(), + "The Qpid account password used in the physical connection."); + parameters[4]= new MBeanParameterInfo( + "virtualHost", + String.class.getName(), + "The virtualHost name."); + parameters[5]= new MBeanParameterInfo( + "initialPoolCapacity", + int.class.getName(), + "The number of physical connections (between 0 and a positive 32-bit integer) to create when creating the (Qpid) connection pool."); + parameters[6]= new MBeanParameterInfo( + "maxPoolCapacity", + int.class.getName(), + "The maximum number of physical database connections (between 0 and a positive 32-bit integer) that the (Qpid) connection pool can contain. "); + parameters[7]= new MBeanParameterInfo( + "maxWaitTimeout", + long.class.getName(), + "The maximum amount of time to wait for an idle connection.A value of -1 indicates an illimted amount of time (i.e. forever)"); + + MBeanOperationInfo operation = new MBeanOperationInfo( + "addBroker", + "Connects QMan with a broker.", + parameters, + void.class.getName(), + MBeanOperationInfo.ACTION); + + MBeanInfo mbean = new MBeanInfo( + QMan.class.getName(), + "QMan Management & Administration interface.", + null, + null, + new MBeanOperationInfo[]{operation}, + null); + + return mbean; + } + + /** + * Invokes an operation on QMan (MBean). + * + * @param actionName the operation name. + * @param params the operation parameters. + * @param signature the operation signature. + * @return the result of the invocation (if the operation is not void); + * @exception MBeanException Wraps a java.lang.Exception thrown by the MBean's invoked method. + * @exception ReflectionException Wraps a java.lang.Exception thrown while trying to invoke the method + */ + public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException + { + if (Names.ADD_BROKER_OPERATION_NAME.equals(actionName)) + { + try + { + addBroker( + (String)params[0], + (Integer)params[1], + (String)params[2], + (String)params[3], + (String)params[4], + (Integer)params[5], + (Integer)params[6], + (Long)params[7]); + } catch(Exception exception) + { + throw new MBeanException(exception); + } + } else + { + throw new ReflectionException(new NoSuchMethodException(actionName)); + } + return null; + } + + /** + * Not implemented for this MBean. + */ + public void setAttribute(Attribute attribute) + { + } + + /** + * Not implemented for this MBean. + */ + public AttributeList setAttributes(AttributeList attributes) + { + return null; + } + + /** + * Simply dispatches the incoming notification to registered listeners. + * Consider that the notification is sent asynchronously so the QMan current thread is not + * waiting for completion of receiver task. + * + * @param notification the incoming notification. + * @param handback the context associated to this notification. + */ + public void handleNotification(final Notification notification, Object handback) + { + _workManager.execute(new Runnable(){ + public void run() + { + sendNotification(notification); + } + }); + } + + /** + * Registers QMan as an MBean on MBeanServer. + * + * @throws MBeanException when it's not possible to proceeed with registration. + */ + private void registerQManService() throws MBeanException + { + JmxService service = new JmxService(); + service.registerQManService(this); + + LOGGER.info(Messages.QMAN_000023_QMAN_REGISTERED_AS_MBEAN); + } + + /** + * Configures work manager component. + */ + private void configureWorkManager() + { + Configuration configuration = Configuration.getInstance(); + _workManager = new ThreadPoolExecutor( + configuration.getWorkerManagerPoolSize(), + configuration.getWorkerManagerMaxPoolSize(), + configuration.getWorkerManagerKeepAliveTime(), + TimeUnit.MILLISECONDS, + new ArrayBlockingQueue(30)); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java new file mode 100644 index 0000000000..bd7d305184 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java @@ -0,0 +1,361 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +import java.io.IOException; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.qpid.api.Message; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.configuration.QpidDatasource; +import org.apache.qpid.management.domain.model.QpidMethod; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.management.messages.MethodInvocationRequestMessage; +import org.apache.qpid.management.messages.SchemaRequestMessage; +import org.apache.qpid.nclient.util.MessageListener; +import org.apache.qpid.nclient.util.MessagePartListenerAdapter; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.MessageAcceptMode; +import org.apache.qpid.transport.MessageAcquireMode; +import org.apache.qpid.transport.MessageCreditUnit; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.Option; +import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.SessionException; +import org.apache.qpid.transport.SessionListener; +import org.apache.qpid.transport.util.Logger; + +/** + * Qpid Broker facade. + * + * @author Andrea Gazzarini + */ +public class QpidService implements SessionListener +{ + private final static Logger LOGGER = Logger.get(QpidService.class); + + private UUID _brokerId; + private Connection _connection; + private Session _session; + private Map _listeners; + + /** + * Builds a new service with the given connection data. + * + * @param connectionData the connection data of the broker. + */ + public QpidService(UUID brokerId) + { + this._brokerId = brokerId; + } + + /** + * Estabilishes a connection with the broker. + * + * @throws QpidException in case of connection failure. + */ + public void connect() throws Exception + { + _connection = QpidDatasource.getInstance().getConnection(_brokerId); + _listeners = new ConcurrentHashMap(); + _session = _connection.createSession(0); + _session.setSessionListener(this); + } + + public void opened(Session ssn) {} + + public void resumed(Session ssn) {} + + public void message(Session ssn, MessageTransfer xfr) + { + MessagePartListenerAdapter l = _listeners.get(xfr.getDestination()); + if (l == null) + { + LOGGER.error("unhandled message: %s", xfr); + } + else + { + l.messageTransfer(xfr); + } + } + + + public void exception(Session ssn, SessionException exc) + { + + } + + public void closed(Session ssn) {} + + /** + * All the previously entered outstanding commands are asynchronous. + * Synchronous behavior is achieved through invoking this method. + */ + public void sync() + { + _session.sync(); + } + + /** + * Closes communication with broker. + */ + public void close() + { + try + { + _session.close(); + _session = null; + _listeners = null; + } catch (Exception e) + { + } + try + { + _connection.close(); + _connection = null; + } catch (Exception e) + { + } + } + + /** + * Associate a message listener with a destination therefore creating a new subscription. + * + * @param queueName The name of the queue that the subscriber is receiving messages from. + * @param destinationName the name of the destination, or delivery tag, for the subscriber. + * @param listener the listener for this destination. + * + * @see Session#messageSubscribe(String, String, short, short, org.apache.qpid.nclient.MessagePartListener, java.util.Map, org.apache.qpid.transport.Option...) + */ + public void createSubscription(String queueName, String destinationName, MessageListener listener) + { + _listeners.put(destinationName, new MessagePartListenerAdapter(listener)); + _session.messageSubscribe + (queueName, + destinationName, + MessageAcceptMode.NONE, + MessageAcquireMode.PRE_ACQUIRED, + null, 0, null); + + _session.messageFlow(destinationName, MessageCreditUnit.BYTE, Session.UNLIMITED_CREDIT); + _session.messageFlow(destinationName, MessageCreditUnit.MESSAGE, Session.UNLIMITED_CREDIT); + + LOGGER.debug(Messages.QMAN_200025_SUBSCRIPTION_DECLARED,queueName,destinationName); + } + + /** + * Removes a previously declared consumer from the broker. + * + * @param destinationName the name of the destination, or delivery tag, for the subscriber. + * @see Session#messageCancel(String, Option...) + */ + public void removeSubscription(String destinationName) + { + _session.messageCancel(destinationName); + LOGGER.debug(Messages.QMAN_200026_SUBSCRIPTION_REMOVED,destinationName); + } + + /** + * Declares a queue on the broker with the given name. + * + * @param queueName the name of the declared queue. + * @see Session#queueDeclare(String, String, java.util.Map, Option...) + */ + public void declareQueue(String queueName) + { + _session.queueDeclare(queueName, null, null); + LOGGER.debug(Messages.QMAN_200027_QUEUE_DECLARED,queueName); + } + + /** + * Removes the queue with the given name from the broker. + * + * @param queueName the name of the queue. + * @see Session#queueDelete(String, Option...) + */ + public void deleteQueue(String queueName) + { + _session.queueDelete(queueName); + LOGGER.debug(Messages.QMAN_200028_QUEUE_REMOVED,queueName); + } + + /** + * Binds (on the broker) a queue with an exchange. + * + * @param queueName the name of the queue to bind. + * @param exchangeName the exchange name. + * @param routingKey the routing key used for the binding. + * @see Session#exchangeBind(String, String, String, java.util.Map, Option...) + */ + public void declareBinding(String queueName, String exchangeName, String routingKey) + { + _session.exchangeBind(queueName, exchangeName, routingKey, null); + LOGGER.debug(Messages.QMAN_200029_BINDING_DECLARED,routingKey,queueName,exchangeName); + } + + /** + * Removes a previously declare binding between an exchange and a queue. + * + * @param queueName the name of the queue. + * @param exchangeName the name of the exchange. + * @param routingKey the routing key used for binding. + */ + public void declareUnbinding(String queueName, String exchangeName, String routingKey) + { + _session.exchangeUnbind(queueName, exchangeName, routingKey); + LOGGER.debug(Messages.QMAN_200030_BINDING_REMOVED,routingKey,queueName,exchangeName); + } + + /** + * Sends a command message with the given data on the management queue. + * + * @param messageData the command message content. + */ + + /** + * Requests a schema for the given package.class.hash. + * + * @param packageName the package name. + * @param className the class name. + * @param schemaHash the schema hash. + * @throws IOException when the schema request cannot be sent. + */ + public void requestSchema(final String packageName, final String className, final Binary schemaHash) throws IOException + { + Message message = new SchemaRequestMessage() + { + @Override + protected String className () + { + return className; + } + + @Override + protected String packageName () + { + return packageName; + } + + @Override + protected Binary schemaHash () + { + return schemaHash; + } + }; + + sendMessage(message); + } + + /** + * Invokes an operation on a broker object instance. + * + * @param packageName the package name. + * @param className the class name. + * @param schemaHash the schema hash of the corresponding class. + * @param objectId the object instance identifier. + * @param parameters the parameters for this invocation. + * @param method the method (definition) invoked. + * @param bankId the object bank identifier. + * @param brokerId the broker identifier. + * @return the sequence number used for this message. + * @throws MethodInvocationException when the invoked method returns an error code. + * @throws UnableToComplyException when it wasn't possibile to invoke the requested operation. + */ + public void invoke( + final String packageName, + final String className, + final Binary schemaHash, + final Binary objectId, + final Object[] parameters, + final QpidMethod method, + final int sequenceNumber, + final long bankId, + final long brokerId) throws MethodInvocationException, UnableToComplyException + { + Message message = new MethodInvocationRequestMessage(bankId, brokerId) + { + + @Override + protected int sequenceNumber () + { + return sequenceNumber; + } + + protected Binary objectId() { + return objectId; + } + + protected String packageName() + { + return packageName; + } + + protected String className() + { + return className; + } + + @Override + protected QpidMethod method () + { + return method; + } + + @Override + protected Object[] parameters () + { + return parameters; + } + + @Override + protected Binary schemaHash () + { + return schemaHash; + } + }; + + try { + sendMessage(message); + sync(); + } catch(Exception exception) { + throw new UnableToComplyException(exception); + } + } + + /** + * Sends a command message. + * + * @param message the command message. + * @throws IOException when the message cannot be sent. + */ + public void sendMessage(Message message) throws IOException + { + _session.messageTransfer( + Names.MANAGEMENT_EXCHANGE, + MessageAcceptMode.EXPLICIT, + MessageAcquireMode.PRE_ACQUIRED, + message.getHeader(), + message.readData()); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java new file mode 100644 index 0000000000..e6d99971cd --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/SequenceNumberGenerator.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +/** + * Sequence number generator utility class. + * + * @author Andrea Gazzarini + */ +public class SequenceNumberGenerator +{ + private static int sequenceNumber; + + /** + * Returns a valid sequence number. + * + * @return a sequence number. + */ + public static synchronized int getNextSequenceNumber() + { + return sequenceNumber++; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java new file mode 100644 index 0000000000..9da8832624 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +/** + * Thrown in case of service startup failure. + * For example the configuration file couldn't be read because is not well-formed. + * + * @author Andrea Gazzarini. + */ +public class StartupFailureException extends Exception +{ + private static final long serialVersionUID = -4102037574602857703L; + + /** + * Builds a new StartupFailureException with the given exception. + * + * @param exception the exception cause. + */ + public StartupFailureException(Exception exception) + { + super(exception); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java new file mode 100644 index 0000000000..2ab9a41e75 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/services/UnableToComplyException.java @@ -0,0 +1,31 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +public class UnableToComplyException extends Exception +{ + public UnableToComplyException(Exception exception) + { + super(exception); + } + + private static final long serialVersionUID = -3071434478559509435L; +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java b/java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java new file mode 100644 index 0000000000..d7f9d8d6f0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/jmx/EntityLifecycleNotification.java @@ -0,0 +1,147 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.jmx; + +import javax.management.Notification; +import javax.management.ObjectName; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.services.SequenceNumberGenerator; + +/** + * Q-Man JMX entity lifecycle notification. + * A notification is sent to interested listener by Q-Man on the following scenarios : + * + *
- A schema (class / event) has been requested (Schema request); + *
- A schema (class / event) has been injected (Schema response); + *
- A schema cannot be parsed (probably it is malformed); + *
- An object instance has been created (Instrumentation / Configuration response); + *
- An event instance has been created (Instrumentation / Configuration response); + *
- An object instance has been removed (Instrumentation / Configuration response); + * + * @author Andrea Gazzarini + */ +public class EntityLifecycleNotification extends Notification +{ + private static final long serialVersionUID = -7755773156742412161L; + + public static final String SCHEMA_INJECTED_NOTIFICATION_TYPE = "org.apache.qpid.management.lifecycle.entity.schema.injected"; + public static final String SCHEMA_REQUESTED_NOTIFICATION_TYPE = "org.apache.qpid.management.lifecycle.entity.schema.requested"; + public static final String MALFORMED_SCHEMA_NOTIFICATION_TYPE = "org.apache.qpid.management.lifecycle.error.schema"; + + public static final String INSTANCE_ADDED_NOTIFICATION_TYPE = "qman.lifecycle.entity.instance.created"; + public static final String INSTANCE_REMOVED_NOTIFICATION_TYPE = "qman.lifecycle.entity.instance.removed"; + + private String _packageName = Names.NOT_AVAILABLE; + private String _className = Names.NOT_AVAILABLE; + private String _classKind = Names.NOT_AVAILABLE; + + private ObjectName _objectName; + + /** + * Builds a new notification with the given parameters. + * + * @param type the notification type. + * @param sequenceNumber the sequence number. + * @param packageName the package name. + * @param className the class name. + * @param classKind the class kind (i.e. class or event) + * @param objectName the object name of the affected mbean. + */ + public EntityLifecycleNotification( + String type, + String packageName, + String className, + String classKind, + ObjectName objectName) + { + super( + type, + Names.APPLICATION_NAME, + SequenceNumberGenerator.getNextSequenceNumber()); + + this._className = className; + this._packageName = packageName; + this._classKind = classKind; + this._objectName = objectName; + } + + /** + * Returns the package name of object contained in this notification. + * + * @return the package name of object contained in this notification. + */ + public String getPackageName() + { + return _packageName; + } + + /** + * Returns the class name of object contained in this notification. + * + * @return the class name of object contained in this notification. + */ + public String getClassName() + { + return _className; + } + + /** + * Returns the class kind of object contained in this notification. + * + * @return the class kind of object contained in this notification. + * @see Names#CLASS + * @see Names#EVENT + */ + public String getClassKind() + { + return _classKind; + } + + /** + * Returns the object name of object contained in this notification. + * + * @return the object name of object contained in this notification. + */ + public ObjectName getObjectName() + { + return _objectName; + } + + /** + * Returns a string representation of this notification. + * + * @return a string representation of this notification. + */ + @Override + public String toString() + { + return new StringBuilder() + .append(getType()) + .append(':') + .append(_packageName) + .append('.') + .append(_className) + .append('@') + .append(_objectName) + .toString(); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java b/java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java new file mode 100644 index 0000000000..dec29c1b93 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/jmx/OperationHasBeenInvokedNotification.java @@ -0,0 +1,168 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.jmx; + +import javax.management.Notification; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.handler.impl.InvocationResult; +import org.apache.qpid.management.domain.services.SequenceNumberGenerator; + +/** + * Q-Man JMX method invocation notification. + * This kind of notification is sent to interested listener by Q-Man when + * a method has been invoked (Method invocation request) + * + * @author Andrea Gazzarini + */ +public class OperationHasBeenInvokedNotification extends Notification +{ + private static final long serialVersionUID = -7755773156742412161L; + public static final String NOTIFICATION_TYPE = "org.apache.qpid.management.operation.invoked"; + + private final String _operationName; + private final Object [] _parameters; + private final String [] _signature; + private final Exception _exception; + private final InvocationResult _result; + + /** + * Builds a new notification with the given parameters. + * + * @param type the notification type. + * @param operationName the operation name. + * @param params the operation parameters. + * @param signature the operation signature. + * @param exception the exception raised by the invocation. + */ + public OperationHasBeenInvokedNotification( + String operationName, + Object[] parameters, + String [] signature, + Exception exception) + { + super( + NOTIFICATION_TYPE, + Names.APPLICATION_NAME, + SequenceNumberGenerator.getNextSequenceNumber()); + + this._operationName= operationName; + this._parameters = parameters; + this._signature = signature; + this._result = null; + this._exception = exception; + } + + /** + * Builds a new notification with the given parameters. + * + * @param type the notification type. + * @param operationName the operation name. + * @param params the operation parameters. + * @param signature the operation signature. + * @param objectName the target mbean object name. + * @param result the invocation result. + */ + public OperationHasBeenInvokedNotification( + String operationName, + Object[] parameters, + String [] signature, + InvocationResult result) + { + super( + NOTIFICATION_TYPE, + Names.APPLICATION_NAME, + SequenceNumberGenerator.getNextSequenceNumber()); + + this._operationName= operationName; + this._parameters = parameters; + this._signature = signature; + this._result = result; + this._exception = null; + } + + /** + * Returns the exception raised by this notification + * referred operation. + * + * @return the exception raised by this notification referred operation. + */ + public Exception getException() + { + return _exception; + } + + /** + * Returns the exception raised by this notification + * referred operation. + * + * @return the exception raised by this notification referred operation. + */ + public InvocationResult getResult() + { + return _result; + } + + /** + * Returns the operation name. + * + * @return the operation name. + */ + public String getOperationName() + { + return _operationName; + } + + /** + * Returns the parameters used in method invocation. + * + * @return the parameters used in method invocation. + */ + public Object [] getParameters() + { + return _parameters; + } + + /** + * Returns the signature of the invoked operation. + * + * @return the signature of the invoked operation. + */ + public String [] getSignature() + { + return _signature; + } + + /** + * Returns a string representation of this notification. + * + * @return a string representation of this notification. + */ + @Override + public String toString() + { + return new StringBuilder() + .append(getType()) + .append(':') + .append(_operationName) + .toString(); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java b/java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java new file mode 100644 index 0000000000..2fa20fb456 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/messages/ManagementMessage.java @@ -0,0 +1,189 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.messages; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.apache.qpid.api.Message; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.domain.services.SequenceNumberGenerator; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.codec.BBEncoder; + +/** + * Message implementation used for specific management purposes. + * + * @author Andrea Gazzarini + */ +public abstract class ManagementMessage implements Message +{ + /** + * Strategy interface for building / getting data. + * + * @author Andrea Gazzarini + */ + private interface IDataBuilderStrategy + { + ByteBuffer getData(); + }; + + /** + * Strategy used for retrieving raw data from this message when it has been already encoded. + */ + IDataBuilderStrategy READING = new IDataBuilderStrategy() + { + public ByteBuffer getData() { + return _data; + }; + }; + + /** + * Strategy used for retrieving raw data from this message when it hasn't been already encoded. + */ + IDataBuilderStrategy ACCUMULATING = new IDataBuilderStrategy() + { + public ByteBuffer getData() { + _codec.writeInt8((byte)opcode()); + _codec.writeSequenceNo(sequenceNumber()); + + specificMessageEncoding(); + + _data =_codec.segment(); + _reader = READING; + return _data; + } + }; + + protected BBEncoder _codec; + protected ByteBuffer _data; + private int _messageTransferId; + private IDataBuilderStrategy _reader = ACCUMULATING; + + /** + * Builds an empty management message. + */ + ManagementMessage() + { + _codec = new BBEncoder(100); + _codec.writeMagicNumber(); + } + + /** + * Returns the sequence number that will be used for this message. + * + * @return the sequence number that will be used for this message. + */ + protected int sequenceNumber () + { + return SequenceNumberGenerator.getNextSequenceNumber(); + } + + /** + * Returns the opcode that will be used for this message. + * + * @return the opcode that will be used for this message. + */ + abstract char opcode (); + + /** + * Returns the delivery properties of this message. + * + * @return the delivery properties of this message. + */ + public DeliveryProperties getDeliveryProperties () + { + return Configuration.getInstance().getCommandDeliveryProperties(); + } + + /** + * Returns the header of this message. + * + * @return the header of this message. + */ + public Header getHeader () + { + return Configuration.getInstance().getCommandMessageHeader(); + } + + /** + * Returns the messages header properties of this message. + * + * @return the message header properties of this message. + */ + public MessageProperties getMessageProperties () + { + return Configuration.getInstance().getCommandMessageProperties(); + } + + /** + * Returns the transfer Id of this message. + * + * @return the transfer Id of this message. + */ + public int getMessageTransferId () + { + return _messageTransferId; + } + + /** + * Returns the encoded data of this message. + * + * @return the encoded data of this message. + */ + public ByteBuffer readData () throws IOException + { + return _reader.getData(); + } + + /** + * Sets the header for this message. + * + * @param header the new message header. + */ + public void setHeader (Header header) + { + // N.A. at the moment. + } + + public void appendData (byte[] src) throws IOException + { + } + + public void appendData (ByteBuffer src) throws IOException + { + } + + public void clearData () + { + } + + public void readData (byte[] target) throws IOException + { + } + + /** + * Concrete subclasses (message implementations) must define here their specific data encoding. + */ + abstract void specificMessageEncoding(); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java b/java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java new file mode 100644 index 0000000000..99916085d6 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/messages/MethodInvocationRequestMessage.java @@ -0,0 +1,161 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.messages; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.domain.model.QpidMethod; +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.ReplyTo; +import org.apache.qpid.transport.util.Logger; + +/** + * Abstract representation of a method invocation request message. + * Concrete subclasses must supply the values needed to build & encode the message. + * + * @author Andrea Gazzarini + */ +public abstract class MethodInvocationRequestMessage extends ManagementMessage +{ + private final static Logger LOGGER = Logger.get(MethodInvocationRequestMessage.class); + + private DeliveryProperties _deliveryProperties; + private MessageProperties _messageProperties; + private Header _header; + + /** + * Builds a new method invocation request message with the given target identifiers. + * + * @param bankId the bank identifier. + * @param brokerId the broker identifier. + */ + public MethodInvocationRequestMessage(long bankId, long brokerId) + { + ReplyTo replyTo=new ReplyTo(); + replyTo.setRoutingKey(Configuration.getInstance().getMethodReplyQueueName()); + _messageProperties = new MessageProperties(); + _messageProperties.setReplyTo(replyTo); + + String routingKey = String.format(Names.AGENT_ROUTING_KEY_PREFIX+"%s.%s", brokerId,bankId); + + LOGGER.debug(Messages.QMAN_200032_COMMAND_MESSAGE_ROUTING_KEY, routingKey); + + _deliveryProperties = new DeliveryProperties(); + _deliveryProperties.setRoutingKey(routingKey); + _header = new Header(_deliveryProperties, _messageProperties); + } + + @Override + char opcode () + { + return Protocol.OPERATION_INVOCATION_REQUEST_OPCODE; + } + + /** + * Returns the package name. + * + * @return the package name. + */ + protected abstract String packageName(); + + /** + * Returns the class name. + * + * @return the class name. + */ + protected abstract String className(); + + /** + * Returns the schema hash. + * + * @return the schema hash. + */ + protected abstract Binary schemaHash(); + + /** + * Returns the object identifier. + * + * @return the object identifier. + */ + protected abstract Binary objectId(); + + /** + * Returns the method to be invoked. + * + * @return the method to be invoked. + */ + protected abstract QpidMethod method(); + + /** + * Returns the parameters used for method invocation. + * + * @return the parameters used for method invocation. + */ + protected abstract Object[] parameters(); + + /** + * Returns the delivery properties of this message. + * + * @return the delivery properties of this message. + */ + public DeliveryProperties getDeliveryProperties () + { + return _deliveryProperties; + } + + /** + * Returns the header of this message. + * + * @return the header of this message. + */ + public Header getHeader () + { + return _header; + } + + /** + * Returns the messages header properties of this message. + * + * @return the message header properties of this message. + */ + public MessageProperties getMessageProperties () + { + return _messageProperties; + } + + @Override + void specificMessageEncoding () + { + objectId().encode(_codec); + _codec.writeStr8(packageName()); + _codec.writeStr8(className()); + schemaHash().encode(_codec); + + QpidMethod method = method(); + _codec.writeStr8(method.getName()); + method.encodeParameters(parameters(), _codec); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java b/java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java new file mode 100644 index 0000000000..9df1733649 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/messages/SchemaRequestMessage.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.messages; + +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Abstract representation of a schema request message. + * Concrete subclasses must supply the values needed to build & encode the message. + * + * @author Andrea Gazzarini + */ +public abstract class SchemaRequestMessage extends ManagementMessage +{ + @Override + char opcode () + { + return Protocol.SCHEMA_REQUEST_OPCODE; + } + + /** + * Returns the package name. + * + * @return the package name. + */ + protected abstract String packageName(); + + /** + * Returns the class name. + * + * @return the class name. + */ + protected abstract String className(); + + /** + * Returns the schema hash. + * + * @return the schema hash. + */ + protected abstract Binary schemaHash(); + + @Override + final void specificMessageEncoding () + { + _codec.writeStr8(packageName()); + _codec.writeStr8(className()); + schemaHash().encode(_codec); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java new file mode 100644 index 0000000000..8f73098e20 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/ConnectQManToBroker.java @@ -0,0 +1,89 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.servlet; + +import java.util.UUID; +import java.util.Map.Entry; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.muse.core.platform.mini.MiniServlet; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.configuration.BrokerConnectionData; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.domain.services.QMan; +import org.apache.qpid.transport.util.Logger; + +/** + * When QMan is started and a configuration file is given + * (via system property) with initial broker connection data(s), + * this servlet simply sends connect command(s) to QMan in order + * to estabilish the connection(s) to the requested broker(s). + * + * @author Andrea Gazzarini + */ +public class ConnectQManToBroker extends MiniServlet +{ + private static final long serialVersionUID = 6149614872902682208L; + private final static Logger LOGGER = Logger.get(ConnectQManToBroker.class); + + /** + * Send one or more initial "connect" command(s) to QMan in order + * to estabilish a connection with broker found on the configuration file.. + * Note that this is done only if that configuration file is given (via system + * property) and it is valid. + */ + public void init() + { + Configuration configuration = Configuration.getInstance(); + if (configuration.hasOneOrMoreBrokersDefined()) + { + QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME); + + LOGGER.info(Messages.QMAN_000003_CREATING_MANAGEMENT_CLIENTS); + for (Entry entry : Configuration.getInstance().getConnectionInfos()) + { + qman.createManagementClient(entry.getKey(), entry.getValue()); + } + } else + { + LOGGER.info(Messages.QMAN_000022_NO_BROKER_CONFIGURED); + } + } + + /** + * This is a startup module only so an override of the default servlet + * behaviour must be done in order to prevent incoming http + * requests processing. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException each time this method is called. + */ + @Override + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException + { + throw new ServletException(); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java new file mode 100644 index 0000000000..edd6804e68 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/QManLifeCycleManager.java @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.servlet; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.services.QMan; +import org.apache.qpid.management.domain.services.StartupFailureException; +import org.apache.qpid.transport.util.Logger; + +/** + * QMan JMX lifecycle manager. + * Provides lifecycle management of QMan JMX core including startup and shutdown. + * + * @author Andrea Gazzarini + */ +public class QManLifeCycleManager implements ServletContextListener +{ + private final static Logger LOGGER = Logger.get(QManLifeCycleManager.class); + + /** + * Starts QMan JMX Core. + * + * @param event the application context event. + */ + public void contextInitialized(ServletContextEvent event) + { + try + { + QMan qman = new QMan(); + qman.start(); + event.getServletContext().setAttribute( + Names.APPLICATION_NAME, + qman); + } catch (StartupFailureException exception) + { + LOGGER.error( + exception, + Messages.QMAN_100030_JMX_CORE_STARTUP_FAILURE); + } + } + + /** + * Sutdown QMan JMX Core. + * + * @param event the application context event. + */ + public void contextDestroyed(ServletContextEvent event) + { + ServletContext context = event.getServletContext(); + + QMan qman = (QMan) context.getAttribute(Names.APPLICATION_NAME); + qman.stop(); + + context.removeAttribute(Names.APPLICATION_NAME); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java new file mode 100644 index 0000000000..c6fcde08c4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.servlet; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.wsdm.muse.engine.WSDMAdapterIsolationLayer; +import org.apache.qpid.qman.debug.XmlDebugger; +import org.apache.qpid.transport.util.Logger; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +/** + * QMan Adapter facade. + * This is the main requestor entry point of the WS-DM connector / adapter. + * All WSDM requests will be handled (at higher level) by this servlet. + * + * @author Andrea Gazzarini + */ +public class WSDMAdapter extends HttpServlet +{ + private static final long serialVersionUID = 6149614872902682208L; + private final static Logger LOGGER = Logger.get(WSDMAdapter.class); + private WSDMAdapterIsolationLayer _isolationLayer; + + @Override + public void init() throws ServletException { + LOGGER.debug(Messages.QMAN_000026_WSDM_ADAPTER_STARTS); + + _isolationLayer = new WSDMAdapterIsolationLayer(getServletContext()); + _isolationLayer.initialize(); + + LOGGER.debug(Messages.QMAN_000027_WSDM_ADAPTER_STARTED); + + } + + /** + * Accepts http requests containing a soap envelope (request) and therefore + * acts as the main entry point of whole WS process. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException in case of application failure. + * @throws IOException in case of generic I/O failure. + */ + @Override + protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException + { + PrintWriter writer = response.getWriter(); + + Document soapEnvelopeRequest = null; + String soapEnvelopeResposeAsString = null; + + try + { + soapEnvelopeRequest = XmlUtils.createDocument(request.getInputStream()); + + Document soapEnvelopeResponse = _isolationLayer.handleRequest(soapEnvelopeRequest); + soapEnvelopeResposeAsString = XmlUtils.toString(soapEnvelopeResponse,false,true); + + response.setContentType("text/xml"); + + writer.write(soapEnvelopeResposeAsString); + } catch (SAXException exception) + { + LOGGER.error( + exception, + Messages.QMAN_100019_REQ_OR_RES_MALFORMED); + throw new ServletException(exception); + } finally { + writer.flush(); + + XmlDebugger.debug(soapEnvelopeRequest); + try { + XmlDebugger.debug(soapEnvelopeResposeAsString); + } catch(Exception exception) { + LOGGER.error( + exception, + Messages.QMAN_100019_REQ_OR_RES_MALFORMED); + } + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java new file mode 100644 index 0000000000..09b7309b96 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokerModel.java @@ -0,0 +1,100 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.management.ObjectName; + +import org.apache.qpid.management.Names; + +/** + * Value Object encapsulating a broker management domain model. + * + * @author Andrea Gazzarini + */ +public class BrokerModel +{ + private Map> _objectsByType = new HashMap>(); + private String _id; + + /** + * Adds a new object to this domain model. + * + * @param name the object name of the JMX entity. + */ + void addObject(ObjectName name) + { + String packageName = name.getKeyProperty(Names.PACKAGE); + String className = name.getKeyProperty(Names.CLASS); + if (className != null) + { + String fqn = packageName+"."+className; + + List objects = _objectsByType.get(fqn); + if (objects == null) + { + objects = new ArrayList(); + _objectsByType.put(fqn,objects); + } + objects.add(name); + } + } + + /** + * Gets the identifier of the owner of this model. + * + * @return the identifier of the owner of this model. + */ + public String getId() + { + return _id; + } + + /** + * Sets the identifier of the owner of this model. + * + * @param id the identifier of the owner of this model. + */ + public void setId(String id) + { + this._id = id; + } + + public Set getCategoryNames() + { + return _objectsByType.keySet(); + } + + public List getCategory(String name) + { + return _objectsByType.get(name); + } + + public int getCategoryCount() + { + return _objectsByType.keySet().size(); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java new file mode 100644 index 0000000000..509c86c08b --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/BrokersManagementAction.java @@ -0,0 +1,204 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.configuration.BrokerAlreadyConnectedException; +import org.apache.qpid.management.configuration.BrokerConnectionData; +import org.apache.qpid.management.configuration.BrokerConnectionException; +import org.apache.qpid.management.domain.services.ManagementClient; +import org.apache.qpid.management.domain.services.QMan; + +/** + * This controller is responsible to : + * + *
    + *
  • prepare data for the page that is showing all connected brokers.
  • . + * connect QMan with a broker on demand. + *
+ * + * @author Andrea Gazzarini + */ +public class BrokersManagementAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + + /** + * Retrieves all connected brokers (their connection data) and prepare the model that + * is then forwarded to the appropriate view page. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException in case of failure while forwarding to the view component. + * @throws IOException in case of failure while forwarding to the view component. + */ + @SuppressWarnings("unchecked") + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME); + List managementClients = qman.getManagementClients(); + + List brokers = new ArrayList(managementClients.size()); + + if (!managementClients.isEmpty()) + { + for (ManagementClient managementClient : managementClients) + { + brokers.add(managementClient.getBrokerConnectionData()); + } + request.setAttribute("model", brokers); + } + + RequestDispatcher dispatcher = request.getRequestDispatcher("/brokers_management.jsp"); + dispatcher.forward(request,response); + } catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } + + /** + * Connects QMan with a new broker and forwards to + * the brokers list view page. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException in case of failure while forwarding to the view component. + * @throws IOException in case of failure while forwarding to the view component. + */ + @SuppressWarnings("unchecked") + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME); + + String host = request.getParameter("host"); + String portString = request.getParameter("port"); + String virtualHost = request.getParameter("virtualHost"); + String username = request.getParameter("username"); + String password = request.getParameter("password"); + + String initialCapacityString = request.getParameter("initialCapacity"); + String maxCapacityString = request.getParameter("maxCapacity"); + String maxWaitTimeoutString = request.getParameter("maxWaitTimeout"); + + List errors = new LinkedList(); + int port = 0; + int initialPoolCapacity = 0; + int maxPoolCapacity = 0; + long maxWaitTimeout = 0; + + if(host== null || host.trim().length()==0) + { + errors.add("Invalid value for \"host\" attribute. Must be not null."); + } + + if(virtualHost == null || virtualHost.trim().length()==0) + { + errors.add("Invalid value for \"virtualHost\" attribute. Must be not null."); + } + + try + { + port = Integer.parseInt(portString); + } catch(Exception exception) + { + errors.add("Invalid value for \"port\" attribute. Must be not null and must be a number."); + } + + try + { + initialPoolCapacity = Integer.parseInt(initialCapacityString); + } catch(Exception exception) + { + errors.add("Invalid value for \"Initial Pool Capacity\" attribute. Must be not null and must be a number."); + } + + try + { + maxPoolCapacity = Integer.parseInt(maxCapacityString); + } catch(Exception exception) + { + errors.add("Invalid value for \"Max Pool Capacity\" attribute. Must be not null and must be a number."); + } + + try + { + maxWaitTimeout = Long.parseLong(maxWaitTimeoutString); + } catch(Exception exception) + { + errors.add("Invalid value for \"Max Wait Timeout\" attribute. Must be not null and must be a number."); + } + + request.setAttribute("errors", errors); + + if (errors.isEmpty()) + { + qman.addBroker( + host, + port, + username, + password, + virtualHost, + initialPoolCapacity, + maxPoolCapacity, + maxWaitTimeout); + } + doGet(request, response); + }catch(BrokerAlreadyConnectedException exception) + { + request.setAttribute("errorMessage","Supplied data refers to an already connected broker..."); + RequestDispatcher dispatcher = request.getRequestDispatcher("/brokers_management.jsp"); + dispatcher.forward(request,response); + } + catch(BrokerConnectionException exception) + { + request.setAttribute("errorMessage","Unable to connect with the requested broker..."); + RequestDispatcher dispatcher = request.getRequestDispatcher("/brokers_management.jsp"); + dispatcher.forward(request,response); + } catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java new file mode 100644 index 0000000000..ee098882f1 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleAction.java @@ -0,0 +1,117 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.RuntimeMXBean; +import java.util.Date; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.transport.util.Logger; + +/** + * This action is the controller responsible to prepare data for the home + * page (System Overview) of QMan admin console. + * + * @author Andrea Gazzarini + */ +public class ConsoleAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + + private static final Logger LOGGER = Logger.get(ConsoleAction.class); + + private Date _startDate; + + /** + * Initializes this controller. + * Simply it computes the start date of the application. + */ + @Override + public void init() + { + _startDate = new Date(); + } + + /** + * Prepares data for System Overview admin console page and forward that data to that page. + * + * @throws ServletException when this controller is not able to forward to the appropriate view page. + * @throws IOException when this controller is not able to forward to the appropriate view page. + */ + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + ConsoleModel model = new ConsoleModel(); + model.setVersion("1.0"); + model.setVersionName("Sofia"); + model.setStartDate(_startDate); + model.setHost(System.getProperty(Names.ADAPTER_HOST_PROPERTY_NAME, "localhost")); + model.setPort(Integer.parseInt(System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME, "8080"))); + + try + { + OperatingSystemMXBean operatingSystem = ManagementFactory.getOperatingSystemMXBean(); + model.setOsName(operatingSystem.getName()); + model.setProcessors(operatingSystem.getAvailableProcessors()); + model.setOsVersion(operatingSystem.getVersion()); + model.setArchName(operatingSystem.getArch()); + } catch(Exception exception) + { + LOGGER.warn(exception,Messages.QMAN_300006_OS_MBEAN_FAILURE); + model.setOsName("N.A."); + model.setProcessors(null); + model.setOsVersion("N.A."); + model.setArchName("N.A."); + } + + try + { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + + String bootClasspath = runtime.getBootClassPath(); + model.setBootClasspath(bootClasspath.split(File.pathSeparator)); + + String classpath = runtime.getClassPath(); + model.setClasspath(classpath.split(File.pathSeparator)); + + model.setInputArguments(runtime.getInputArguments().toArray(new String[]{})); + } catch(Exception exception) + { + LOGGER.warn(exception,Messages.QMAN_300007_RUNTIME_MBEAN_FAILURE); + } + + request.setAttribute("model", model); + + RequestDispatcher dispatcher = request.getRequestDispatcher("/console.jsp"); + dispatcher.forward(request,response); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java new file mode 100644 index 0000000000..ac0e1d2bbd --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ConsoleModel.java @@ -0,0 +1,158 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +/** + * Console Model. + * It is a simple Data Transfer Object encapsulating all information about QMan + * console (System Overview) + * + * @author Andrea Gazzarini + */ +public class ConsoleModel implements Serializable +{ + private static final long serialVersionUID = -7676132151242738376L; + private String _version; + private String _versionName; + private Date _startDate; + private String _host; + private int _port; + + private String _osName; + private String _osVersion; + private String _archName; + private Integer _processors; + + private String [] _bootClasspath; + private String [] _classpath; + private String [] _inputArguments; + private String [] _systemProperties; + + public String getVersion() + { + return _version; + } + public void setVersion(String version) + { + this._version = version; + } + public String getVersionName() + { + return _versionName; + } + public void setVersionName(String versionName) + { + this._versionName = versionName; + } + public Date getStartDate() + { + return _startDate; + } + public void setStartDate(Date startDate) + { + this._startDate = startDate; + } + public String getHost() + { + return _host; + } + public void setHost(String host) + { + this._host = host; + } + public int getPort() + { + return _port; + } + public void setPort(int port) + { + this._port = port; + } + public String getOsName() + { + return _osName; + } + public void setOsName(String osName) + { + this._osName = osName; + } + public String getOsVersion() + { + return _osVersion; + } + public void setOsVersion(String osVersion) + { + this._osVersion = osVersion; + } + public String getArchName() + { + return _archName; + } + public void setArchName(String archName) + { + this._archName = archName; + } + public Integer getProcessors() + { + return _processors; + } + public void setProcessors(Integer processors) + { + this._processors = processors; + } + public List getBootClasspath() + { + return Arrays.asList(_bootClasspath); + } + public void setBootClasspath(String [] bootClasspath) + { + this._bootClasspath = bootClasspath; + } + public String [] getClasspath() + { + return _classpath; + } + public void setClasspath(String [] classpath) + { + this._classpath = classpath; + } + public String [] getInputArguments() + { + return _inputArguments; + } + public void setInputArguments(String [] inputArguments) + { + this._inputArguments = inputArguments; + } + public String [] getSystemProperties() + { + return _systemProperties; + } + public void setSystemProperties(String [] systemProperties) + { + this._systemProperties = systemProperties; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java new file mode 100644 index 0000000000..59777cc9c8 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/JmxPerspectiveAction.java @@ -0,0 +1,189 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; +import java.util.Map.Entry; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * This controller is responsible to provide a jmx perspective of a specific resource. + * That means that this controller is querying the Platform MBean server in order to + * get metadata for the requested mbean. + * + * After that metadata will be forwarded to the appropriate view page and therefore + * will be shown on the Admin console. + * + * @author Andrea Gazzarini + */ +public class JmxPerspectiveAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + + /** + * Adapter interface for converting objects on html strings. + * + * @author Andrea Gazzarini. + */ + interface JavaToHtmlAdapter + { + /** + * Returns an HTML string representation of the given object. + * + * @param javaObject the object that needs to be converted. + * @return an html string containing value of the given object. + */ + String toHtml(Object javaObject); + } + + /** + * Adapter implementation for Map (and subclasses). + */ + private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter() + { + @SuppressWarnings("unchecked") + public String toHtml(Object javaObject) + { + Map value = (Map) javaObject; + + // Sanity check : if the map is empty or null there's no need to + // do any convertion + if (value == null || value.isEmpty()) + { + return "(empty)"; + } + + StringBuilder builder = new StringBuilder("
    "); + for (Entry entry : value.entrySet()) + { + builder + .append("
  • ") + .append(entry.getKey()) + .append(" = ") + .append(entry.getValue()); + } + builder.append("
"); + return builder.toString(); + } + }; + + private Map _adapters = new HashMap(); + + @Override + public void init() throws ServletException + { + _adapters.put(Map.class.getName(), mapAdapter); + _adapters.put(HashMap.class.getName(),mapAdapter); + _adapters.put(Properties.class.getName(),mapAdapter); + _adapters.put(Hashtable.class.getName(),mapAdapter); + } + + @SuppressWarnings("unchecked") + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + String resourceId = null; + try + { + resourceId = request.getParameter("resourceId"); + + ObjectName objectName = new ObjectName(resourceId); + String [] keyProperties = objectName.getKeyPropertyListString().split(","); + + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + MBeanInfo metadata = server.getMBeanInfo(objectName); + + Map attributes = getAttributes(server, objectName,metadata.getAttributes()); + + request.setAttribute("resourceId", objectName); + request.setAttribute("metadata",metadata); + request.setAttribute("nameAttributes",keyProperties); + request.setAttribute("attributes",attributes); + + RequestDispatcher dispatcher = request.getRequestDispatcher("/jmx_perspective.jsp"); + dispatcher.forward(request,response); + } catch(MalformedObjectNameException exception) + { + request.setAttribute("errorMessage","Malformed Resource ID : supplied value is "+resourceId); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + + } + catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } + + /** + * Starting from an mbean metadata, this method retrieves all the attributes + * from the corresponding MBean Server. + * + * @param server the mbean server where the target mbean is registered. + * @param name the name of the target mbean. + * @param metadata the metadata of mbean. + * @return a map containing all attributes of the given mbean. + * @throws Exception when it's not possible to retrieve attributes. + */ + private Map getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadata) throws Exception + { + Map result = new HashMap(metadata.length); + for (MBeanAttributeInfo attribute : metadata) + { + Object value = server.getAttribute(name, attribute.getName()); + result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value)); + } + return result; + } + + /** + * Converts the given attribute value in a html string format. + * + * @param type the java type of the given attribute value. + * @param value the attribute value. + * @return a html string format of the given value. + */ + private String getAdaptedValue(String type, Object value) + { + JavaToHtmlAdapter adapter = _adapters.get(type); + return (adapter != null) ? adapter.toHtml(value) : String.valueOf(value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java new file mode 100644 index 0000000000..aefd4ca8dd --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/LoggingConfigurationAction.java @@ -0,0 +1,114 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.qpid.qman.debug.WsdlDebugger; +import org.apache.qpid.qman.debug.XmlDebugger; + +/** + * Logging configuration controller. + * Accepts input parameters from admin console and configure the underlying + * logging subsystem at runtime. + * + * @author Andrea Gazzarini + */ +public class LoggingConfigurationAction extends HttpServlet +{ + private static final long serialVersionUID = 633352305870632824L; + + private final static String WSDL_DEBUG_ENABLED_PARAM = "wsdlDebugEnabled"; + private final static String SOAP_DEBUG_ENABLED_PARAM = "soapDebugEnabled"; + private final static String WEB_SERVER_LOG_LEVEL_PARAM = "webServerLogLevel"; + private final static String QMAN_LOG_LEVEL_PARAM = "qmanLogLevel"; + + private final static String WEB_SERVER_PACKAGE = "org.mortbay"; + private final static String QMAN_PACKAGE = "org.qpid.apache.management"; + + /** + * Retrieves current logging configuration and forward those data to the logging configuration view page. + * In this way that page will be able to display the current logging settings. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException when this controller is not able to forward to the appropriate view page. + * @throws IOException when this controller is not able to forward to the appropriate view page. + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + Level messageDebuggerLogLevel = Logger.getLogger(XmlDebugger.class).getEffectiveLevel(); + Level wsdlDebuggerLogLevel = Logger.getLogger(WsdlDebugger.class).getEffectiveLevel(); + Level webServerLogLevel = Logger.getLogger(WEB_SERVER_PACKAGE).getEffectiveLevel(); + Level qmanLogLevel = Logger.getLogger(QMAN_PACKAGE).getEffectiveLevel(); + + request.setAttribute(WSDL_DEBUG_ENABLED_PARAM,wsdlDebuggerLogLevel.equals(Level.DEBUG)); + request.setAttribute(SOAP_DEBUG_ENABLED_PARAM,messageDebuggerLogLevel.equals(Level.DEBUG)); + request.setAttribute(WEB_SERVER_LOG_LEVEL_PARAM,webServerLogLevel); + request.setAttribute(QMAN_LOG_LEVEL_PARAM,qmanLogLevel); + + RequestDispatcher dispatcher = request.getRequestDispatcher("/logging_configuration.jsp"); + dispatcher.forward(request, response); + } + + /** + * Accepts user data coming from admin console and use it for configure the underlying logging + * subsystem. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException when this controller is not able to forward to the appropriate view page. + * @throws IOException when this controller is not able to forward to the appropriate view page. + */ + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + String wsdlDebugEnabled = request.getParameter(WSDL_DEBUG_ENABLED_PARAM); + String soapDebugEnabled = request.getParameter(SOAP_DEBUG_ENABLED_PARAM); + + String qmanLevel = request.getParameter(QMAN_LOG_LEVEL_PARAM); + String serverLevel = request.getParameter(WEB_SERVER_LOG_LEVEL_PARAM); + + Logger.getLogger(WEB_SERVER_PACKAGE).setLevel(Level.toLevel(serverLevel)); + Logger.getLogger(QMAN_PACKAGE).setLevel(Level.toLevel(qmanLevel)); + + Logger.getLogger(WsdlDebugger.class).setLevel( + "on".equals(wsdlDebugEnabled) + ? Level.DEBUG + : Level.INFO); + + Logger.getLogger(XmlDebugger.class).setLevel( + "on".equals(soapDebugEnabled) + ? Level.DEBUG + : Level.INFO); + + doGet(request, response); + } +} + \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java new file mode 100644 index 0000000000..f1a55be6bf --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/ResourcesManagementAction.java @@ -0,0 +1,91 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Set; + +import javax.management.MBeanServer; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.services.ManagementClient; +import org.apache.qpid.management.domain.services.QMan; + +/** + * This controller retrieves from QMan all the registered resources and organize + * that data in a model that is then forwarded to the appropriate view page. + * + * TODO : In the corresponding view page only one broker is displayed. + * A query should be made on QMan mbean in order to retrieve all connected broker and therefore + * a model for each of them should be created. + * In the corresponding weg page there should be a "tab" for each broker. Each tab should show only + * the objects belonging to that broker. + * + * @author Andrea Gazzarini + */ +public class ResourcesManagementAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + + @SuppressWarnings("unchecked") + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + QMan qman = (QMan)getServletContext().getAttribute(Names.APPLICATION_NAME); + List managementClient = qman.getManagementClients(); + + if (!managementClient.isEmpty()) + { + BrokerModel model = new BrokerModel(); + model.setId(managementClient.toString()); + + MBeanServer mxServer = ManagementFactory.getPlatformMBeanServer(); + Set objectNames = mxServer.queryNames(new ObjectName("Q-MAN:*"), null); + for (ObjectName objectName : objectNames) + { + model.addObject(objectName); + } + + request.setAttribute("model", model); + } + + RequestDispatcher dispatcher = request.getRequestDispatcher("/resources_management.jsp"); + dispatcher.forward(request,response); + } catch(MalformedObjectNameException exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java new file mode 100644 index 0000000000..ca5b3285b0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmOperationsPerspectiveAction.java @@ -0,0 +1,191 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.URI; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; +import java.util.Map.Entry; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +/** + * This controller is responsible to retirve operations metadata from a WS-Resource. + * That metadat will be forwarded and used by the corresponding view page. + * + * TODO : This is not really showing WS metadata. Insted JMX metadata is used here. + * + * @author Andrea Gazzarini + * + */ +public class WsdmOperationsPerspectiveAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + + private ProxyHandler proxyHandler; + + interface JavaToHtmlAdapter + { + String toHtml(Object javaObject); + } + + private URI resourceUri; + + private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter() + { + @SuppressWarnings("unchecked") + public String toHtml(Object javaObject) + { + Map value = (Map) javaObject; + + if (value == null || value.isEmpty()) + { + return "(empty)"; + } + + StringBuilder builder = new StringBuilder(); + builder.append("
    "); + for (Entry entry : value.entrySet()) + { + builder + .append("
  • ") + .append(entry.getKey()) + .append(" = ") + .append(entry.getValue()); + } + builder.append("
"); + return builder.toString(); + } + }; + + private Map adapters = new HashMap(); + + @Override + public void init() throws ServletException + { + adapters.put(Map.class.getName(), mapAdapter); + adapters.put(HashMap.class.getName(),mapAdapter); + adapters.put(Properties.class.getName(),mapAdapter); + adapters.put(Hashtable.class.getName(),mapAdapter); + + proxyHandler = new ReflectionProxyHandler(); + proxyHandler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + proxyHandler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", Names.PREFIX)); + proxyHandler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", Names.PREFIX)}); + proxyHandler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", Names.PREFIX)); + proxyHandler.setReturnType(Element[].class); + } + + @SuppressWarnings("unchecked") + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + String resourceId = request.getParameter("resourceId"); + ObjectName objectName = new ObjectName(resourceId); + String wsdmResourceId = objectName.getKeyProperty(Names.OBJECT_ID); + + EndpointReference resourceEndpointReference = new EndpointReference(getURI(request)); + resourceEndpointReference.addParameter( + Names.RESOURCE_ID_QNAME, + wsdmResourceId); + +// WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference); +// Element wsdl = ((Element[])resourceClient.invoke(proxyHandler,WSDL_DIALECT))[0]; +// Element rmd = ((Element[])resourceClient.invoke(proxyHandler,RMD_DIALECT))[0]; + + String [] keyProperties = objectName.getKeyPropertyListString().split(","); + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + MBeanInfo metadata = server.getMBeanInfo(objectName); + + Map attributes = getAttributes(server, objectName,metadata.getAttributes()); + + request.setAttribute("resourceId", resourceId); + request.setAttribute("metadata",metadata); + request.setAttribute("nameAttributes",keyProperties); + request.setAttribute("attributes",attributes); + + RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_operations_perspective.jsp"); + dispatcher.forward(request,response); + } catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } + + private URI getURI(HttpServletRequest request) + { + if (resourceUri == null) + { + StringBuilder builder = new StringBuilder(); + builder + .append(request.getProtocol()) + .append("//") + .append(request.getServerName()) + .append(":") + .append(request.getServerPort()) + .append("/qman/services/QManWsResource"); + resourceUri = URI.create(builder.toString()); + } + return resourceUri; + } + + private Map getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadata) throws Exception + { + Map result = new HashMap(metadata.length); + for (MBeanAttributeInfo attribute : metadata) + { + Object value = server.getAttribute(name, attribute.getName()); + result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value)); + } + return result; + } + + private String getAdaptedValue(String type, Object value) + { + JavaToHtmlAdapter adapter = adapters.get(type); + return (adapter != null) ? adapter.toHtml(value) : String.valueOf(value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java new file mode 100644 index 0000000000..e3a8eb50d7 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmPropertiesPerspectiveAction.java @@ -0,0 +1,185 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.net.URI; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; +import java.util.Map.Entry; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +public class WsdmPropertiesPerspectiveAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + + private ProxyHandler proxyHandler; + + interface JavaToHtmlAdapter + { + String toHtml(Object javaObject); + } + + private URI resourceUri; + + private JavaToHtmlAdapter mapAdapter = new JavaToHtmlAdapter() + { + @SuppressWarnings("unchecked") + public String toHtml(Object javaObject) + { + Map value = (Map) javaObject; + + if (value == null || value.isEmpty()) + { + return "(empty)"; + } + + StringBuilder builder = new StringBuilder(); + builder.append("
    "); + for (Entry entry : value.entrySet()) + { + builder + .append("
  • ") + .append(entry.getKey()) + .append(" = ") + .append(entry.getValue()); + } + builder.append("
"); + return builder.toString(); + } + }; + + private Map adapters = new HashMap(); + + @Override + public void init() throws ServletException + { + adapters.put(Map.class.getName(), mapAdapter); + adapters.put(HashMap.class.getName(),mapAdapter); + adapters.put(Properties.class.getName(),mapAdapter); + adapters.put(Hashtable.class.getName(),mapAdapter); + + proxyHandler = new ReflectionProxyHandler(); + proxyHandler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + proxyHandler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", Names.PREFIX)); + proxyHandler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", Names.PREFIX)}); + proxyHandler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", Names.PREFIX)); + proxyHandler.setReturnType(Element[].class); + } + + @SuppressWarnings("unchecked") + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + String resourceId = request.getParameter("resourceId"); + ObjectName objectName = new ObjectName(resourceId); + + String wsresourceid = objectName.getKeyProperty(Names.OBJECT_ID); + + EndpointReference resourceEndpointReference = new EndpointReference(getURI(request)); + resourceEndpointReference.addParameter( + Names.RESOURCE_ID_QNAME, + wsresourceid); + +// WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference); +// Element wsdl = ((Element[])resourceClient.invoke(proxyHandler,WSDL_DIALECT))[0]; +// Element rmd = ((Element[])resourceClient.invoke(proxyHandler,RMD_DIALECT))[0]; + + String [] keyProperties = objectName.getKeyPropertyListString().split(","); + + + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + MBeanInfo metadata = server.getMBeanInfo(objectName); + + Map attributes = getAttributes(server, objectName,metadata.getAttributes()); + + request.setAttribute("resourceId", resourceId); + request.setAttribute("metadata",metadata); + request.setAttribute("nameAttributes",keyProperties); + request.setAttribute("attributes",attributes); + + RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_properties_perspective.jsp"); + dispatcher.forward(request,response); + } catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } + + private URI getURI(HttpServletRequest request) + { + if (resourceUri == null) + { + StringBuilder builder = new StringBuilder(); + builder + .append(request.getProtocol()) + .append("//") + .append(request.getServerName()) + .append(":") + .append(request.getServerPort()) + .append("/qman/services/QManWsResource"); + resourceUri = URI.create(builder.toString()); + } + return resourceUri; + } + + private Map getAttributes(MBeanServer server, ObjectName name, MBeanAttributeInfo [] metadata) throws Exception + { + Map result = new HashMap(metadata.length); + for (MBeanAttributeInfo attribute : metadata) + { + Object value = server.getAttribute(name, attribute.getName()); + result.put(attribute.getName(),getAdaptedValue(attribute.getType(), value)); + } + return result; + } + + private String getAdaptedValue(String type, Object value) + { + JavaToHtmlAdapter adapter = adapters.get(type); + return (adapter != null) ? adapter.toHtml(value) : String.valueOf(value); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java new file mode 100644 index 0000000000..b4c488e97c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmRmdPerspectiveAction.java @@ -0,0 +1,139 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.net.URI; + +import javax.management.ObjectName; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.metadata.WsxConstants; +import org.apache.muse.ws.resource.metadata.WsrmdConstants; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +public class WsdmRmdPerspectiveAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + private static final Object [] RMD_DIALECT = new Object[]{WsrmdConstants.NAMESPACE_URI}; + + private ProxyHandler proxyHandler; + + private URI resourceUri; + + @Override + public void init() throws ServletException + { + proxyHandler = new ReflectionProxyHandler(); + proxyHandler.setAction(WsxConstants.GET_METADATA_URI); + proxyHandler.setRequestName(WsxConstants.GET_METADATA_QNAME); + proxyHandler.setRequestParameterNames(new QName[]{ + new QName( + WsxConstants.NAMESPACE_URI, + WsxConstants.DIALECT, + WsxConstants.PREFIX)}); + proxyHandler.setResponseName(WsxConstants.METADATA_QNAME); + proxyHandler.setReturnType(Element[].class); + } + + @SuppressWarnings("unchecked") + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + String resourceId = request.getParameter("resourceId"); + ObjectName objectName = new ObjectName(resourceId); + + String wsresourceid = objectName.getKeyProperty(Names.OBJECT_ID); + EndpointReference resourceEndpointReference = new EndpointReference(getURI(request)); + + resourceEndpointReference.addParameter( + Names.RESOURCE_ID_QNAME, + wsresourceid); + + WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference); + Element rmd = ((Element[])resourceClient.invoke(proxyHandler,RMD_DIALECT))[0]; + +// NodeList nodelist = wsdl.getChildNodes(); +// Element definitions = null; +// for (int i = 0; i < nodelist.getLength(); i++) +// { +// Node node = nodelist.item(i); +// switch (node.getNodeType()) +// { +// case Node.ELEMENT_NODE: +// { +// Element element = (Element) node; +// if (element.getNodeName().indexOf("definitions") != -1) +// { +// definitions = element; +// break; +// } +// } +// } +// } + + String output = XmlUtils.toString(rmd); + + String [] keyProperties = objectName.getKeyPropertyListString().split(","); + + request.setAttribute("resourceId", resourceId); + request.setAttribute("nameAttributes",keyProperties); + request.setAttribute("rmd",output); + RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_rmd_perspective.jsp"); + dispatcher.forward(request,response); + } catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } + + private URI getURI(HttpServletRequest request) + { + if (resourceUri == null) + { + StringBuilder builder = new StringBuilder(); + builder + .append("http://") + .append(request.getServerName()) + .append(":") + .append(request.getServerPort()) + .append("/qman/services/QManWsResource"); + resourceUri = URI.create(builder.toString()); + } + return resourceUri; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java new file mode 100644 index 0000000000..77a5237037 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/web/action/WsdmWsdlPerspectiveAction.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.web.action; + +import java.io.IOException; +import java.net.URI; + +import javax.management.ObjectName; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.metadata.WsxConstants; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class WsdmWsdlPerspectiveAction extends HttpServlet +{ + private static final long serialVersionUID = -2411413147821629363L; + private static final Object [] WSDL_DIALECT = new Object[]{WsxConstants.WSDL_DIALECT}; + + private ProxyHandler proxyHandler; + + private URI resourceUri; + + @Override + public void init() throws ServletException + { + proxyHandler = new ReflectionProxyHandler(); + proxyHandler.setAction(WsxConstants.GET_METADATA_URI); + proxyHandler.setRequestName(WsxConstants.GET_METADATA_QNAME); + proxyHandler.setRequestParameterNames(new QName[]{ + new QName( + WsxConstants.NAMESPACE_URI, + WsxConstants.DIALECT, + WsxConstants.PREFIX)}); + proxyHandler.setResponseName(WsxConstants.METADATA_QNAME); + proxyHandler.setReturnType(Element[].class); + } + + @SuppressWarnings("unchecked") + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + try + { + String resourceId = request.getParameter("resourceId"); + ObjectName objectName = new ObjectName(resourceId); + + String wsresourceid = objectName.getKeyProperty(Names.OBJECT_ID); + EndpointReference resourceEndpointReference = new EndpointReference(getURI(request)); + + resourceEndpointReference.addParameter( + Names.RESOURCE_ID_QNAME, + wsresourceid); + + WsResourceClient resourceClient = new WsResourceClient(resourceEndpointReference); + Element wsdl = ((Element[])resourceClient.invoke(proxyHandler,WSDL_DIALECT))[0]; + + NodeList nodelist = wsdl.getChildNodes(); + Element definitions = null; + for (int i = 0; i < nodelist.getLength(); i++) + { + Node node = nodelist.item(i); + switch (node.getNodeType()) + { + case Node.ELEMENT_NODE: + { + Element element = (Element) node; + if (element.getNodeName().indexOf("definitions") != -1) + { + definitions = element; + break; + } + } + } + } + + String output = XmlUtils.toString(definitions); + + String [] keyProperties = objectName.getKeyPropertyListString().split(","); + + request.setAttribute("resourceId", resourceId); + request.setAttribute("nameAttributes",keyProperties); + request.setAttribute("wsdl",output); + RequestDispatcher dispatcher = request.getRequestDispatcher("/wsdm_wsdl_perspective.jsp"); + dispatcher.forward(request,response); + } catch(Exception exception) + { + request.setAttribute("errorMessage","Unable to detect the exact cause Please look at the reported stack trace below."); + request.setAttribute("exception",exception); + RequestDispatcher dispatcher = request.getRequestDispatcher("/error_page.jsp"); + dispatcher.forward(request,response); + } + } + + private URI getURI(HttpServletRequest request) + { + if (resourceUri == null) + { + StringBuilder builder = new StringBuilder(); + builder + .append("http://") + .append(request.getServerName()) + .append(":") + .append(request.getServerPort()) + .append("/qman/services/QManWsResource"); + resourceUri = URI.create(builder.toString()); + } + return resourceUri; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java new file mode 100644 index 0000000000..79a387e80c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmu.java @@ -0,0 +1,130 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import javax.management.MBeanRegistration; +import javax.management.MBeanServer; +import javax.management.NotificationBroadcasterSupport; +import javax.management.ObjectName; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.handler.impl.QpidDomainObject; +import org.apache.qpid.management.domain.handler.impl.QpidDomainObjectMBean; +import org.apache.qpid.management.jmx.EntityLifecycleNotification; + +/** + * QEmu is basically an instance creator that is installed separately + * as part of QMan test cases & examples. + * Reason for that is to emulate object creation (queues, exchanges, etc...) + * without having Qpid broker connected and therefore controlling the + * total number of the instances that are created. + * + * @author Andrea Gazzarini + */ +public class QEmu extends NotificationBroadcasterSupport implements QEmuMBean, MBeanRegistration{ + + private MBeanServer _mxServer; + private final static String PACKAGE_NAME= "org.apache.qpid"; + private final static String QUEUE = "queue"; + + /** + * Unregisters a Queue MBean with MBeanServer. + * + * @param objectName the name of the MBean that must unregistered. + * @throws Exception when the creation or the registration fails. + */ + public void unregister(ObjectName objectName) throws Exception + { + _mxServer.unregisterMBean(objectName); + + sendNotification( + EntityLifecycleNotification.INSTANCE_REMOVED_NOTIFICATION_TYPE, + objectName); + } + + /** + * Creates and registers a Queue MBean with MBeanServer. + * + * @param objectName the name of the queue MBean. + * @throws Exception when the creation or the registration fails. + */ + public void createQueue(ObjectName objectName) throws Exception + { + QpidDomainObjectMBean queue = new QpidDomainObject(); + _mxServer.registerMBean(queue, objectName); + + sendNotification( + EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE, + objectName); + } + + /** + * Sends a notification about a lifecycle event of the mbean associated + * with the given object. + * + * @param type the event (notification) type. + * @param name the name of the event source. + */ + private void sendNotification(String type,ObjectName name) + { + sendNotification( + new EntityLifecycleNotification( + type, + PACKAGE_NAME, + QUEUE, + Names.CLASS, + name)); + } + + /** + * Not implemented for this class. + */ + public void postDeregister() + { + // N.A. + } + + /** + * Not implemented for this class. + */ + public void postRegister(Boolean registrationDone) + { + // N.A. + } + + /** + * Not implemented for this class. + */ + public void preDeregister() + { + // N.A. + } + + /** + * MBean server callback. + * Stores the value of the owner MBeanServer. + */ + public ObjectName preRegister(MBeanServer server, ObjectName name) + { + this._mxServer = server; + return name; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java new file mode 100644 index 0000000000..47aa4ea681 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuInitializer.java @@ -0,0 +1,95 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.lang.management.ManagementFactory; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.transport.util.Logger; + +/** + * QPid Emulator Initializer. + * This component is basically responsible to create and initialize + * an emulator module used for simulate object instances creation. + * + * @author Andrea Gazzarini + */ +public class QEmuInitializer extends HttpServlet +{ + private static final long serialVersionUID = 6149614872902682208L; + private final static Logger LOGGER = Logger.get(QEmuInitializer.class); + + /** + * QEmu initialization method. + * + * @throws ServletException when the module cannot be initialized. + */ + public void init() throws ServletException + { + try + { + ManagementFactory.getPlatformMBeanServer().registerMBean( + new QEmu(), + Names.QPID_EMULATOR_OBJECT_NAME); + } catch(Exception exception) + { + LOGGER.warn( + exception, + Messages.QMAN_300005_QEMU_INITIALIZATION_FAILURE); + throw new ServletException(exception); + } + } + + /** + * This is a startup module only so an override of the + * default servlet behaviour must be done in order to + * prevent incoming http requests processing. + * + * @param request the http request. + * @param response the http response. + * @throws ServletException each time this method is called. + */ + @Override + public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException + { + throw new ServletException(); + } + + /** + * Unregister QPid emulator. + */ + public void destroy() + { + try + { + ManagementFactory.getPlatformMBeanServer().unregisterMBean( + Names.QPID_EMULATOR_OBJECT_NAME); + } catch (Exception exception) + { + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java new file mode 100644 index 0000000000..f22e7ff12d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/QEmuMBean.java @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import javax.management.ObjectName; + +/** + * Management interface for QEmu. + * + * @author Andrea Gazzarini + * @see QEmu + */ +public interface QEmuMBean +{ + /** + * Creates and registers a Queue MBean with MBeanServer. + * + * @param objectName the name of the queue MBean. + * @throws Exception when the creation or the registration fails. + */ + void createQueue(ObjectName name) throws Exception; + + /** + * Unregisters a Queue MBean with MBeanServer. + * + * @param objectName the name of the MBean that must unregistered. + * @throws Exception when the creation or the registration fails. + */ + void unregister(ObjectName name) throws Exception; +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java new file mode 100644 index 0000000000..eef70b5544 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java @@ -0,0 +1,76 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import javax.management.ObjectName; + +/** + * Thrown when the artifacts related to a specific resource cannot be built. + * + * @author Andrea Gazzarini + */ +public class ArtifactsNotAvailableException extends Exception +{ + private static final long serialVersionUID = -9010460152421791926L; + + private final WsArtifacts _artifacts; + private final ObjectName _objectName; + + /** + * Builds a new exception with the given arguments. + * + * @param artifacts the artifacts built. + * @param cause the exception cause. + * @param objectName the object name of the corresponding JMX entity. + */ + public ArtifactsNotAvailableException( + WsArtifacts artifacts, + Throwable cause, + ObjectName objectName) + { + super(cause); + this._artifacts = artifacts; + this._objectName = objectName; + } + + /** + * Returns a message that indicates which artifacts were built. + * + * @return a message that indicates which artifacts were built. + */ + @Override + public String getMessage() + { + StringBuilder builder = new StringBuilder(); + if (_artifacts == null) + { + return super.getMessage(); + } + + builder.append("Built artifacts for ") + .append(_objectName) + .append(" : ") + .append( (_artifacts.getWsdl() != null) ? "WSDL," : "") + .append( (_artifacts.getCapabilityClass() != null) ? "Capability Class," : "") + .append( (_artifacts.getResourceMetadataDescriptor() != null) ? "Resource Metadata Descriptor," : ""); + return builder.toString(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java new file mode 100644 index 0000000000..f3c8077d46 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/BuilderException.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +/** + * Thrown when a WSRF artifact (either WSDL or capability) cannot be built. + * + * @author Andrea Gazzarini + */ +public class BuilderException extends Exception +{ + private static final long serialVersionUID = -8267818907567906262L; + + /** + * Builds a new exception with the given cause. + * + * @param cause the exception cause. + */ + public BuilderException(Exception cause) + { + super(cause); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java new file mode 100644 index 0000000000..59a5801505 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Constants.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +public interface Constants +{ + String WSRP_PROPERTIES_XPATH = "/wsdl:definitions/wsdl:types/xsd:schema[" + + "@targetNamespace='http://amqp.apache.org/qpid/management/qman']" + + "/xsd:element[@name='QManWsResourceProperties']/xsd:complexType/xsd:sequence"; + + String SERVICE_LOCATION_XPATH = "/wsdl:definitions/wsdl:service/wsdl:port/wsdl-soap:address/@location"; + String QMAN_SCHEMA_XPATH = "/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://amqp.apache.org/qpid/management/qman']"; + + String MIN_OCCURS = "minOccurs"; + String REF_ATTRIBUTE = "ref"; + String NAME_ATTRIBUTE = "name"; + String TYPE_ATTRIBUTE ="type"; + + QName XSD_ELEMENT_QNAME = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI,"element","xsd"); + QName XSD_COMPLEX_TYPE_QNAME = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI,"complexType","xsd"); + QName XSD_SEQUENCE_QNAME = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI,"sequence","xsd"); + +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java new file mode 100644 index 0000000000..bde98092a0 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ConsumerCapability.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import org.apache.muse.core.AbstractCapability; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.notification.NotificationConsumer; +import org.apache.muse.ws.notification.NotificationMessage; +import org.apache.muse.ws.notification.NotificationMessageListener; +import org.apache.muse.ws.notification.WsnConstants; + +/** + * WS-Notifications consumer capability. + * At the moment QMan is not a consumer of itself so this capability is here only + * for test purposes. + * + * @author Andrea Gazzarini + */ +public class ConsumerCapability extends AbstractCapability implements NotificationMessageListener +{ + /** + * Initializes this capability and register itself as message listener. + * + * @throws SoapFault when the initialization fails. + */ + public void initializeCompleted() throws SoapFault + { + super.initializeCompleted(); + + NotificationConsumer wsn = (NotificationConsumer)getResource().getCapability(WsnConstants.CONSUMER_URI); + wsn.addMessageListener(this); + } + + /** + * Returns true if this consumer can accepts the message. + * + * @return true; + */ + public boolean accepts(NotificationMessage message) + { + return true; + } + + /** + * On Message callback. + */ + public void process(NotificationMessage message) + { + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java new file mode 100644 index 0000000000..370cf3086d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/DummyCapabilityBuilder.java @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanOperationInfo; +import javax.management.ObjectName; + +import org.apache.muse.core.Environment; + +/** + * Dummy capability builder used for avoid duplicated builds for the + * same class. + * Basically it acts likes a Null Object when the target capability class has been + * already built. + * + * @author Andrea Gazzarini + */ +public class DummyCapabilityBuilder implements IArtifactBuilder +{ + /** + * Director callback. + * Do nothing here (see class comments above.) + */ + public void begin(ObjectName objectName) + { + } + + /** + * Director callback. + * Do nothing here (see class comments above.) + */ + public void endAttributes() + { + } + + /** + * Director callback. + * Do nothing here (see class comments above.) + */ + public void endOperations() + { + } + + /** + * Director callback. + * Do nothing here (see class comments above.) + */ + public void onAttribute(MBeanAttributeInfo attributeMetadata) + { + } + + /** + * Director callback. + * Do nothing here (see class comments above.) + */ + public void onOperation(MBeanOperationInfo operationMetadata) + { + } + + /** + * Director callback. + * Do nothing here (see class comments above.) + */ + public void setEnvironment(Environment environment) + { + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java new file mode 100644 index 0000000000..70b9b0e009 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/IArtifactBuilder.java @@ -0,0 +1,82 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanOperationInfo; +import javax.management.ObjectName; + +import org.apache.muse.core.Environment; + +/** + * Defines behaviour needed by WS-DM artifact builders. + * Each concrete implementor must provide its own parser + * implementation of the given JMX data. + * + * @author Andrea Gazzarini + */ +public interface IArtifactBuilder +{ + /** + * The build process begin and the given parameter is the + * object name of the corresponding JMX entity. + * + * @throws BuilderException when the initialization fails. + */ + void begin(ObjectName objectName) throws BuilderException; + + /** + * Processes an attribute (its metadata) of the current MBean. + * + * @param attributeMetadata the attribute metadata. + * @throws BuilderException when the builder cannot parse the given metadata. + */ + void onAttribute(MBeanAttributeInfo attributeMetadata) throws BuilderException; + + /** + * Processes an operation (its metadata) of the current MBean. + * + * @param operationMetadata the operation metadata. + * @throws BuilderException when the builder cannot parse the given metadata. + */ + void onOperation(MBeanOperationInfo operationMetadata) throws BuilderException; + + /** + * Ends of the attributes section. + * + * @throws BuilderException when the builder encounter a problem during this phase.. + */ + void endAttributes() throws BuilderException; + + /** + * Ends of the operations section. + * + * @throws BuilderException when the builder encounter a problem during this phase.. + */ + void endOperations() throws BuilderException; + + /** + * Injects the adapter enviroment on this builder. + * + * @param environment the adapter environment. + */ + void setEnvironment(Environment environment); +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java new file mode 100644 index 0000000000..37ecc0c031 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java @@ -0,0 +1,219 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.management.ManagementFactory; + +import javax.management.Attribute; +import javax.management.AttributeNotFoundException; +import javax.management.InstanceNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.muse.ws.resource.impl.AbstractWsResourceCapability; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.domain.handler.impl.InvocationResult; +import org.apache.qpid.management.domain.services.MethodInvocationException; +import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault; +import org.apache.qpid.management.wsdm.common.MethodInvocationFault; +import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault; +import org.apache.qpid.management.wsdm.common.QManFault; +import org.apache.qpid.transport.util.Logger; + +/** + * Abstract capability used for centralize common + * behaviour of the QMan resource(s) related capabilities. + * + * @author Andrea Gazzarini + */ +public abstract class MBeanCapability extends AbstractWsResourceCapability +{ + private static final Logger LOGGER = Logger.get(MBeanCapability.class); + + protected final MBeanServer _mxServer; + protected ObjectName _objectName; + + /** + * Builds a new capability related to the given object name. + * + * @param objectName the name of the target object of this capability. + */ + public MBeanCapability() + { + _mxServer = ManagementFactory.getPlatformMBeanServer(); + } + + /** + * Injects on this capability the object name of the target mbean. + * + * @param objectName the object name of the target mbean. + */ + void setResourceObjectName(ObjectName objectName) + { + this._objectName = objectName; + } + + /** + * Returns the attribute value of a QMan managed object instance. + * + * @param attributeName the name of the attribute to be requested. + * @return the value for the requested attribute. + * @throws NoSuchAttributeFault when the requested attribute cannot be found + * on the given entity instance. + * @throws EntityInstanceNotFoundFault when the requested entity instance cannot + * be found. + * @throws QManFault in case of internal system failure. + */ + Object getAttribute(String attributeName) throws NoSuchAttributeFault, EntityInstanceNotFoundFault, QManFault + { + try + { + return _mxServer.getAttribute(_objectName, attributeName); + } catch (AttributeNotFoundException exception) + { + throw new NoSuchAttributeFault( + getWsResource().getEndpointReference(), + attributeName); + } catch (InstanceNotFoundException exception) + { + throw new EntityInstanceNotFoundFault( + getWsResource().getEndpointReference(), + _objectName); + } catch (Exception exception) + { + LOGGER.error( + Messages.QMAN_100035_GET_ATTRIBUTE_FAILURE, + attributeName, + _objectName); + throw new QManFault( + getWsResource().getEndpointReference(), + exception); + } + } + + /** + * Sets the value for the given attribute on this MBean (proxy). + * + * @param objectName + * the object name of the target instance (excluding the domain + * name). + * @param attributeName + * the name of the attribute to be requested. + * @param value + * the value for the requested attribute. + * @throws NoSuchAttributeFault + * when the requested attribute cannot be found on the given + * entity instance. + * @throws EntityInstanceNotFoundFault + * when the requested entity instance cannot be found. + * @throws QManFault + * in case of internal system failure. + */ + void setAttribute(String attributeName, Object value) throws NoSuchAttributeFault, EntityInstanceNotFoundFault, QManFault + { + try + { + _mxServer.setAttribute(_objectName, new Attribute(attributeName,value)); + } catch (AttributeNotFoundException exception) + { + throw new NoSuchAttributeFault( + getWsResource().getEndpointReference(), + attributeName); + } catch (InstanceNotFoundException exception) + { + throw new EntityInstanceNotFoundFault( + getWsResource().getEndpointReference(), + _objectName); + } catch (Exception exception) + { + LOGGER.error( + Messages.QMAN_100036_SET_ATTRIBUTE_FAILURE, + attributeName, + _objectName); + throw new QManFault( + getWsResource().getEndpointReference(), + exception); + } + } + + /** + * Invokes the requested operation on target JMX resource. + * + * @param operationName the name of the operation to be invoked. + * @param params parameters used for operation invocation. + * @param signature the operation / method signature. + * @throws EntityInstanceNotFoundFault + * when the target MBean doesn't exist on Management server. + * @throws MethodInvocationFault + * when the invocation of the requested operation raises an exception. + * @throws QManFault + * in case of not-well known failure. + */ + Result invoke(String operationName, Object [] params, String [] signature) throws EntityInstanceNotFoundFault, MethodInvocationFault,QManFault + { + try + { + InvocationResult output = (InvocationResult) _mxServer + .invoke( + _objectName, + operationName, + params, + signature); + + return new Result(output.getOutputSection()); + + } catch (InstanceNotFoundException exception) + { + throw new EntityInstanceNotFoundFault( + getWsResource().getEndpointReference(), + _objectName); + } catch (MBeanException exception) + { + if (exception.getTargetException() instanceof MethodInvocationException) + { + MethodInvocationException failure = (MethodInvocationException) exception.getTargetException(); + throw new MethodInvocationFault( + getWsResource().getEndpointReference(), + operationName, + failure.getStatusText(), + failure.getReturnCode()); + } else { + LOGGER.error( + Messages.QMAN_100037_INVOKE_OPERATION_FAILURE, + operationName, + _objectName); + throw new QManFault( + getWsResource().getEndpointReference(), + exception); + } + }catch(Exception exception) + { + LOGGER.error( + Messages.QMAN_100037_INVOKE_OPERATION_FAILURE, + operationName, + _objectName); + throw new QManFault( + getWsResource().getEndpointReference(), + exception); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java new file mode 100644 index 0000000000..ea67bdf9e1 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java @@ -0,0 +1,549 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import javassist.CannotCompileException; +import javassist.ClassClassPath; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; +import javassist.CtNewMethod; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.ObjectName; +import javax.xml.namespace.QName; + +import org.apache.muse.core.Environment; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault; +import org.apache.qpid.management.wsdm.common.MethodInvocationFault; +import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault; +import org.apache.qpid.management.wsdm.common.QManFault; +import org.apache.qpid.transport.util.Logger; + +/** + * Builder for capability class that will implements the interface + * and the behaviour of the underlying JMX Entity. + * The product of this builder (capability class) will be used for create a new instance + * of the corresponding capability. It will be the "adapter" between WS-Resource and + * JMX MBean. + * + * @author Andrea Gazzarini + */ +public class MBeanCapabilityBuilder implements IArtifactBuilder{ + + private final static String GET_PROPERTY_NAMES_METHOD_COMMON_PART = "public QName[] getPropertyNames() { return "; + private final static String GET_PROPERTY_NAMES_METHOD_WITH_ARRAY = GET_PROPERTY_NAMES_METHOD_COMMON_PART+" PROPERTIES;}"; + private final static String GET_PROPERTY_NAMES_METHOD_WITH_EMPTY_ARRAY = GET_PROPERTY_NAMES_METHOD_COMMON_PART+" new QName[0];}"; + private final static Logger LOGGER = Logger.get(MBeanCapabilityBuilder.class); + + /** + * Handler interface definining operation needed to be + * peformed (by a concrete implementor) when the "endAttributes" + * director callback happens. + * + * @author Andrea Gazzarini + */ + interface EndAttributesHandler { + + /** + * Concrete implementor must define in this method what + * needs to be done when the corresponding director callback + * happens (@see {@link MBeanCapabilityBuilder#endAttributes()} + * + * @throws BuilderException when a failure is raised inside the concrete implementation. + */ + void endAttributes() throws BuilderException; + }; + + /** + * This is the concrete implementation of the internal interface EndAttributesHandler + * that is activated when this builder detects the presence of at least one property on the + * capability class. + */ + final EndAttributesHandler _atLeastThereIsOneProperty = new EndAttributesHandler() { + + /** + * Creates the QName array instance member and the corresponding + * accessor getPropertyNames(). + * + * @throws BuilderException when the member above cannot be added to the capability class. + */ + public void endAttributes() throws BuilderException + { + try + { + _properties.deleteCharAt(_properties.length()-1); + _properties.append("};"); + + CtField properties = CtField.make(_properties.toString(), _capabilityClassDefinition); + + _capabilityClassDefinition.addField(properties); + + CtMethod getPropertyNames = CtNewMethod.make( + GET_PROPERTY_NAMES_METHOD_WITH_ARRAY, + _capabilityClassDefinition); + _capabilityClassDefinition.addMethod(getPropertyNames); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + }; + + /** + * This is the concrete implementation of the internal interface EndAttributesHandler + * that is activated when this builder detects that there are no properties defined for + * the capability class. + */ + final EndAttributesHandler _noPropertyHasBeenDefined= new EndAttributesHandler() + { + /** + * Creates the getPropertyNames() that simply returns an empty QName array. + * + * @throws BuilderException when the member above cannot be added to the capability class. + */ + public void endAttributes() throws BuilderException + { + try + { + CtMethod getPropertyNames = CtNewMethod.make( + GET_PROPERTY_NAMES_METHOD_WITH_EMPTY_ARRAY, + _capabilityClassDefinition); + _capabilityClassDefinition.addMethod(getPropertyNames); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + }; + + /** + * This is the active state for this builder when the requested class has never been + * built. + */ + IArtifactBuilder _classNotAvailable = new IArtifactBuilder() + { + + /** + * Build process begins. + * The given object name is used to build a minimal definition of the product class. + * + * @param objectName the name of the JMX entity. + * @throws BuilderException when the initial definiton of the capability cannot be created. + */ + public void begin(ObjectName objectName) throws BuilderException + { + String className = objectName.getKeyProperty(Names.CLASS); + ClassPool pool = ClassPool.getDefault(); + pool.insertClassPath(new ClassClassPath(MBeanCapabilityBuilder.class)); + pool.importPackage(QName.class.getPackage().getName()); + pool.importPackage(ObjectName.class.getPackage().getName()); + pool.importPackage(QManFault.class.getPackage().getName()); + pool.importPackage(Names.class.getPackage().getName()); + pool.importPackage(Result.class.getPackage().getName()); + pool.importPackage(NoSuchAttributeFault.class.getPackage().getName()); + pool.importPackage(EntityInstanceNotFoundFault.class.getPackage().getName()); + pool.importPackage(MethodInvocationFault.class.getPackage().getName()); + + _capabilityClassDefinition = pool.makeClass("org.apache.qpid.management.wsdm.capabilities."+className); + try + { + _capabilityClassDefinition.setSuperclass(pool.get(MBeanCapability.class.getName())); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + + /** + * Director callback. + * All attributes have been notified. + * + * This builder is using this callback in order to create the initial + * properties QNames declaration. + * + */ + public void endAttributes() throws BuilderException + { + _endAttributeHandler.endAttributes(); + } + + @SuppressWarnings("unchecked") + public void endOperations() throws BuilderException + { + try + { + _capabilityClass = _capabilityClassDefinition.toClass( + QManAdapterCapability.class.getClassLoader(), + QManAdapterCapability.class.getProtectionDomain()); + } catch (Exception exception) + { + throw new BuilderException(exception); + } + } + + /** + * Director callback. + * Attrbute metadata notification. With this callback the director informs this builder that the + * currently processed MBean has an attribute with the given metadata. + * This builder uses this information in order to add a property and the corresponding accessors + * to the capability class that is going to be built. + * + * @throws BuilderException bytecode manipulation / creation failure. + */ + public void onAttribute(MBeanAttributeInfo attribute) throws BuilderException + { + String name = attribute.getName(); + String type = attribute.getType(); + + try + { + type = Class.forName(type).getCanonicalName(); + + addPropertyMemberInstance(type, name); + + String nameForAccessors = getNameForAccessors(name); + + if (attribute.isReadable()) + { + String accessor = generateGetter(type, nameForAccessors,name); + CtMethod getter = CtNewMethod.make(accessor,_capabilityClassDefinition); + _capabilityClassDefinition.addMethod(getter); + appendToPropertiesArray(name); + + LOGGER.debug( + Messages.QMAN_200043_GENERATED_ACCESSOR_METHOD, + _objectName, + accessor); + } + + if (attribute.isWritable()) + { + String accessor = generateSetter(type, nameForAccessors,name); + CtMethod setter = CtNewMethod.make(accessor,_capabilityClassDefinition); + _capabilityClassDefinition.addMethod(setter); + + LOGGER.debug( + Messages.QMAN_200043_GENERATED_ACCESSOR_METHOD, + _objectName, + accessor); + } + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + + public void onOperation(MBeanOperationInfo operation) throws BuilderException + { + StringBuilder method = new StringBuilder(); + try + { + method + .append("public Result ") + .append(operation.getName()) + .append("( "); + + for (MBeanParameterInfo parameter: operation.getSignature()) + { + method + .append(Class.forName(parameter.getType()).getCanonicalName()) + .append(' ') + .append(parameter.getName()) + .append(','); + } + + method.deleteCharAt(method.length()-1); + method.append(") throws EntityInstanceNotFoundFault, MethodInvocationFault,QManFault { return invoke(") + .append("\"").append(operation.getName()).append("\"") + .append(", new Object[]{ "); + + for (MBeanParameterInfo parameter: operation.getSignature()) + { + method.append(parameter.getName()) + .append(','); + } + + method.deleteCharAt(method.length()-1); + method.append("}, new String[]{ "); + + for (MBeanParameterInfo parameter: operation.getSignature()) + { + method + .append("\"") + .append(parameter.getType()) + .append("\","); + } + method.deleteCharAt(method.length()-1); + method.append("}); }"); + + String methodAsString = method.toString(); + methodAsString = methodAsString.replace("new Object[]{}","null"); + methodAsString = methodAsString.replace("new String[]{}","null"); + + CtMethod definition = CtNewMethod.make(methodAsString,_capabilityClassDefinition); + _capabilityClassDefinition.addMethod(definition); + } catch(Exception exception) + { + throw new BuilderException(exception); + } finally { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug( + Messages.QMAN_200044_GENERATED_METHOD, + _objectName, + method.toString()); + } + } + } + + public void setEnvironment(Environment environment) + { + // Nothing to do here... + } + }; + + StringBuilder _properties = new StringBuilder("private static final QName[] PROPERTIES = new QName[]{ "); + private Class _capabilityClass; + CtClass _capabilityClassDefinition; + EndAttributesHandler _endAttributeHandler = _noPropertyHasBeenDefined; + + private ObjectName _objectName; + + IArtifactBuilder _state; + + /** + * Director callback. + * Attrbute metadata notification. With this callback the director informs this builder that the + * currently processed MBean has an attribute with the given metadata. + * This builder uses this information in order to add a property and the corresponding accessors + * to the capability class that is going to be built. + * + * @throws BuilderException bytecode manipulation / creation failure. + */ + public void onAttribute(MBeanAttributeInfo attribute) throws BuilderException + { + _state.onAttribute(attribute); + } + + /** + * First callback : this method is called at the begin of the director process. + * Contains builder initialization code. + * + * @param objectName the name of the target JMX entity of this capability. + * @throws BuilderException when the initialization fails. + */ + @SuppressWarnings("unchecked") + public void begin(ObjectName objectName) throws BuilderException + { + try + { + this._objectName = objectName; + String className = objectName.getKeyProperty(Names.CLASS); + _capabilityClass = (Class) Class.forName("org.apache.qpid.management.wsdm.capabilities."+className); + _state = new DummyCapabilityBuilder(); + } catch (ClassNotFoundException exception) + { + _state = _classNotAvailable; + } + + _state.begin(objectName); + } + + /** + * Director callback. + * Operation metadata notification. With this callback the director informs this builder that the + * currently processed MBean has an operation with the given metadata. + * This builder uses this information in order to add a method to the capability class that is + * going to be built. + * + * For example, let's suppose that an operation like that is detected on the MBean : + * + * public void purge(int request) + * + * then the capability will be enrichied with the following method : + * + * public void purge(int request) throws QManFault { + * invoke( + * "purge", + * new Object[]{request}, + * new String[]{int.class.getName()}); + * } + * + * @throws BuilderException bytecode manipulation / creation failure. + */ + public void onOperation(MBeanOperationInfo operation) throws BuilderException + { + _state.onOperation(operation); + } + + /** + * Returns the capability class (the product of this builder). + * + * @return the capability class (the product of this builder). + */ + Class getCapabilityClass() + { + return _capabilityClass; + } + + /** + * Determines what needs to be done when all attributes + * metadata has been notified to this builder. + * Capability class must have an array member with all defined + * properties and a getter method that returns it. + * In this method those two members are declared (obviously only + * if this capability has at least one property). + * + * @throws BuilderException when something fails during this phase. + */ + public void endAttributes() throws BuilderException + { + _state.endAttributes(); + } + + /** + * Director callback. + * This method is notified when all operations metadata has been + * notified to this builder. + * This is the place where the capability class is created, defined and loaded by the JVM. + * + * @throws BuilderException issues on this method are basically class loading related. + */ + @SuppressWarnings("unchecked") + public void endOperations() throws BuilderException + { + _state.endOperations(); + } + + /** + * Injects the module environment on this builder. + * + * @param environment the module environment. + */ + public void setEnvironment(Environment environment) + { + // Nothing to do here... + } + + /** + * Generates the get accessor method for the given property. + * + * @param type the type of the property. + * @param name the name of the property with the first letter capitalized. + * @param plainName the plain name of the property. + * @return the getter method (as a string). + */ + String generateGetter(String type, String name,String plainName) + { + return new StringBuilder() + .append("public ") + .append(type) + .append(' ') + .append("get") + .append(name) + .append("() throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault { return (") + .append(type) + .append(") getAttribute(\"") + .append(plainName) + .append("\"); }") + .toString(); + } + + /** + * Generates the set accessor method for the given property. + * + * @param type the type of the property. + * @param name the name of the property with the first letter capitalized. + * @param plainName the plain name of the property. + * @return the setter method (as a string). + */ + String generateSetter(String type, String name, String plainName) + { + return new StringBuilder() + .append("public void ") + .append("set") + .append(name) + .append("(") + .append(type) + .append(" newValue) throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault {") + .append(" setAttribute(\"") + .append(plainName) + .append("\", newValue); }") + .toString(); + } + + /** + * Appends the given attribute name to the properties array declared as an + * instance member of the capability class. + * + * @param attributeName the name of the attribute. + */ + private void appendToPropertiesArray(String attributeName) + { + _properties.append("new QName(Names.NAMESPACE_URI, \"") + .append(attributeName) + .append("\", Names.PREFIX),"); + + _endAttributeHandler = _atLeastThereIsOneProperty; + } + + /** + * Adds a new property member instance to the capability class. + * + * @param type the type of the property. + * @param name the name of the property. + * @throws CannotCompileException when the property cannot be added. + */ + private void addPropertyMemberInstance(String type, String name) throws CannotCompileException + { + StringBuilder buffer = new StringBuilder() + .append("private ") + .append(type) + .append(' ') + .append(name) + .append(';'); + + CtField field= CtField.make(buffer.toString(),_capabilityClassDefinition); + _capabilityClassDefinition.addField(field); + } + + /** + * Returns a name that will be used in accessor methods. + * That name will differ from the given one because the first letter will be capitalized. + * For example, if the given name is "name" the return value will be "Name". + * + * @param name the plain name of the attribute. + * @return a capitalized version of the given name to be used in accessors. + */ + String getNameForAccessors(String name) + { + return + Character.toUpperCase(name.charAt(0)) + + name.substring(1); + } + +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java new file mode 100644 index 0000000000..414f37a746 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java @@ -0,0 +1,557 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import javax.xml.namespace.QName; + +import org.apache.muse.core.AbstractCapability; +import org.apache.muse.core.Resource; +import org.apache.muse.core.ResourceManager; +import org.apache.muse.core.routing.MessageHandler; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.notification.NotificationProducer; +import org.apache.muse.ws.notification.WsnConstants; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.configuration.Configuration; +import org.apache.qpid.management.jmx.EntityLifecycleNotification; +import org.apache.qpid.management.wsdm.common.ThreadSessionManager; +import org.apache.qpid.management.wsdm.common.UnableToConnectWithBrokerFault; +import org.apache.qpid.management.wsdm.muse.engine.WSDMAdapterEnvironment; +import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer; +import org.apache.qpid.management.wsdm.notifications.LifeCycleEvent; +import org.apache.qpid.transport.util.Logger; + +/** + * QMan Adapter capability. + * Basically it acts as a lifecycle manager of all ws resource that correspond to entities on JMX side. + * + * @author Andrea Gazzarini +*/ +@SuppressWarnings("serial") +public class QManAdapterCapability extends AbstractCapability +{ + private final static Logger LOGGER = Logger.get(QManAdapterCapability.class); + + private MBeanServer _mxServer; + private WsArtifactsFactory _artifactsFactory; + private URI _resourceURI; + private NotificationProducer _publisherCapability; + private ThreadPoolExecutor _workManager; + private Map _lifeCycleTopics = new HashMap(); + + /** + * Runnable wrapper used for sending asynchronous + * notifications. + * + * @author Andrea Gazzarini + */ + private final class AsynchNotificationTask implements Runnable + { + private final QName topicName; + private final LifeCycleEvent event; + + AsynchNotificationTask(QName tName, LifeCycleEvent evt) + { + topicName = tName; + event = evt; + } + + public void run() + { + try + { + _publisherCapability.publish(topicName,event); + } catch (SoapFault exception) + { + LOGGER.error( + exception, + Messages.QMAN_100038_UNABLE_TO_SEND_WS_NOTIFICATION); + } + } + }; + + /** + * NotificationFilter for "create" only events. + */ + private final NotificationFilter _filterForNewInstances = new NotificationFilter(){ + + /** + * Returns true when the notification is related to a creation of a new instance. + * + * @return true when the notification is related to a creation of a new instance. + */ + public boolean isNotificationEnabled(Notification notification) + { + return EntityLifecycleNotification.INSTANCE_ADDED_NOTIFICATION_TYPE.equals(notification.getType()); + } + + }; + + /** + * NotificationFilter for "remove" only events. + */ + private final NotificationFilter _filterForRemovedInstances = new NotificationFilter(){ + + /** + * Returns true when the notification is related to a deletion of an existing instance. + * + * @return true when the notification is related to a deletion of an existing instance. + */ + public boolean isNotificationEnabled(Notification notification) + { + return EntityLifecycleNotification.INSTANCE_REMOVED_NOTIFICATION_TYPE.equals(notification.getType()); + } + }; + + /** + * This listener handles "create" mbean events and therefore provides procedure to create and initialize + * corresponding ws resources. + */ + private final NotificationListener _listenerForNewInstances = new NotificationListener() + { + /** + * Handles JMX "create" notification type. + * + * @param notification the entity lifecycle notification. + * @param data user data associated with the incoming notifiication : it is not used at the moment. + */ + public void handleNotification(Notification notification, Object data) + { + ObjectName eventSourceName = null; + try + { + EntityLifecycleNotification lifecycleNotification = (EntityLifecycleNotification) notification; + eventSourceName = lifecycleNotification.getObjectName(); + + ThreadSessionManager.getInstance().getSession().setObjectName(eventSourceName); + + LOGGER.debug(Messages.QMAN_200039_DEBUG_JMX_NOTIFICATION, notification); + + ResourceManager resourceManager = getResource().getResourceManager(); + Resource resource = resourceManager.createResource(Names.QMAN_RESOURCE_NAME); + + WsArtifacts artifacts = _artifactsFactory.getArtifactsFor(resource,eventSourceName); + MBeanCapability capability = _artifactsFactory.createCapability( + artifacts.getCapabilityClass(), + eventSourceName); + + ThreadSessionManager.getInstance().getSession().setWsdlDocument(artifacts.getWsdl()); + ThreadSessionManager.getInstance().getSession().setResourceMetadataDescriptor(artifacts.getResourceMetadataDescriptor()); + + resource.setWsdlPortType(Names.QMAN_RESOURCE_PORT_TYPE_NAME); + capability.setCapabilityURI(Names.NAMESPACE_URI+"/"+capability.getClass().getSimpleName()); + capability.setMessageHandlers(createMessageHandlers(capability)); + + resource.addCapability(capability); + resource.initialize(); + resourceManager.addResource(resource.getEndpointReference(), resource); + + LOGGER.info( + Messages.QMAN_000030_RESOURCE_HAS_BEEN_CREATED, + eventSourceName); + + AsynchNotificationTask asynchNotificationTask = new AsynchNotificationTask( + getTopicName(lifecycleNotification.getClassKind()), + LifeCycleEvent.newCreateEvent( + eventSourceName.getKeyProperty(Names.OBJECT_ID), + lifecycleNotification.getPackageName(), + lifecycleNotification.getClassName())); + + _workManager.execute(asynchNotificationTask); + + } catch (ArtifactsNotAvailableException exception) + { + LOGGER.error( + exception, + Messages.QMAN_100023_BUILD_WS_ARTIFACTS_FAILURE); + } catch (IllegalAccessException exception) + { + LOGGER.error( + exception, + Messages.QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE, + eventSourceName); + } catch (InstantiationException exception) + { + LOGGER.error( + exception, + Messages.QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE, + eventSourceName); + } catch (SoapFault exception) + { + LOGGER.error( + exception,Messages.QMAN_100025_WSRF_FAILURE, + eventSourceName); + } catch (Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100025_WSRF_FAILURE, + eventSourceName); + } + } + }; + + /** + * This listener handles "remove" mbean events and therefore provides procedure to shutdown and remove + * corresponding ws resources. + */ + private final NotificationListener _listenerForRemovedInstances = new NotificationListener() + { + /** + * Handles JMX "remove" notification type. + * + * @param notification the entity lifecycle notification. + * @param data user data associated with the incoming notifiication : it is not used at the moment. + */ + public void handleNotification(Notification notification, Object data) + { + EntityLifecycleNotification lifecycleNotification = (EntityLifecycleNotification) notification; + ObjectName eventSourceName = lifecycleNotification.getObjectName(); + + LOGGER.debug(Messages.QMAN_200042_REMOVING_RESOURCE, eventSourceName); + + EndpointReference endpointPointReference = new EndpointReference(_resourceURI); + endpointPointReference.addParameter( + Names.RESOURCE_ID_QNAME, + eventSourceName.getKeyProperty(Names.OBJECT_ID)); + + ResourceManager resourceManager = getResource().getResourceManager(); + try + { + Resource resource = resourceManager.getResource(endpointPointReference); + resource.shutdown(); + + LOGGER.info( + Messages.QMAN_000031_RESOURCE_HAS_BEEN_REMOVED, + eventSourceName); + + AsynchNotificationTask asynchNotificationTask = new AsynchNotificationTask( + getTopicName(lifecycleNotification.getClassKind()), + LifeCycleEvent.newRemoveEvent( + eventSourceName.getKeyProperty(Names.OBJECT_ID), + lifecycleNotification.getPackageName(), + lifecycleNotification.getClassName())); + + _workManager.execute(asynchNotificationTask); + + } + catch(Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100027_RESOURCE_SHUTDOWN_FAILURE, + eventSourceName); + } + } + }; + + /** + * Initializes this capability. + * + * @throws SoapFault when the initialization fails.. + */ + @Override + public void initialize() throws SoapFault + { + super.initialize(); + + registerByteArraySerializer(); + + createLifeCycleTopics(); + + initializeWorkManager(); + + createQManResourceURI(); + + _mxServer = ManagementFactory.getPlatformMBeanServer(); + _artifactsFactory = new WsArtifactsFactory(getEnvironment(),_mxServer); + + registerQManLifecycleListeners(); + } + + /** + * Connects QMan with a broker with the given connection data. + * + * @param host the host where the broker is running. + * @param port the port number where the broker is running. + * @param username username for estabilshing connection. + * @param password password for estabilshing connection. + * @param virtualHost the virtualHost name. + * @param initialPoolCapacity the initial size of broker connection pool. + * @param maxPoolCapacity the max allowed size of broker connection pool. + * @param maxWaitTimeout the max wait timeout for retrieving connections. + * @throws SoapFault when the connection with broker cannot be estabilished. + */ + @SuppressWarnings("unchecked") + public void connect( + String host, + int port, + String username, + String password, + String virtualHost, + int initialPoolCapacity, + int maxPoolCapacity, + long maxWaitTimeout) throws SoapFault + { + try + { + _mxServer.invoke( + Names.QMAN_OBJECT_NAME, + "addBroker", + new Object[]{host,port,username,password,virtualHost,initialPoolCapacity,maxPoolCapacity,maxWaitTimeout}, + new String[]{ + String.class.getName(), + int.class.getName(), + String.class.getName(), + String.class.getName(), + String.class.getName(), + int.class.getName(), + int.class.getName(), + long.class.getName()}); + } catch(Exception exception) + { + LOGGER.error(Messages.QMAN_100017_UNABLE_TO_CONNECT,host,port); + throw new UnableToConnectWithBrokerFault( + getResource().getEndpointReference(), + host, + port, + username, + virtualHost, + exception.getMessage()); + } + } + + /** + * Creates the message handlers for the given capability. + * + * @param capability the QMan capability. + * @return a collection with message handlers for the given capability. + */ + protected Collection createMessageHandlers(MBeanCapability capability) + { + Collection handlers = new ArrayList(); + + for (Method method : capability.getClass().getDeclaredMethods()) + { + String name = method.getName(); + + QName requestName = new QName( + Names.NAMESPACE_URI, + name, + Names.PREFIX); + + QName returnValueName = new QName( + Names.NAMESPACE_URI, + name+"Response", + Names.PREFIX); + + String actionURI = Names.NAMESPACE_URI+"/"+name; + + MessageHandler handler = new QManMessageHandler( + actionURI, + requestName, + returnValueName); + + handler.setMethod(method); + handlers.add(handler); + } + return handlers; + } + + /** + * Returns the publisher capability associated with the owner resource. + * + * @return the publisher capability associated with the owner resource. + */ + NotificationProducer getPublisherCapability() + { + return (NotificationProducer) getResource().getCapability(WsnConstants.PRODUCER_URI); + } + + /** + * Creates events & objects lifecycle topic that will be used to publish lifecycle event + * messages.. + */ + void createLifeCycleTopics() + { + try + { + _publisherCapability = getPublisherCapability(); + + _publisherCapability.addTopic(Names.EVENTS_LIFECYLE_TOPIC_NAME); + _lifeCycleTopics.put(Names.EVENT,Names.EVENTS_LIFECYLE_TOPIC_NAME); + + LOGGER.info( + Messages.QMAN_000032_EVENTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED, + Names.OBJECTS_LIFECYLE_TOPIC_NAME); + + _publisherCapability.addTopic(Names.OBJECTS_LIFECYLE_TOPIC_NAME); + _lifeCycleTopics.put(Names.CLASS,Names.OBJECTS_LIFECYLE_TOPIC_NAME); + + LOGGER.info( + Messages.QMAN_000033_OBJECTS_LIFECYCLE_TOPIC_HAS_BEEN_CREATED, + Names.OBJECTS_LIFECYLE_TOPIC_NAME); + + _publisherCapability.addTopic(Names.UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME); + LOGGER.info( + Messages.QMAN_000034_UNCLASSIFIED_LIFECYCLE_TOPIC_HAS_BEEN_CREATED, + Names.OBJECTS_LIFECYLE_TOPIC_NAME); + } catch(Exception exception) + { + LOGGER.error(exception, Messages.QMAN_100036_TOPIC_DECLARATION_FAILURE); + } + } + + /** + * Starting from an object type (i.e. event or class) returns the name of the + * corresponding topic where the lifecycle message must be published. + * Note that if the given object type is unknown then the "Unclassified Object Types" topic + * will be returned (and therefore the message will be published there). + * + * @param objectType the type of the object. + * @return the name of the topic associated with the given object type. + */ + QName getTopicName(String objectType) + { + QName topicName = _lifeCycleTopics.get(objectType); + return (topicName != null) + ? topicName + : Names.UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME; + } + + /** + * Workaround : it seems that is not possibile to declare a serializer + * for a byte array using muse descriptor... + * What is the stringified name of the class? + * byte[].getClass().getName() is [B but is not working (ClassNotFound). + * So, at the end, this is hard-coded here! + */ + private void registerByteArraySerializer() + { + SerializerRegistry.getInstance().registerSerializer( + byte[].class, + new ByteArraySerializer()); + } + + /** + * Creates the URI that will be later used to identify a QMan WS-Resource. + * Note that the resources that will be created are identified also with their resource id. + * Briefly we could say that this is the soap:address of the WS-Resource definition. + * + * @throws SoapFault when the URI cannot be built (probably it is malformed). + */ + private void createQManResourceURI() throws SoapFault + { + WSDMAdapterEnvironment environment = (WSDMAdapterEnvironment) getEnvironment(); + String resourceURI = environment.getDefaultURIPrefix()+Names.QMAN_RESOURCE_NAME; + try + { + _resourceURI = URI.create(resourceURI); + + } catch(IllegalArgumentException exception) + { + LOGGER.info( + exception, + Messages.QMAN_100029_MALFORMED_RESOURCE_URI_FAILURE, + resourceURI); + throw new SoapFault(exception); + } + } + + /** + * Initializes the work manager used for asynchronous notifications. + */ + private void initializeWorkManager() + { + Configuration configuration = Configuration.getInstance(); + _workManager = new ThreadPoolExecutor( + configuration.getWorkerManagerPoolSize(), + configuration.getWorkerManagerMaxPoolSize(), + configuration.getWorkerManagerKeepAliveTime(), + TimeUnit.MILLISECONDS, + new ArrayBlockingQueue(30)); + } + + /** + * This adapter capability needs to be an event listener of QMan JMX core + * in order to detect relevant lifecycle events and therefore create WS artifacts & notification(s). + * + * @throws SoapFault when it's not possible to register event listener : is QMan running? + */ + @SuppressWarnings("serial") + private void registerQManLifecycleListeners() throws SoapFault + { + try + { + _mxServer.addNotificationListener( + Names.QMAN_OBJECT_NAME, + _listenerForNewInstances, + _filterForNewInstances, + null); + + _mxServer.addNotificationListener( + Names.QMAN_OBJECT_NAME, + _listenerForRemovedInstances, + _filterForRemovedInstances, + null); + + try + { + _mxServer.addNotificationListener( + Names.QPID_EMULATOR_OBJECT_NAME, + _listenerForNewInstances, + _filterForNewInstances, null); + + _mxServer.addNotificationListener( + Names.QPID_EMULATOR_OBJECT_NAME, + _listenerForRemovedInstances, + _filterForRemovedInstances, null); + + } catch (Exception exception) + { + LOGGER.info(Messages.QMAN_000028_TEST_MODULE_NOT_FOUND); + } + } catch(InstanceNotFoundException exception) + { + throw new SoapFault(exception); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java new file mode 100644 index 0000000000..95f54ef5b5 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMessageHandler.java @@ -0,0 +1,104 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.reflect.Method; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.routing.ReflectionMessageHandler; +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer; +import org.w3c.dom.Element; + +/** + * JMXConnectionListener_example custom implementation of Muse message handler to properly deal with + * byte arrays. + * + * @author Andrea Gazzarini + */ +public class QManMessageHandler extends ReflectionMessageHandler +{ + + /** + * Builds a new message handler with the given arguments. + * + * @param actionURI the action URI. + * @param requestQName the qname of the incoming request. + * @param returnValueName the qname of the result value. + */ + public QManMessageHandler(String actionURI, QName requestQName, + QName returnValueName) + { + super(actionURI, requestQName, returnValueName); + } + + /** + * Transforms the given xml element in the corresponding + * object representation. + * + * @throws SoapFaul when unmarshal operation fails. + */ + @SuppressWarnings("unchecked") + public Object[] fromXML(Element xml) throws SoapFault + { + Method method = getMethod(); + + if (xml == null ) + { + return EMPTY_REQUEST; + } + + Class[] parameters = method.getParameterTypes(); + Object[] objects = new Object[parameters.length]; + + Element[] elements = XmlUtils.getAllElements(xml); + + if (parameters.length == 1 && elements.length == 0) + { + elements = new Element[]{ xml }; + } + + if (elements.length != parameters.length) + { + throw new SoapFault("IncorrectParams"); + } + + SerializerRegistry registry = SerializerRegistry.getInstance(); + + for (int i = 0; i < elements.length; ++i) + { + Class clazz = parameters[i]; + if (clazz == byte[].class) + { + objects[i] = new ByteArraySerializer().fromXML(elements[i]); + } else + { + Serializer ser = registry.getSerializer(parameters[i]); + objects[i] = ser.fromXML(elements[i]); + } + } + return objects; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java new file mode 100644 index 0000000000..d6255d0bed --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java @@ -0,0 +1,99 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.metadata.WsxConstants; +import org.apache.muse.ws.resource.WsResource; +import org.apache.muse.ws.resource.metadata.MetadataDescriptor; +import org.apache.muse.ws.resource.metadata.WsrmdConstants; +import org.apache.muse.ws.resource.metadata.ext.WsrfMetadataExchange; +import org.apache.muse.ws.wsdl.WsdlUtils; +import org.apache.qpid.management.wsdm.muse.resources.QManWsResource; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * QMan resource metadata exchange. + * We cannot resuse the preexisting classes directly because the wsdl of the service instance + * is retrieved using a file path. + * Since the owner resource (QManWsResource) is dynamic (I mean, its interface is dynamic), the corresponding + * WSDL cannot defined at compile time but needs some changes when the resource is created. + * As part of that, the WSDL template found under wsdl folder is modified with the additional properties of the given + * resource. The metadata exchange capability must include those properties too. + * + * Note that this capability is appliable only to a QManWsResource. + * + * @author Andrea Gazzarini + */ +public class QManMetadataExchangeCapability extends WsrfMetadataExchange +{ + /** + * Returns the WSDL associated with the owner of this capability. + * + * @return the WSDL associated with the owner of this capability. + */ + @Override + protected Element getWSDL() + { + QManWsResource resource = (QManWsResource) getResource(); + + Document wsdlDoc = resource.getWsdl(); + Element wsdl = XmlUtils.getFirstElement(wsdlDoc); + + WsdlUtils.removeWsdlReferences(wsdl); + WsdlUtils.removeSchemaReferences(wsdl); + + return wsdl; + } + + /** + * Returns the resource metadata descriptor associated with the owenr + * resource of thi capability. + * + * @return the resource metadata descriptor. + */ + protected Element getResourceMetadataDescriptor() + { + WsResource resource = (WsResource)getResource(); + MetadataDescriptor metadataDescriptor = resource.getPropertyCollection().getMetadata(); + return metadataDescriptor.toXML(); + } + + public Element[] getMetadata(String dialect) + { + if (dialect == null) + { + return new Element[]{ + getResourceMetadataDescriptor(), + getWSDL()}; + } else { + if (WsrmdConstants.NAMESPACE_URI.equals(dialect)) + { + return new Element[]{getResourceMetadataDescriptor()}; + } else if (WsxConstants.WSDL_DIALECT.equals(dialect)) + { + return new Element[]{getWSDL()}; + } + } + return super.getMetadata(dialect); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java new file mode 100644 index 0000000000..a00d2665ae --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.util.*; + +/** + * Data Transfer Object that encapsulates the result of a method invocation. + * This is the object that will be marshalled in XML and will contain the result of a method + * invocation (status code & text). + * + * @author Andrea Gazzarini + */ +public final class Result +{ + private final Map _outputParameters; + + /** + * Builds a new result DTO with the given parameters. + * + * @param statusCode the return code. + * @param statusText the status message. + * @param outputParameters the output parameters. + */ + public Result(Map outputParameters) + { + this._outputParameters = outputParameters; + } + + /** + * Returns the output parameterss. + * + * @return the output parameterss. + */ + public Map getOutputParameters() + { + return _outputParameters; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java new file mode 100644 index 0000000000..c1678eb43f --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilder.java @@ -0,0 +1,135 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.util.ArrayList; +import java.util.List; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanOperationInfo; +import javax.management.ObjectName; + +import org.apache.muse.core.Environment; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.resource.metadata.WsrmdConstants; +import org.apache.qpid.management.Names; +import org.apache.qpid.qman.debug.WsdlDebugger; +import org.w3c.dom.Element; + +/** + * Resource Metadata Descriptor Builder. + * It is used for build the metadata descriptor for properties of the + * incoming jmx object. + * + * @author Andrea Gazzarini + */ +class RmdBuilder implements IArtifactBuilder +{ + private List _metadataDescriptor = new ArrayList(); + + ObjectName _objectName; + + /** + * Nothing to be done here on this builder. + * Simply logs a message indicating the target object name. + * + * @param objectName the jmx name of the object that is going to be processed. + */ + public void begin(ObjectName objectName) + { + this._objectName = objectName; + } + + /** + * Nothing to be done here on this builder. + * + * @throws BuilderException never. + */ + public void endAttributes() + { + // N.A. for this builder. + } + + /** + * Nothing to be done here on this builder. + * + * @throws BuilderException never. + */ + public void endOperations() + { + // N.A. for this builder. + } + + /** + * Process a single attribute metadata. + * An attribute (that is, a property) represented by the corresponding incoming + * attribute metadata will generate an wsrmd:Property xml element with the constraints + * (initial values, static values, allowed values) contained on the metadata. + * + * @param attributeMetadata the attribute (jmx) metadata. + */ + public void onAttribute(MBeanAttributeInfo attributeMetadata) + { + Element property = XmlUtils.createElement(WsrmdConstants.PROPERTY_QNAME); + property.setAttribute(Names.NAME_ATTRIBUTE, Names.PREFIX+":"+attributeMetadata.getName()); + property.setAttribute(Names.MODIFIABILITY, + attributeMetadata.isWritable() + ? Names.READ_WRITE + : Names.READ_ONLY); + property.setAttribute(Names.MUTABILITY,Names.MUTABLE); + + WsdlDebugger.debug(_objectName, property); + + _metadataDescriptor.add(property); + } + + /** + * Nothing to be done here on this builder. + * + * @throws BuilderException never. + */ + public void onOperation(MBeanOperationInfo operation) + { + // N.A. for this builder + } + + /** + * Nothing to be done here on this builder. + * + * @throws BuilderException never. + */ + public void setEnvironment(Environment environment) + { + // N.A. for this builder + } + + /** + * Nothing to be done here on this builder. + * + * @throws BuilderException never. + */ + public Element[] getResourceMetadataDescriptor() + { + Element [] properties = _metadataDescriptor.toArray( + new Element[_metadataDescriptor.size()]); + return properties; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java new file mode 100644 index 0000000000..35a919c295 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java @@ -0,0 +1,196 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.ObjectName; + +import org.apache.muse.core.Environment; +import org.apache.muse.core.Resource; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Director used for coordinate the building process of WS-DM artifacts. + * + * @author Andrea Gazzarini + */ +final class WSDMArtifactsDirector +{ + private final ObjectName _eventSourceObjectName; + private final MBeanInfo _metadata; + + private final MBeanCapabilityBuilder _capabilityBuilder; + private final WsdlBuilder _wsdlBuilder; + private final RmdBuilder _rmdBuilder; + + /** + * Builds a new director with the given objectname and (jmx) metadata. + * + * @param eventSourceObjectName the object name of the event source mbean. + * @param metadata the jmx metadata of the corresponding mbean. + */ + WSDMArtifactsDirector(ObjectName eventSourceObjectName, MBeanInfo metadata) + { + this._eventSourceObjectName = eventSourceObjectName; + this._metadata = metadata; + + _wsdlBuilder = new WsdlBuilder(); + _capabilityBuilder = new MBeanCapabilityBuilder(); + _rmdBuilder = new RmdBuilder(); + } + + /** + * Starts the build process of this director. + * This method acts as a facade of the whole build process. + * + * @throws BuilderException when one step of the build process fails. + */ + void direct() throws BuilderException + { + processObjectName(); + processAttributes(); + endAttributes(); + processOperations(); + endOperations(); + } + + /** + * Notifiies builder that all the operations metadata have been transmitted. + * + * @throws BuilderException when one builder raises an exception during this operation. + */ + private void endOperations() throws BuilderException + { + _capabilityBuilder.endOperations(); + _wsdlBuilder.endOperations(); + _rmdBuilder.endOperations(); + } + + /** + * Notifiies builder that all the attributes metadata have been transmitted. + * + * @throws BuilderException when one builder raises an exception during this operation. + */ + private void endAttributes() throws BuilderException + { + _capabilityBuilder.endAttributes(); + _wsdlBuilder.endAttributes(); + _rmdBuilder.endAttributes(); + } + + /** + * Injects event source object name on all builders. + * + * @throws BuilderException when one builder raises an exception during this operation. + */ + void processObjectName() throws BuilderException + { + _capabilityBuilder.begin(_eventSourceObjectName); + _wsdlBuilder.begin(_eventSourceObjectName); + _rmdBuilder.begin(_eventSourceObjectName); + } + + /** + * Injects attributes metadata on all builders. + * + * @throws BuilderException when one builder raises an exception during this operation. + */ + void processAttributes() throws BuilderException + { + for (MBeanAttributeInfo attribute : _metadata.getAttributes()) + { + _capabilityBuilder.onAttribute(attribute); + _wsdlBuilder.onAttribute(attribute); + _rmdBuilder.onAttribute(attribute); + } + } + + /** + * Injects operations metadata on all builders. + * + * @throws BuilderException when one builder raises an exception during this operation. + */ + void processOperations() throws BuilderException + { + for (MBeanOperationInfo operation : _metadata.getOperations()) + { + _capabilityBuilder.onOperation(operation); + _wsdlBuilder.onOperation(operation); + } + } + + /** + * Returns the capabilty class. + * + * @return the capability class. + */ + Class getCapabilityClass() + { + return _capabilityBuilder.getCapabilityClass(); + } + + /** + * Returns the wsdl. + * + * @return the wsdl. + */ + Document getWsdl() + { + return _wsdlBuilder.getWsdl(); + } + + /** + * Returns the resource metadata descriptor containing metadata (rules, constraints, etc) + * for the current resource. + * The returned object is an array of Element and each of them maps a resource property. + * + * @return the resource metadata descriptor (as an array of Element). + */ + Element [] getResourceMetadataDescriptor() + { + return _rmdBuilder.getResourceMetadataDescriptor(); + } + + /** + * Injects the environment on this director. + * + * @param environment the QMan environment. + */ + void setEnvironment(Environment environment) + { + _wsdlBuilder.setEnvironment(environment); + _capabilityBuilder.setEnvironment(environment); + _rmdBuilder.setEnvironment(environment); + } + + /** + * Injectcs the ws resource on this director. + * + * @param resource the ws resource. + */ + public void setResource(Resource resource) + { + _wsdlBuilder.setWsdlPath(resource.getWsdlPath()); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java new file mode 100644 index 0000000000..ac4636b9c9 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifacts.java @@ -0,0 +1,93 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Web Service Artifacts. + * Basically it acts as a container for all artifacts built when a new WS-Resource is created. + * With WS artifacts we mean : + * + *
    + *
  • Capability class (which encapsulate the WS-DM capability concern)
  • + *
  • WS Resource Metadata Descriptor (RMD)
  • + *
  • Web Service Description (WSDL)
  • + *
+ * + * @author Andrea Gazzarini + */ +class WsArtifacts { + + private final Class_capabilityClass; + private final Element[] _resourceMetadataDescriptor; + private final Document _wsdl; + + /** + * Builds a new artifacts container with the given artifacts. + * + * @param capabilityClass the capability class. + * @param resourceMetadataDescriptor the resource metadata descriptor. + * @param wsdl the wsdl. + */ + public WsArtifacts( + Class capabilityClass, + Element[] resourceMetadataDescriptor, + Document wsdl) + { + this._capabilityClass = capabilityClass; + this._resourceMetadataDescriptor = resourceMetadataDescriptor; + this._wsdl = wsdl; + } + + /** + * Returns the capability class. + * + * @return the capability class. + */ + Class getCapabilityClass() + { + return _capabilityClass; + } + + /** + * Returns the resource metadata descriptor. + * It is not a whole document but each property metadata is described in a + * separated element so the returned object is an array of elements. + * + * @return the resource metadata descriptor. + */ + Element[] getResourceMetadataDescriptor() + { + return _resourceMetadataDescriptor; + } + + /** + * Returns the web service description. + * + * @return the web service description (WSDL). + */ + Document getWsdl() + { + return _wsdl; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java new file mode 100644 index 0000000000..94505d28f7 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsArtifactsFactory.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.muse.core.Environment; +import org.apache.muse.core.Resource; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.transport.util.Logger; + +/** + * Manager for all WS-* related artifacts. + * Basically it is a factory ehnanced with a _cache mechanism so each created resource + * (WSDL, capability class, descriptor) is created and its reference is returned when requested + * again. + * + * @author Andrea Gazzarini + */ +class WsArtifactsFactory +{ + private final static Logger LOGGER = Logger.get(WsArtifactsFactory.class); + + private final MBeanServer _mxServer; + private final Environment _environment; + private Map _cache; + + /** + * Builds a new factory with the given environment and mbean server. + * + * @param environment the builder environment. + * @param mxServer the management server. + */ + public WsArtifactsFactory(Environment environment, MBeanServer mxServer) + { + this._environment = environment; + this._mxServer = mxServer; + this._cache = new HashMap(); + } + + /** + * Returns the WS artifacts corresponding with the given resource. + * + * @param resource the WS resource. + * @param objectName the resource identifier (name). + * @return the WS artifacts corresponding with the given resource. + * @throws ArtifactsNotAvailableException when some problem occurs during artifacts generation. + */ + @SuppressWarnings("unchecked") + WsArtifacts getArtifactsFor(Resource resource, ObjectName objectName) throws ArtifactsNotAvailableException + { + WsArtifacts result = null; + try + { + Hashtable keyProperties = objectName.getKeyPropertyList(); + keyProperties.remove(Names.NAME_ATTRIBUTE); + keyProperties.remove(Names.OBJECT_ID); + + ObjectName searchKey = ObjectName.getInstance(objectName.getDomain(),keyProperties); + + LOGGER.debug( + Messages.QMAN_200041_INCOMING_OBJECT_NAME_AND_DERIVED_KEY, + objectName, + searchKey); + + result = _cache.get(searchKey); + if (result == null) + { + MBeanInfo metadata = _mxServer.getMBeanInfo(objectName); + + WSDMArtifactsDirector director = new WSDMArtifactsDirector(objectName,metadata); + director.setEnvironment(_environment); + director.setResource(resource); + director.direct(); + + result = new WsArtifacts( + director.getCapabilityClass(), + director.getResourceMetadataDescriptor(), + director.getWsdl()); + + _cache.put(searchKey, result); + + LOGGER.debug( + Messages.QMAN_200040_WS_ARTIFACTS_CACHED, + searchKey); + } + + return result; + } catch(Exception exception) + { + throw new ArtifactsNotAvailableException( + result, + exception, + objectName); + } + } + + /** + * Utility method for create concrete instance of the given capability class. + * + * @param capabilityClass the capability class. + * @param objectName the object name that will act as the target for this capability invocations. + * @return an initialized instance of the given capability class. + * @throws InstantiationException when the class cannot be instantiated. + * @throws IllegalAccessException when this method does not have access to + * the definition of the capability class. + */ + MBeanCapability createCapability(Class capabilityClass, ObjectName objectName) + throws InstantiationException, IllegalAccessException + { + MBeanCapability capability = capabilityClass.newInstance(); + capability.setResourceObjectName(objectName); + return capability; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java new file mode 100644 index 0000000000..6bfccda1ce --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java @@ -0,0 +1,460 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.ObjectName; +import javax.xml.transform.TransformerException; + +import org.apache.muse.core.Environment; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.util.ReflectUtils; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.wsdl.WsdlUtils; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.wsdm.muse.engine.WSDMAdapterEnvironment; +import org.apache.qpid.management.wsdm.muse.serializer.ObjectSerializer; +import org.apache.qpid.qman.debug.WsdlDebugger; +import org.apache.qpid.transport.util.Logger; +import org.apache.xpath.XPathAPI; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +/** + * TO BE IMPROVED USING JAXB!! + * + * @author Andrea Gazzarini + */ +class WsdlBuilder implements IArtifactBuilder,Constants { + + private final static Logger LOGGER = Logger.get(WsdlBuilder.class); + + private WSDMAdapterEnvironment _environment; + private Document _document; + private Element schema; + private Element _wsrpProperties; + private ObjectSerializer _serializer; + private ObjectName _objectName; + private Map arrayTypesAlreadyDeclared = new HashMap(); + + private Element _arrayComplexType; + private Element _nestedArrayType; + + /** + * For each attibute the corresponding xml type definition must be inserted on the QMan + * schema related section. + * After that, a reference to that definition must be declared on the wsrp element . + * + * @param attributeMetadata the attribute metadata. + * @throws BuilderException only if this builder wasn't able to get a reference (via XPath) + * to QMan schema section. + */ + public void onAttribute(MBeanAttributeInfo attributeMetadata) throws BuilderException + { + try + { + String attributeName = attributeMetadata.getName(); + schema.appendChild(defineSchemaFor(attributeMetadata.getType(), attributeName)); + + Element propertyRef= XmlUtils.createElement(_document, XSD_ELEMENT_QNAME); + propertyRef.setAttribute(MIN_OCCURS, "0"); + propertyRef.setAttribute( + REF_ATTRIBUTE, + Names.PREFIX+":"+attributeName); + + _wsrpProperties.appendChild(propertyRef); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + + @SuppressWarnings("unchecked") + private Element defineSchemaFor(String type, String attributeName) throws Exception + { + Element propertyDeclaration = XmlUtils.createElement(_document, XSD_ELEMENT_QNAME); + String xmlType = null; + if (type.equals(Map.class.getName())) + { + xmlType="qman:map"; + } else if (UUID.class.getName().equals(type)) + { + xmlType = "qman:uuid"; + } else if (type.startsWith("[")) + { + Class arrayClass = Class.forName(type); + Class clazz = ReflectUtils.getClassFromArrayClass(arrayClass); + String arrayType = arrayClass.getSimpleName().replace("[]", "").trim(); + arrayType = Character.toUpperCase(arrayType.charAt(0))+arrayType.substring(1); + if (!arrayTypesAlreadyDeclared.containsKey(type)) + { + _arrayComplexType.setAttribute(NAME_ATTRIBUTE, "arrayOf"+arrayType); + _nestedArrayType.setAttribute(TYPE_ATTRIBUTE, _serializer.getXmlType(clazz)); + schema.appendChild(_arrayComplexType); + arrayTypesAlreadyDeclared.put(type, arrayType); + } + xmlType = "qman:arrayOf"+arrayTypesAlreadyDeclared.get(type); + } + else + { + xmlType = _serializer.getXmlType(Class.forName(type)); + } + propertyDeclaration.setAttribute(NAME_ATTRIBUTE,attributeName); + propertyDeclaration.setAttribute(TYPE_ATTRIBUTE, xmlType); + return propertyDeclaration; + } + + /** + * Initializes this builder. + * + * @param objectName the name of the current JMX entity. + * @throws BuilderException when it's not possible to proceed with the initialization. + */ + public void begin(ObjectName objectName) throws BuilderException + { + this._objectName = objectName; + this._serializer = (ObjectSerializer) SerializerRegistry.getInstance().getSerializer(Object.class); + + createWsrpPropertiesElement(); + + createReusableArrayComplextType(); + + replaceDummyServiceLocationOnWsdl(); + + createSchemaElement(); + } + + public void onOperation(MBeanOperationInfo operationMetadata) throws BuilderException + { + // SCHEMA SECTION + /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */ + + try + { + // + + Element methodRequestElement= _document.createElement("xsd:element"); + String methodNameRequest = operationMetadata.getName()+"Request"; + methodRequestElement.setAttribute("name", methodNameRequest); + methodRequestElement.setAttribute("type", "qman:"+methodNameRequest); + + // +// Element methodResponseElement= _document.createElement("xsd:element"); + String methodNameResponse= operationMetadata.getName()+"Response"; +// methodResponseElement.setAttribute("name", methodNameResponse); +// methodResponseElement.setAttribute("type", "qman:result");//+methodNameResponse); + + schema.appendChild(methodRequestElement); +// schema.appendChild(methodResponseElement); + + /* + + + + + + + + */ + + Element methodNameRequestComplexType = _document.createElement("xsd:complexType"); + methodNameRequestComplexType.setAttribute("name", methodNameRequest); + Element methodNameRequestComplexTypeSequence = _document.createElement("xsd:sequence"); + + for(MBeanParameterInfo parameter : operationMetadata.getSignature()) + { + methodNameRequestComplexTypeSequence.appendChild(defineSchemaFor(parameter.getType(), parameter.getName())); + } + + methodNameRequestComplexType.appendChild(methodNameRequestComplexTypeSequence); + schema.appendChild(methodNameRequestComplexType); + + /* + + + + + + + + */ + Element definitions = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions"); + + String requestMessageName = methodNameRequest+"Message"; + String responseMessageName = methodNameResponse+"Message"; + + Element requestMessage = _document.createElement("message"); + requestMessage.setAttribute("name", requestMessageName); + Element requestPart = _document.createElement("wsdl:part"); + requestPart.setAttribute("element", "qman:"+methodNameRequest); + requestPart.setAttribute("name", methodNameRequest); + requestMessage.appendChild(requestPart); + + Element responseMessage = _document.createElement("wsdl:message"); + responseMessage.setAttribute("name", responseMessageName); + Element responsePart = _document.createElement("wsdl:part"); + responsePart.setAttribute("element", "qman:result");//+methodNameResponse); + responsePart.setAttribute("name", methodNameResponse); + responseMessage.appendChild(responsePart); + + definitions.appendChild(requestMessage); + definitions.appendChild(responseMessage); + + + /* + + + + + + + */ + Element portType = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions/wsdl:portType"); + Element operation = _document.createElement("wsdl:operation"); + operation.setAttribute("name", operationMetadata.getName()); + + Element input = _document.createElement("wsdl:input"); + input.setAttribute("message", "qman:"+requestMessageName); + input.setAttribute("name", methodNameRequest); + input.setAttribute("wsa:action", Names.NAMESPACE_URI+"/"+operationMetadata.getName()); + + //name="SetResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest"/> + + operation.appendChild(input); + + Element output = _document.createElement("wsdl:output"); + output.setAttribute("message", "qman:"+responseMessageName); + output.setAttribute("name", methodNameResponse); + output.setAttribute("wsa:action", Names.NAMESPACE_URI+"/"+methodNameResponse); + + operation.appendChild(output); + + portType.appendChild(operation); + + /* + + + + + + + + + + */ + Element binding = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions/wsdl:binding"); + Element bindingOperation = _document.createElement("wsdl:operation"); + bindingOperation.setAttribute("name", operationMetadata.getName()); + + Element soapOperation = _document.createElement("wsdl-soap:operation"); + soapOperation.setAttribute("soapAction", Names.NAMESPACE_URI+"/"+operationMetadata.getName()); + + Element bindingInput = _document.createElement("wsdl:input"); + Element bodyIn = _document.createElement("wsdl-soap:body"); + bodyIn.setAttribute("use", "literal"); + + Element bindingOutput = _document.createElement("wsdl:output"); + Element bodyOut = _document.createElement("wsdl-soap:body"); + bodyOut.setAttribute("use", "literal"); + + bindingOutput.appendChild(bodyOut); + bindingInput.appendChild(bodyIn); + + bindingOperation.appendChild(soapOperation); + bindingOperation.appendChild(bindingInput); + bindingOperation.appendChild(bindingOutput); + + binding.appendChild(bindingOperation); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + + /** + * Director callback : all attributes have been notified. + * Nothing to do here. + */ + public void endAttributes() + { + // N.A. + } + + /** + * Director callback : all operations have been notified. + * Nothing to do here. + */ + public void endOperations() + { + // N.A. + } + + /** + * Returns the WSDL built by this builder. + * + * @return the WSDL built by this builder. + */ + public Document getWsdl() + { + WsdlDebugger.debug(_objectName,_document); + return _document; + } + + /** + * Injects the application context environment + * on this builder. + * + * @param environment the application context environment. + */ + public void setEnvironment(Environment environment) + { + this._environment = (WSDMAdapterEnvironment)environment; + } + + /** + * Injects the path of the wsdl document. + * + * @param wsdlPath the path of the wsdl document. + */ + public void setWsdlPath(String wsdlPath) + { + _document = WsdlUtils.createWSDL(_environment, wsdlPath, true); + } + + /** + * Create a reference to the WSRP properties element. + * + * @throws BuilderException in case of XPath evaluation problem. + */ + private void createWsrpPropertiesElement() throws BuilderException + { + try + { + _wsrpProperties = (Element) XPathAPI.selectSingleNode( + _document, + WSRP_PROPERTIES_XPATH); + } catch (TransformerException exception) + { + LOGGER.error(Messages.QMAN_100040_UNABLE_TO_LOCATE_WSRP_PROPERTIES); + throw new BuilderException(exception); + } + } + + /** + * Creates a template element that will be used for array + * type schema declaration(s). + */ + private void createReusableArrayComplextType() + { + _arrayComplexType = XmlUtils.createElement(_document, XSD_COMPLEX_TYPE_QNAME); + Element sequence = XmlUtils.createElement(_document, XSD_SEQUENCE_QNAME); + _nestedArrayType = XmlUtils.createElement(_document, XSD_ELEMENT_QNAME); + _nestedArrayType.setAttribute(NAME_ATTRIBUTE, "entry"); + sequence.appendChild(_nestedArrayType); + _arrayComplexType.appendChild(sequence); + } + + private void createSchemaElement() throws BuilderException + { + try + { + schema = (Element) XPathAPI.selectSingleNode( + _document.getDocumentElement(), + QMAN_SCHEMA_XPATH); + } catch(Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100034_WSDL_SCHEMA_SECTION_NOT_FOUND); + throw new BuilderException(exception); + } + } + + /** + * The template WSDL contains a dummy URL as service location that + * needs to be replaced with the real service address. + * + * @throws BuilderException when replacement fails (XPath problem). + */ + private void replaceDummyServiceLocationOnWsdl() throws BuilderException + { + try + { + Attr location = (Attr) XPathAPI.selectSingleNode( + _document, + SERVICE_LOCATION_XPATH); + + StringBuilder builder = new StringBuilder("http://") + .append(InetAddress.getLocalHost().getHostName()) + .append(':') + .append(System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME,"8080")) + .append('/') + .append(_environment.getContextPath()) + .append('/') + .append("services/QManWsResource"); + location.setValue(builder.toString()); + } catch(Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE); + throw new BuilderException(exception); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java new file mode 100644 index 0000000000..116d74727a --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java @@ -0,0 +1,58 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.management.ObjectName; +import javax.xml.namespace.QName; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; + +/** + * Thrown when some operation has been requested on an entity and the entity hasn't been found + * on the managed domain. + * + * @author Andrea Gazzarini + */ +public class EntityInstanceNotFoundFault extends QManFault +{ + private static final long serialVersionUID = -3772811863214553615L; + + private final static QName EXCEPTION_QNAME = new QName( + Names.NAMESPACE_URI, + "EntityInstanceNotFoundFault", + Names.PREFIX); + + /** + * Builds a new exception with the given endpoint reference and the object name of the entity + * that wasn't found. + * + * @param endpointReference the origin endpoint reference of this exception. + * @param targetEntityName the object name of the not found entity. + */ + public EntityInstanceNotFoundFault(EndpointReference endpointReference, ObjectName targetEntityName) + { + super( + endpointReference, + EXCEPTION_QNAME, + targetEntityName.getCanonicalName()); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java new file mode 100644 index 0000000000..f24c2bfd46 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.xml.namespace.QName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * This is the exception encapsulating the fault that will be thrown in case of + * method invocation failure. + * + * @author Andrea Gazzarini + */ +public class MethodInvocationFault extends QManFault +{ + private static final long serialVersionUID = 5977379710882983474L; + + private String _message; + private long _returnCode; + + /** + * Builds a new exception with the given endpoint reference and method invocation exception. + * This constructor will be used when the invocation thrown the MethodInvocationException. + * + * @param endpointReference the endpoint reference. + * @param methodName the name of the method. + * @param message the explanatio message. + * @param returnCode the a mnemonic code associated with the failure. + */ + public MethodInvocationFault( + EndpointReference endpointReference, + String methodName, + String message, + long returnCode) + { + super( + endpointReference, + new QName( + Names.NAMESPACE_URI, + "OperationInvocationFault", + Names.PREFIX), + String.format("OPERATION \"%s\" FAILURE. See detail section for further details.",methodName)); + this._message = message; + this._returnCode = returnCode; + } + + @Override + public Element getDetail() + { + Element detail = super.getDetail(); + Document owner = detail.getOwnerDocument(); + detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_TEXT_NAME,_message)); + detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_CODE_NAME,_returnCode)); + return detail; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java new file mode 100644 index 0000000000..e9f37f8afb --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java @@ -0,0 +1,70 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.xml.namespace.QName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * This is the exception encapsulating the fault that will be thrown when a requested + * attribute is not found on the target ws resource. + * + * @author Andrea Gazzarini + */ +public class NoSuchAttributeFault extends QManFault +{ + private static final long serialVersionUID = 5977379710882983474L; + + private String _attributeName; + + /** + * Builds a new exception with the given endpoint reference, JMX object name + * and attribute that hasn't been found. + * + * @param endpointReference the endpoint reference. + * @param attributeName the name of the attribute that hasn't been found. + */ + public NoSuchAttributeFault(EndpointReference endpointReference, String attributeName) + { + super( + endpointReference, + new QName( + Names.NAMESPACE_URI, + "NoSuchAttributeFault", + Names.PREFIX), + "Attribute not found on this WS-Resource."); + _attributeName = attributeName; + } + + @Override + public Element getDetail() + { + Element detail = super.getDetail(); + Document owner = detail.getOwnerDocument(); + detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_ATTRIBUTE_NAME,_attributeName)); + return detail; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java new file mode 100644 index 0000000000..eb7eee9547 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ObjectNameIdFactory.java @@ -0,0 +1,61 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.management.ObjectName; +import javax.xml.namespace.QName; + +import org.apache.muse.core.routing.ResourceIdFactory; +import org.apache.qpid.management.Names; + +/** + * ResourceIdFactory implementation that is using an objectName as + * resource identifier. + * This is done in order to make a relationship between an MBean (which is part of the + * JMX core domain model) and a WS-Resource (the same entity as is represented on WS-DM adapter side). + * + * @author Andrea Gazzarini + */ +public class ObjectNameIdFactory implements ResourceIdFactory +{ + /** + * Returns the name of the identifier element. + * + * @return the name of the identifier element. + */ + public QName getIdentifierName() + { + return Names.RESOURCE_ID_QNAME; + } + + /** + * Returns the object name used as a resource identifier. + * Developer note : this factory is highly coupled with ThreadSessionManager stuff because + * the object name that will be used as identifier is supposed to be in the thread session. + * + * @return the object name used as a resource identifier. + */ + public String getNextIdentifier() + { + ObjectName objectName = ThreadSessionManager.getInstance().getSession().getObjectName(); + return objectName.getKeyProperty(Names.OBJECT_ID); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java new file mode 100644 index 0000000000..0a52c2ba65 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManFault.java @@ -0,0 +1,72 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.xml.namespace.QName; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.basefaults.BaseFault; +import org.apache.qpid.management.Names; + +/** + * Base class for QMan thrown faults. + * This should be thrown to denote a situation where a not-well cause could be determined. + */ +public class QManFault extends BaseFault +{ + private static final long serialVersionUID = 5977379710882983474L; + private final static QName SERVICE = new QName( + Names.NAMESPACE_URI, + "QMan", + Names.PREFIX); + + private final static QName EXCEPTION_QNAME = new QName( + Names.NAMESPACE_URI, + "QManFault", + Names.PREFIX); + + /** + * Builds a new exception with the given endpoint reference and the exception cause. + * + * @param endpointReference the endpoint reference. + * @param cause the exception cause. + */ + public QManFault(EndpointReference endpointReference, Exception cause) + { + super(EXCEPTION_QNAME,cause.getMessage()); + setCode(SERVICE); + setOriginReference(endpointReference); + } + + /** + * Builds a new exception with the given endpoint reference, qname and detail message. + * + * @param endpointReference the endpoint reference. + * @param qname the qname of this exception. + * @param message the detail message of this exception. + */ + public QManFault(EndpointReference endpointReference, QName qname, String message) + { + super(qname,message); + setOriginReference(endpointReference); + setCode(SERVICE); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java new file mode 100644 index 0000000000..1a34971c6a --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/QManResourceIdFactory.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import java.util.UUID; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.routing.ResourceIdFactory; +import org.apache.qpid.management.Names; + +/** + * A simple implementation of resource id factory that uses a UUID as resource + * identifier. + * + * @author Andrea Gazzarini + */ +public class QManResourceIdFactory implements ResourceIdFactory +{ + /** + * Returns the identifier name for id element. + * + * @return the identifier name for id element. + */ + public QName getIdentifierName() + { + return Names.RESOURCE_ID_QNAME; + } + + /** + * Returns the next valid identifier. + * + * @return the next valid identifier. + */ + public String getNextIdentifier() + { + return UUID.randomUUID().toString(); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java new file mode 100644 index 0000000000..588879b951 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSession.java @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.management.ObjectName; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Thread-scoped session. + * + * @author Andrea Gazzarini + */ +public class ThreadSession +{ + private ObjectName _objectName; + private Document _wsdl; + private Element [] _wsrmdProperties; + + /** + * Empty constructor. + */ + ThreadSession() + { + } + + /** + * Gets the object name associated with this thread session. + * + * @return the object name associated with this thread session. + */ + public ObjectName getObjectName() + { + return _objectName; + } + + /** + * Sets the object name on this thread session. + * + * @param the object name of this thread session.. + */ + public void setObjectName(ObjectName objectName) + { + this._objectName = objectName; + } + + /** + * Sets the WSDL document on this thread session. + * + * @param the WSDL document of this thread session.. + */ + public void setWsdlDocument(Document wsdlDoc) + { + this._wsdl = wsdlDoc; + } + + /** + * Gets the WSDL document associated with this thread session. + * + * @return the WSDL document associated with this thread session. + */ + public Document getWsdlDocument() + { + return _wsdl; + } + + /** + * Gets the RDM elements associated with this thread session. + * + * @return the RDM elements associated with this thread session. + */ + public Element[] getResourceMetadataDescriptor() + { + return _wsrmdProperties; + } + + /** + * Sets the WSDL elements on this thread session. + * + * @param the WSDL elements of this thread session.. + */ + public void setResourceMetadataDescriptor(Element[] rmd) + { + this._wsrmdProperties = rmd; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java new file mode 100644 index 0000000000..6a081bfec4 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/ThreadSessionManager.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +/** + * Thread session manager used to handle thread-scoped sessions. + * + * @author Andrea Gazzarini + */ +public final class ThreadSessionManager +{ + private static ThreadSessionManager instance = new ThreadSessionManager(); + + private ThreadLocal sessions; + + /** + * Builds and initializes a new manager. + */ + private ThreadSessionManager() + { + this.sessions = new ThreadLocal(); + } + + /** + * Returns the singleton instance of this manager. + * + * @return the singleton instance of this manager. + */ + public static ThreadSessionManager getInstance() + { + return instance; + } + + /** + * Returns (or create and returns) the session associated with the + * current thread. + * + * @return the thread session. + */ + public ThreadSession getSession() + { + ThreadSession session = (ThreadSession) sessions.get(); + if (session == null) + { + session = new ThreadSession(); + sessions.set(session); + } + return session; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java new file mode 100644 index 0000000000..55365b4051 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/UnableToConnectWithBrokerFault.java @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.xml.namespace.QName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * This is the exception encapsulating the fault that will be thrown in case of + * broker connection failure. + * + * @author Andrea Gazzarini + */ +public class UnableToConnectWithBrokerFault extends QManFault +{ + private static final long serialVersionUID = 5977379710882983474L; + + private String _host; + private int _port; + private String _username; + private String _virtualHostName; + + /** + * Builds a new exception with the given endpoint reference and connection data. + * + * @param host the requested qpid host. + * @param port the requested qpid port. + * @param username the username used for estabilishing connection. + * @param virtualHostName the name of the target virtual host.. + */ + public UnableToConnectWithBrokerFault( + EndpointReference endpointReference, + String host, + int port, + String username, + String virtualHostName, + String message) + { + super( + endpointReference, + new QName( + Names.NAMESPACE_URI, + "UnableToConnectFault", + Names.PREFIX), + String.format("Unable to connect with the requested broker. Underlying exception message was %s",message)); + this._host = host; + this._port = port; + this._username = username; + this._virtualHostName = virtualHostName; + } + + @Override + public Element getDetail() + { + Element detail = super.getDetail(); + Document owner = detail.getOwnerDocument(); + detail.appendChild(XmlUtils.createElement(owner, Names.HOST_QNAME,_host)); + detail.appendChild(XmlUtils.createElement(owner, Names.PORT_QNAME,_port)); + detail.appendChild(XmlUtils.createElement(owner, Names.USERNAME_QNAME,_username)); + detail.appendChild(XmlUtils.createElement(owner, Names.VIRTUAL_HOST_QNAME,_virtualHostName)); + return detail; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java new file mode 100644 index 0000000000..e4d0f25adc --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterEnvironment.java @@ -0,0 +1,118 @@ +package org.apache.qpid.management.wsdm.muse.engine; +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + +import java.io.File; +import java.net.URI; + +import javax.servlet.ServletContext; + +import org.apache.muse.core.AbstractEnvironment; +import org.apache.muse.util.FileUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.transport.util.Logger; + +/** + * QMan Adapter enviroment implementation. + * + * @author Andrea Gazzarini + */ +public class WSDMAdapterEnvironment extends AbstractEnvironment +{ + private final static Logger LOGGER = Logger.get(WSDMAdapterEnvironment.class); + private final File _realDirectory; + private final ServletContext _servletContext; + + /** + * Builds a new qman environment with the given application context. + * + * @param servletContext the application context. + */ + public WSDMAdapterEnvironment(ServletContext servletContext) + { + this._servletContext = servletContext; + String realDirectoryPath = servletContext.getRealPath(Names.WEB_APP_CLASSES_FOLDER); + + _realDirectory = (realDirectoryPath != null) + ? new File(realDirectoryPath) + : FileUtils.CURRENT_DIR; + + String defaultURI = getDefaultURIPrefix()+"adapter"; + setDefaultURI(defaultURI); + + LOGGER.info(Messages.QMAN_000029_DEFAULT_URI, defaultURI); + } + + /** + * Returns the endpoint created starting by this application default URI. + * + * @return the endpoint created starting by this application default URI. + */ + public EndpointReference getDeploymentEPR() + { + return new EndpointReference(URI.create(getDefaultURI())); + } + + /** + * Returns the application classes folder. + * + * @return the application classes folder. + */ + public File getRealDirectory() + { + return _realDirectory; + } + + /** + * Returns the default endpoint reference URI. + * + * @return the default endpoint reference URI. + */ + public String getDefaultURIPrefix() + { + return new StringBuilder() + .append("http://") + .append(System.getProperty( + Names.ADAPTER_HOST_PROPERTY_NAME, + Protocol.DEFAULT_QMAN_HOSTNAME)) + .append(":") + .append(System.getProperty( + Names.ADAPTER_PORT_PROPERTY_NAME, + String.valueOf(Protocol.DEFAULT_QMAN_PORT_NUMBER))) + .append(_servletContext.getContextPath()) + .append("/services/") + .toString(); + } + + /** + * Returns the context path name of QMan application. + * + * @return the context path name of QMan application. + */ + public String getContextPath() + { + return _servletContext.getContextPath(); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java new file mode 100644 index 0000000000..e9a74bf60c --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/engine/WSDMAdapterIsolationLayer.java @@ -0,0 +1,57 @@ +package org.apache.qpid.management.wsdm.muse.engine; +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + +import javax.servlet.ServletContext; + +import org.apache.muse.core.Environment; +import org.apache.muse.core.platform.mini.MiniIsolationLayer; + +/** + * QMan specific implementation of the Apache Muse isolation layer. + * If you are a Muse expert you were wondering why don't we use the muse default implementation... + * well, + * + * @author Andrea Gazzarini + */ +public class WSDMAdapterIsolationLayer extends MiniIsolationLayer +{ + /** + * Builds a new isolation layer with the given application context. + * + * @param initialContext the application context. + */ + public WSDMAdapterIsolationLayer(ServletContext initialContext) + { + super(null, initialContext); + } + + /** + * WSDMAdapterEnvironment factory method. + * + * @return the environment. + */ + protected Environment createEnvironment() + { + return new WSDMAdapterEnvironment(getInitialContext()); + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java new file mode 100644 index 0000000000..c16c156b73 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java @@ -0,0 +1,762 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.resources; + +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.Capability; +import org.apache.muse.core.Environment; +import org.apache.muse.core.ResourceManager; +import org.apache.muse.core.routing.MessageHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.addressing.WsaConstants; +import org.apache.muse.ws.addressing.soap.SoapConstants; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.addressing.soap.SoapUtils; +import org.apache.muse.ws.resource.WsResource; +import org.apache.muse.ws.resource.metadata.MetadataDescriptor; +import org.apache.muse.ws.resource.metadata.WsrmdConstants; +import org.apache.muse.ws.resource.metadata.impl.SimpleMetadataDescriptor; +import org.apache.muse.ws.resource.metadata.impl.WsrmdUtils; +import org.apache.muse.ws.resource.properties.ResourcePropertyCollection; +import org.apache.muse.ws.resource.properties.impl.SimpleResourcePropertyCollection; +import org.apache.muse.ws.resource.properties.impl.WsrpUtils; +import org.apache.muse.ws.resource.properties.schema.ResourcePropertiesSchema; +import org.apache.muse.ws.resource.properties.schema.impl.SimpleResourcePropertiesSchema; +import org.apache.muse.ws.wsdl.WsdlUtils; +import org.apache.qpid.management.Messages; +import org.apache.qpid.management.wsdm.common.ThreadSessionManager; +import org.apache.qpid.transport.util.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * QMan WS resource. + * We could say that this is a QMan manageable entity under the + * WS-DM perspective. + * + * @author Andrea Gazzarini + */ +@SuppressWarnings("unchecked") +public class QManWsResource implements WsResource +{ + private final static Logger LOGGER = Logger.get(QManWsResource.class); + + /** + * Internal state of this resource. + * + * @author Andrea Gazzarini + */ + interface State + { + /** + * Provides initialization of this resource. + * + * @throws SoapFault when the initialization fails. + */ + void initialize() throws SoapFault; + + /** + * Returns true if this resource has been initialized. + * + * @return true if this resource has been initialized. + */ + boolean hasBeenInitialized(); + + /** + * Returns true if this resource has been shutdown. + * + * @return true if this resource has been shutdown. + */ + boolean hasBeenShutdown(); + + /** + * Shuts down this resource. + * + * @throws SoapFault when the shutdown procedure fails. + */ + void shutdown() throws SoapFault; + } + + private final State _hasBeenShutdown = new State() + { + /** + * Return false because this resource has been shutdown so therefore + * initialization occurred. + * + * @return true; + */ + public boolean hasBeenInitialized() + { + return true; + } + + /** + * Returns true because this state indicates that resource has been shutdown. + * + * @return true. + */ + public boolean hasBeenShutdown() + { + return true; + } + + /** + * Since this resource has been shutdown the initialization + * cannot be performed again. + * As conseguence of that this method throws an exception. + * + * @throws SoapFault each time this method is called. + */ + public void initialize() throws SoapFault + { + LOGGER.error(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED); + throw new SoapFault(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED); + } + + public void shutdown() throws SoapFault + { + LOGGER.error(Messages.QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN); + throw new SoapFault(Messages.QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN); + } + }; + + private final State _hasBeenInitialized = new State() + { + /** + * Returns true because this is the state where a resource is when it + * has been initialized. + * + * @return true. + */ + public boolean hasBeenInitialized() + { + return true; + } + + /** + * Returns false because this resource has been initialized but no shutdown request + * has been received. + * + * @return false. + */ + public boolean hasBeenShutdown() + { + return false; + } + + /** + * A resource in this state cannot be initialized again so if this method is called an + * exception is thrown. + * + * @throws SoapFault each time this method is called. + */ + public void initialize() throws SoapFault + { + LOGGER.error(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED); + throw new SoapFault(Messages.QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED); + } + + /** + * Shuts down this resource. + * + * @throws SoapFault when the shutdown procedure fails. + */ + public void shutdown() throws SoapFault + { + shutdownCapabilities(); + + ResourceManager manager = getResourceManager(); + + if (manager.getResource(_enpointReference) != null) + { + manager.removeResource(_enpointReference); + } + + _currentState = _hasBeenShutdown; + } + }; + + /** + * The initial state of this resource. + * As the name suggests, it is not yet initialized. + */ + private final State _notYetInitialized = new State() + { + /** + * Provides initialization of this resource. + * + * @throws SoapFault when the initialization fails. + */ + public void initialize() throws SoapFault + { + _properties = new SimpleResourcePropertyCollection(); + _wsdl = ThreadSessionManager.getInstance().getSession().getWsdlDocument(); + + ResourcePropertiesSchema schema = createPropertiesSchema(_wsdl); + _properties.setSchema(schema); + + MetadataDescriptor metadata = createMetadataDescriptor(_wsdl); + _properties.setMetadata(metadata); + + initializeCapabilities(); + + _properties.applyMetadata(); + + // Resource intialization completed : Let's make a state change. + _currentState = _hasBeenInitialized; + } + + /** + * Shuts down this resource. + * + * @throws SoapFault when the shutdown procedure fails. */ + public void shutdown() throws SoapFault + { + LOGGER.error(Messages.QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED); + throw new SoapFault(Messages.QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED); + } + + /** + * Returns false because this state indicates that + * the resource has not yet been initialized. + * + * @return false; + */ + public boolean hasBeenInitialized() + { + return false; + } + + /** + * Returns false because the resource, when is in this state + * hasn't been initialized and as conseguence of that hasn't + * been shutdonm. + * + * @return false; + */ + public boolean hasBeenShutdown() + { + return false; + } + }; + + private Map _capabilitiesByAction = new HashMap(); + private Map _capabilitiesByURI = new LinkedHashMap(); + + private String _contextPath; + private Environment _environment; + private EndpointReference _enpointReference; + + private State _currentState = _notYetInitialized; + + private ResourceManager _resourceManager; + private ResourcePropertyCollection _properties; + + private Map _initParameters = Collections.EMPTY_MAP; + + // Workaround : muse is using and hardcoded java.util.logging.Logger but we should use + // SLF4j so this is the original implementatation that won't never be used (on QMan classes) + private java.util.logging.Logger _logger; + + private Document _wsdl; + private String _wsdlPath; + private QName _wsdlPortType; + + /** + * Adds the given capability to this resource. + * + * @param capability the capability to be added. + */ + public void addCapability(Capability capability) + { + capability.setResource(this); + capability.setLog(getLog()); + capability.setEnvironment(getEnvironment()); + + String uri = capability.getCapabilityURI(); + _capabilitiesByURI.put(uri, capability); + + LOGGER.debug( + Messages.QMAN_200033_CAPABILITY_CLASS_HAS_BEEN_ADDED, + capability.getClass(), + uri); + } + + /** + * Returns the capability associated with the given URI. + * + * @return the capability associated with the given URI. + */ + public Capability getCapability(String capabilityURI) + { + return _capabilitiesByURI.get(capabilityURI); + } + + /** + * Returns a collection with all registered capability URIs. + * + * @return a collection with all registered capability URIs. + */ + public final Collection getCapabilityURIs() + { + return Collections.unmodifiableSet(_capabilitiesByURI.keySet()); + } + + /** + * Returns the context path of this resource. + * + * @return the context path of this resource. + */ + public final String getContextPath() + { + return _contextPath; + } + + /** + * Returns the endpoint reference of this resource. + * + * @return the endpoint reference of this resource. + */ + public EndpointReference getEndpointReference() + { + return _enpointReference; + } + + /** + * Returns the enviroment associated with this resource. + * + * @return the enviroment associated with this resource. + */ + public final Environment getEnvironment() + { + return _environment; + } + + /** + * Returns the initialization parameter of this resource associated with + * the given name. + * + * @param name the init parameter name. + * @return the initialization parameter associated with the given name. + */ + public final String getInitializationParameter(String name) + { + return (String)getInitializationParameters().get(name); + } + + /** + * Returns the map containing all init parameters of this resource. + * + * @return the map containing all init parameters of this resource. + */ + public final Map getInitializationParameters() + { + return _initParameters; + } + + /** + * N.A. This resource uses QMan logging instead of plain java.util.logger + * implementation. + */ + public final java.util.logging.Logger getLog() + { + return _logger; + } + + /** + * Returns the resource manager associated with this resource. + * + * @return the resource manager associated with this resource. + */ + public ResourceManager getResourceManager() + { + return _resourceManager; + } + + /** + * Returns the wsdl (relative) path of this resource. + * + * @return the wsdl (relative) path of this resource. + */ + public String getWsdlPath() + { + return _wsdlPath; + } + + /** + * Returns the port type of this resource. + * + * @return the port type of this resource. + */ + public final QName getWsdlPortType() + { + return _wsdlPortType; + } + + /** + * Returns true if this resource has been initialized, false otherwise. + * + * @return true if this resource has been initialized, false otherwise. + */ + public final boolean hasBeenInitialized() + { + return _currentState.hasBeenInitialized(); + } + + /** + * Returns true if this resource has been shutdown, false otherwise. + * + * @return true if this resource has been shutdown, false otherwise. + */ + public final boolean hasBeenShutdown() + { + return _currentState.hasBeenShutdown(); + } + + /** + * Checks if a capability with the given URI is available for this resource. + * + * @return true if a capability with the given URI is available for this resource, false otherwise. + */ + public final boolean hasCapability(String capabilityURI) + { + return getCapability(capabilityURI) != null; + } + + /** + * Returns the collection containing all properties of this resource. + * + * @return the collection containing all properties of this resource. + */ + public final ResourcePropertyCollection getPropertyCollection() + { + return _properties; + } + + /** + * Return the WSDL document of this resource. + * + * @return the WSDL document of this resource. + */ + public Document getWsdl() + { + return _wsdl; + } + + /** + * Initializes this resources. + * Note that the what needs to be done depends on the current state of this + * resource. + * + * @throws SoapFault when the initialization fails. + */ + public void initialize() throws SoapFault + { + _currentState.initialize(); + } + + /** + * Invokes the action specified in the given soap request on this resource. + * + * @param requestBody the SOAP body. + * @return the result of the invocation as org.w3c.dom.Element + */ + public Element invoke(Element requestBody) + { + String action = _environment.getAddressingContext().getAction(); + Capability capability = getCapabilityForAction(action); + + // Sanity check : is there a capability for the given action? + if (capability == null) + { + SoapFault wsaFault = new SoapFault( + String.format( + Messages.ACTION_NOT_SUPPORTED, + action,getContextPath())); + + wsaFault.setCode(SoapConstants.SENDER_QNAME); + wsaFault.setSubCode(WsaConstants.ACTION_NOT_SUPPORTED_FAULT_QNAME); + + Element detail = XmlUtils.createElement(WsaConstants.PROBLEM_ACTION_QNAME); + XmlUtils.setElement(detail, WsaConstants.ACTION_QNAME, action); + wsaFault.setDetail(detail); + + LOGGER.error( + Messages.QMAN_100020_ACTION_NOT_SUPPORTED, + action, + getContextPath()); + + return wsaFault.toXML(); + } + + MessageHandler handler = capability.getMessageHandler(action); + Method method = handler.getMethod(); + + try + { + Object[]parameters = handler.fromXML(requestBody); + Object result = method.invoke(capability, parameters); + return handler.toXML(result); + } + catch (Throwable throwable) + { + LOGGER.error( + throwable, + Messages.QMAN_100037_INVOKE_OPERATION_FAILURE); + + SoapFault response = SoapUtils.convertToFault( + (throwable.getCause()!= null) + ? throwable.getCause() + : throwable); + return response.toXML(); + } + } + + /** + * Sets the context path of this resource. + * + * @param contextPath the context path of this resource. + */ + public final void setContextPath(String contextPath) + { + _contextPath = contextPath; + } + + /** + * Sets the endpoint reference of this resource. + * + * @param endpointReference the endpoint reference of this resource. + */ + public final void setEndpointReference(EndpointReference endpointReference) + { + if (_enpointReference != null && hasBeenInitialized()) + throw new RuntimeException(("ExistingResourceEPR")); + + _enpointReference = endpointReference; + } + + /** + * Sets the context environment of this resource. + * + * @param environment the context environment of this resource. + */ + public final void setEnvironment(Environment environment) + { + _environment = environment; + } + + /** + * Sets the initialization parameters of this resource. + * + * @param parameters the init parameters of this resource. + */ + public final void setInitializationParameters(Map parameters) + { + _initParameters = (parameters != null) + ? parameters + : Collections.EMPTY_MAP; + } + + /** + * N.A. for this resource. QMan logging mechanism is used for that. + */ + public final void setLog(java.util.logging.Logger log) + { + _logger = log; + } + + /** + * Sets the resource manager owner of this resource. + * + * @param manager the resource manager of this resource. + */ + public void setResourceManager(ResourceManager manager) + { + _resourceManager = manager; + } + + /** + * Sets the WSDL (relative) path of this resource. + * + * @param wsdlPath the WSDL (relative) path of this resource. + */ + public final void setWsdlPath(String wsdlPath) + { + this._wsdlPath = wsdlPath; + } + + /** + * Sets the port type of this resource. + * + * @param wsdlPortType the port type of this resource. + */ + public final void setWsdlPortType(QName wsdlPortType) + { + _wsdlPortType = wsdlPortType; + } + + /** + * Shutdown procedure for this resource. + * + * @throws SoapFault when the shutdown procedure fails. + */ + public synchronized void shutdown() throws SoapFault + { + _currentState.shutdown(); + } + + /** + * Returns a string representation of this resource. + * Basically the resource endpoint reference (as a string) is returned. + * + * @return the resource endpoint reference (as a string) is returned. + */ + public String toString() + { + return getEndpointReference().toString(); + } + + /** + * Initializes capabilities of this resource. + * + * @throws SoapFault when at least one capability fails to initialize. + */ + private void initializeCapabilities() throws SoapFault + { + for (Entry entry : _capabilitiesByURI.entrySet()) + { + Capability capability = entry.getValue(); + capability.initialize(); + + for (Object action : capability.getActions()) + { + _capabilitiesByAction.put((String)action, capability); + } + + capability.initializeCompleted(); + } + } + + /** + * Shutdown procedure for all registered capabilities of this resource. + * + * @throws SoapFault when at least one capability shutdown fails. + */ + private void shutdownCapabilities() throws SoapFault + { + for (Entry entry : _capabilitiesByURI.entrySet()) + { + Capability capabilty = entry.getValue(); + capabilty.prepareShutdown(); + capabilty.shutdown(); + } + } + + /** + * Creates a metadata descriptor for this resource. + * + * @param wsdl the WSDL document. + * @return a metadata descriptor for this resource. + * @throws SoapFault when it's not possible build the descriptor. + */ + private MetadataDescriptor createMetadataDescriptor(Document wsdl) throws SoapFault + { + try + { + Element portTypeXML = WsdlUtils.getPortType(wsdl, getWsdlPortType()); + + String rmdName = XmlUtils.getAttribute( + portTypeXML, + WsrmdConstants.DESCRIPTOR_ATTR_QNAME); + + String rmdPath = XmlUtils.getAttribute( + portTypeXML, + WsrmdConstants.DESCRIPTOR_LOCATION_ATTR_QNAME); + + LOGGER.debug(Messages.QMAN_200034_RMD_NAME, rmdName); + LOGGER.debug(Messages.QMAN_200035_RMD_PATH, rmdPath); + + Environment env = getEnvironment(); + String path = env.createRelativePath(getWsdlPath(), rmdPath); + Document rmdDoc = env.getDocument(path); + + Element[] additionalProperties = + ThreadSessionManager + .getInstance() + .getSession() + .getResourceMetadataDescriptor(); + + Element metadataDescriptor = WsrmdUtils.getMetadataDescriptor(rmdDoc, rmdName); + + for (Element element : additionalProperties) + { + +// rmdDoc.importNode(element, true); + Element adopted = (Element) rmdDoc.importNode(element,false); + metadataDescriptor.appendChild(adopted); + } + + return new SimpleMetadataDescriptor(metadataDescriptor); + } + catch(Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100021_RMD_BUID_FAILURE, + getContextPath()); + throw new SoapFault(exception); + } + } + + /** + * Returns the capability associated with the given action. + * + * @param action the wsa:action of the requested capability. + * @return the capability associated with the given action. + */ + private Capability getCapabilityForAction(String action) + { + return (Capability)_capabilitiesByAction.get(action); + } + + /** + * Creates a WSRP document representing schema properties for this resource. + * + * @param wsdl the DOM document holding the resource's WSDL. + * @return the WSRP document schema. + */ + private ResourcePropertiesSchema createPropertiesSchema(Document wsdl) + { + QName wsrpName = WsrpUtils.getPropertiesName(wsdl, getWsdlPortType()); + Element wsrpDoc = WsdlUtils.getElementDeclaration(wsdl, wsrpName); + return new SimpleResourcePropertiesSchema(wsrpName, wsrpDoc); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java new file mode 100644 index 0000000000..a064542658 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java @@ -0,0 +1,83 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.xerces.impl.dv.util.Base64; +import org.w3c.dom.Element; + +/** + * Implementation of Muse Serializer for byte array type. + * + * @author Andrea Gazzarini + */ +public class ByteArraySerializer implements Serializer { + + /** + * Return a byte array representation of the given xml element. + * + * @param xml the element to unmarshal. + * @throws SoapFault when the unmarshalling fails. + */ + public Object fromXML(Element xml) throws SoapFault + { + try + { + return Base64.decode(xml.getTextContent()); + } catch (Exception exception) + { + throw new SoapFault(exception); + } + } + + /** + * Returns the java type associated to this class. + * + * @return the java type associated to this class. + */ + public Class getSerializableType() + { + return byte[].class; + } + + /** + * Return an xml representation of the given byte array with the given name. + * + * @param object the byte array to marshal. + * @param qname the qualified (xml) name of the object to use in xml representation. + * @return the xml representation of the byte array. + * @throws SoapFault when the marshalling fails. + */ + public Element toXML(Object object, QName qname) throws SoapFault + { + Element element = XmlUtils.createElement( + qname, + Base64.encode((byte[]) object)); + element.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); + element.setAttribute("xsi:type","xsd:base64Binary"); + return element; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java new file mode 100644 index 0000000000..60350ccc31 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/DateSerializer.java @@ -0,0 +1,75 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import java.util.Date; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.w3c.dom.Element; + +/** + * Implementation of Muse Serializer for Date type. + * Note that Muse already ships a serializer but the formatter used on that class + * is losing precision betweem marshal / unmarshal operations. + * + * @author Andrea Gazzarini + */ +public class DateSerializer implements Serializer +{ + /** + * Return a Date representation of the given xml element. + * + * @param xml the element to unmarshal. + * @throws SoapFault when the unmarshalling fails. + */ + public Object fromXML(Element elementData) throws SoapFault + { + return new Date(Long.parseLong(elementData.getTextContent())); + } + + /** + * Returns the java type associated to this class. + * + * @return the java type associated to this class. + */ + public Class getSerializableType() + { + return Date.class; + } + + /** + * Return an xml representation of the given UUID with the given name. + * + * @param object the UUID to marshal. + * @param qname the qualified (xml) name of the object to use in xml representation. + * @return the xml representation of the UUID. + * @throws SoapFault when the marshalling fails. + */ + public Element toXML(Object obj, QName qname) throws SoapFault + { + Date date = (Date) obj; + return XmlUtils.createElement(qname, String.valueOf(date.getTime())); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java new file mode 100644 index 0000000000..b819d52ad1 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java @@ -0,0 +1,85 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.wsdm.capabilities.Result; +import org.w3c.dom.Element; + +/** + * Implementation of Muse Serializer for Result type. + * + * @author Andrea Gazzarini + */ +public class InvocationResultSerializer implements Serializer +{ + private Serializer _mapSerializer = SerializerRegistry.getInstance().getSerializer(Map.class); + + /** + * Return a UUID representation of the given xml element. + * + * @param xml the element to unmarshal. + * @throws SoapFault when the unmarshalling fails. + */ + @SuppressWarnings("unchecked") + public Object fromXML(Element elementData) throws SoapFault + { + Element outputParameters = XmlUtils.getFirstElement(elementData); + return new Result((Map) _mapSerializer.fromXML(outputParameters)); + } + + /** + * Returns the java type associated to this class. + * + * @return the java type associated to this class. + */ + public Class getSerializableType() + { + return Result.class; + } + + /** + * Return an xml representation of the given UUID with the given name. + * + * @param object the UUID to marshal. + * @param qname the qualified (xml) name of the object to use in xml representation. + * @return the xml representation of the UUID. + * @throws SoapFault when the marshalling fails. + */ + public Element toXML(Object obj, QName qname) throws SoapFault + { + Result result = (Result) obj; + Element root = XmlUtils.createElement(qname); + if (result.getOutputParameters() != null) + { + Element outputSection = SerializerRegistry.getInstance().getSerializer(Map.class).toXML(result.getOutputParameters(), new QName("outputParameters")); + root.appendChild(outputSection); + } + return root; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java new file mode 100644 index 0000000000..07e1dfdc56 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java @@ -0,0 +1,134 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +/** + * Implementation of Muse Serializer for Map type. + * + * + * + * + * + * + * + * + * @author Andrea Gazzarini + */ +public class MapSerializer implements Serializer +{ + + ByteArraySerializer _byteArraySerializer = new ByteArraySerializer(); + Serializer _objectSerializer = SerializerRegistry.getInstance().getSerializer(Object.class); + Serializer _stringSerializer = SerializerRegistry.getInstance().getSerializer(String.class); + + /** + * Return a map representation of the given xml element. + * + * @param xml the element to unmarshal. + * @throws SoapFault when the unmarshalling fails. + */ + public Object fromXML(Element xml) throws SoapFault + { + Map result = new HashMap(); + + if (xml != null) + { + Element[] children = XmlUtils.getAllElements(xml); + Serializer objectDeserializer = SerializerRegistry.getInstance().getSerializer(Object.class); + + for (Element entry : children) + { + Element[] keysAndValues = XmlUtils.getAllElements(entry); + Object key = null; + Object value = null; + for (Element element : keysAndValues) + { + if (Names.KEY.equals(element.getLocalName())) + { + key = _stringSerializer.fromXML(element); + } else if (Names.VALUE.equals(element.getLocalName())) + { + value = objectDeserializer.fromXML(element); + } + } + result.put(key, value); + } + } + return result; + } + + /** + * Returns the java type associated to this class. + * + * @return the java type associated to this class. + */ + public Class getSerializableType() + { + return Map.class; + } + + /** + * Return an xml representation of the given Map with the given name. + * + * @param object the Map to marshal. + * @param qname the qualified (xml) name of the object to use in xml representation. + * @return the xml representation of the given Map. + * @throws SoapFault when the marshalling fails. + */ + public Element toXML(Object obj, QName qname) throws SoapFault + { + + Map data = (Map) obj; + + QName entryQName = new QName(qname.getNamespaceURI(),Names.ENTRY,qname.getPrefix()); + QName keyQName = new QName(qname.getNamespaceURI(),Names.KEY,qname.getPrefix()); + QName valueQName = new QName(qname.getNamespaceURI(),Names.VALUE,qname.getPrefix()); + + Element root = XmlUtils.createElement(qname); + root.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); + for (Entry mapEntry: data.entrySet()) + { + Element entry = XmlUtils.createElement(entryQName); + entry.appendChild(_stringSerializer.toXML(mapEntry.getKey(), keyQName)); + if (mapEntry.getValue().getClass() == byte[].class) { + entry.appendChild(_byteArraySerializer.toXML(mapEntry.getValue(), valueQName)); + } else { + entry.appendChild(_objectSerializer.toXML(mapEntry.getValue(), valueQName)); + } + root.appendChild(entry); + } + return root; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java new file mode 100644 index 0000000000..ff0c69cdda --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ObjectSerializer.java @@ -0,0 +1,202 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import java.net.URI; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.Names; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; + +/** + * Generic Serializer for objects. + * It is a general-purpose serializer used for encoding Object values. + */ +public class ObjectSerializer implements Serializer +{ + /** + * Mapping between xsd and java types. + */ + private Map> xml2Java = new HashMap>(); + { + xml2Java.put("xsd:long", Long.class); + xml2Java.put("xsd:boolean",Boolean.class); + xml2Java.put("xsd:double",Double.class); + xml2Java.put("xsd:float",Float.class); + xml2Java.put("xsd:integer",Integer.class); + xml2Java.put("xsd:int",Integer.class); + xml2Java.put("xsd:short",Short.class); + xml2Java.put("xsd:string",String.class); + xml2Java.put("xsd:anyURI",URI.class); + xml2Java.put("xsd:dateTime",Date.class); + xml2Java.put("xsd:QName",QName.class); + xml2Java.put("xsd:element",Element.class); + xml2Java.put("xsd:base64Binary",byte[].class); + xml2Java.put("qman:arrayOfLong",Long[].class); + xml2Java.put("qman:arrayOfBoolean",Boolean[].class); + xml2Java.put("qman:arrayOfDouble",Double[].class); + xml2Java.put("qman:arrayOfFloat",Float[].class); + xml2Java.put("qman:arrayOfInteger",Integer[].class); + xml2Java.put("qman:arrayOfShort",Short[].class); + xml2Java.put("qman:arrayOfString",String[].class); + xml2Java.put("qman:arrayOfURI",URI[].class); + xml2Java.put("qman:arrayOfDate",Date[].class); + xml2Java.put("qman:uuid",UUID.class); + xml2Java.put("qman:map",Map.class); + xml2Java.put("qman:map",HashMap.class); + } + + private Map, String> java2Xml = new HashMap, String>(); + { + java2Xml.put(UUID.class,"qman:uuid"); + java2Xml.put(Long.class,"xsd:long"); + java2Xml.put(long.class,"xsd:long"); + java2Xml.put(Boolean.class,"xsd:boolean"); + java2Xml.put(boolean.class,"xsd:boolean"); + java2Xml.put(Double.class,"xsd:double"); + java2Xml.put(double.class,"xsd:double"); + java2Xml.put(Float.class,"xsd:float"); + java2Xml.put(float.class,"xsd:float"); + java2Xml.put(Integer.class,"xsd:integer"); + java2Xml.put(int.class,"xsd:integer"); + java2Xml.put(Short.class,"xsd:short"); + java2Xml.put(short.class,"xsd:short"); + java2Xml.put(String.class,"xsd:string"); + java2Xml.put(URI.class,"xsd:anyURI"); + java2Xml.put(Date.class,"xsd:dateTime"); + java2Xml.put(QName.class,"xsd:QName"); + java2Xml.put(Element.class,"xsd:element"); + java2Xml.put(byte[].class,"xsd:base64Binary"); + java2Xml.put(Long[].class,"qman:arrayOfLong"); + java2Xml.put(long[].class,"qman:arrayOfLong"); + java2Xml.put(Boolean[].class,"qman:arrayOfBoolean"); + java2Xml.put(boolean[].class,"qman:arrayOfBoolean"); + java2Xml.put(Double[].class,"qman:arrayOfDouble"); + java2Xml.put(double[].class,"qman:arrayOfDouble"); + java2Xml.put(Float[].class,"qman:arrayOfFloat"); + java2Xml.put(float[].class,"qman:arrayOfFloat"); + java2Xml.put(Integer[].class,"qman:arrayOfInteger"); + java2Xml.put(int[].class,"qman:arrayOfInteger"); + java2Xml.put(Short[].class,"qman:arrayOfShort"); + java2Xml.put(short[].class,"qman:arrayOfShort"); + java2Xml.put(String[].class,"qman:arrayOfString"); + java2Xml.put(URI[].class,"qman:arrayOfURI"); + java2Xml.put(Date[].class,"qman:arrayOfDate"); + java2Xml.put(Map.class,"qman:map"); + java2Xml.put(HashMap.class,"qman:map"); + } + + /** + * Converts the incoming element into the appropriate Java type. + * The method will fail if : + * + *
1) The element has no xsi:type attribute; + *
2) The xsi:type attribute has no corresponding java type on this serializer mappings. + * + * @param elementData the xml element containing data to be unmarshalled.l + * @return the java object as result of xml element unmarshalling. + * @throws SoapFault when the marshalling fails. + */ + public Object fromXML(Element elementData) throws SoapFault + { + Attr typeAttribute = elementData.getAttributeNodeNS( + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, + Names.TYPE); + + if (typeAttribute == null) + { + throw new SoapFault( + "No type attribute was found for the current element. " + + "If you are using this serializer, in order to unmarshal the" + + " opportune type the xsi:type must be specified."); + } + + Class clazz = xml2Java.get(typeAttribute.getValue()); + + if (clazz == null) + { + throw new SoapFault( + String.format( + "No corresponding class was found on this serializer mappings for xsi:type %s.", + typeAttribute)); + } + + if (clazz == byte[].class) { + return new ByteArraySerializer().fromXML(elementData); + } + + return SerializerRegistry.getInstance().getSerializer(clazz).fromXML(elementData); + } + + /** + * As this serializer is supposed to deal with generic object types, this method returns Object.class. + * + * @return Object.class + */ + public Class getSerializableType() + { + return Object.class; + } + + /** + * Converts the given object (with the given qname) in XML format. + * This method fails if there's no corresponding xml type for the given runtime type of the input object. + * + * @param obj the object to be marshalled. + * @param qname the qualified name that will be used in encoding. + */ + public Element toXML(Object obj, QName qname) throws SoapFault + { + Class clazz = obj.getClass(); + + Element result = null; + + if (clazz == byte[].class) { + result = new ByteArraySerializer().toXML(obj,qname); + } + else { + result = SerializerRegistry.getInstance().getSerializer(clazz).toXML(obj,qname); + } + result.setAttribute(Names.XSI_TYPE, java2Xml.get(clazz)); + return result; + } + + /** + * Returns the xml type associated with the given class. + * + * @param clazz the class. + * @return the xml type associated with the given class. + */ + public String getXmlType(Class clazz) + { + return java2Xml.get(clazz); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java new file mode 100644 index 0000000000..408a8de6cf --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/UUIDSerializer.java @@ -0,0 +1,72 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import java.util.UUID; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.w3c.dom.Element; + +/** + * Implementation of Muse Serializer for UUID type. + * + * @author Andrea Gazzarini + */ +public class UUIDSerializer implements Serializer +{ + /** + * Return a UUID representation of the given xml element. + * + * @param xml the element to unmarshal. + * @throws SoapFault when the unmarshalling fails. + */ + public Object fromXML(Element elementData) throws SoapFault + { + return UUID.fromString(elementData.getTextContent()); + } + + /** + * Returns the java type associated to this class. + * + * @return the java type associated to this class. + */ + public Class getSerializableType() + { + return UUID.class; + } + + /** + * Return an xml representation of the given UUID with the given name. + * + * @param object the UUID to marshal. + * @param qname the qualified (xml) name of the object to use in xml representation. + * @return the xml representation of the UUID. + * @throws SoapFault when the marshalling fails. + */ + public Element toXML(Object obj, QName qname) throws SoapFault + { + return XmlUtils.createElement(qname, String.valueOf(obj)); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java new file mode 100644 index 0000000000..9284a62461 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEvent.java @@ -0,0 +1,149 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.notifications; + +import org.apache.muse.util.xml.XmlSerializable; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.qpid.management.Names; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Object representation of a QMan entity lifecycle event notification. + * Note that with entity we mean both object(s) and event(s). + * + * At the moment there are only two types of lifecycle events : CREATE and REMOVE. + * The first one if fired when a new instance (event or object) is created, while the second + * one is fired when an object instance (events are transient objects so they are not destroyed) + * is removed. + * + * Developer Note : The marshal & unmarshal ops could be handled using JAXB but + * we are not sure about the running environment (JAXB libs were included only + * starting from 1.6) + * + * This is the event XML representation : + * + * + + 16038bd5-b62b-4e86-9833-7560ed57b474 + org.qpid.apache.broker + session + + + + * @author Andrea Gazzarini + */ +public class LifeCycleEvent implements XmlSerializable +{ + private final String _resourceId; + private final String _packageName; + private final String _name; + + private final LifeCycleEventType _type; + + /** + * Builds a new event with the given data. + * + * @param resourceId resource identifier. + * @param packageName resource package name. + * @param name resource name. + * @param type event type. + */ + private LifeCycleEvent(String resourceId, String packageName, String name, LifeCycleEventType type) + { + this._resourceId = resourceId; + this._packageName = packageName; + this._name = name; + this._type = type; + } + + /** + * Factory method for a new "CREATE" event. + * Builds a new "CREATE" event with the given data. + * + * @param resourceId resource identifier. + * @param packageName resource package name. + * @param name resource name. + */ + public static LifeCycleEvent newCreateEvent(String resourceId, String packageName, String name) + { + return new LifeCycleEvent(resourceId, packageName, name, LifeCycleEventType.CREATED); + } + + /** + * Factory method for a new "REMOVE" event. + * Builds a new "REMOVE" event with the given data. + * + * @param resourceId resource identifier. + * @param packageName resource package name. + * @param name resource name. + */ + public static LifeCycleEvent newRemoveEvent(String resourceId, String packageName, String name) + { + return new LifeCycleEvent(resourceId, packageName, name, LifeCycleEventType.REMOVED); + } + + /** + * Returns an XML representation of this event. + * + * @return an XML representation of this event. + */ + public Element toXML() + { + return toXML(XmlUtils.EMPTY_DOC); + } + + /** + * Returns an XML representation of this event using the given + * input document as owner. + * + * @return an XML representation of this event. + */ + public Element toXML(Document factory) + { + Element lifeCycleEvent = XmlUtils.createElement(factory, Names.LIFECYCLE_EVENT_QNAME); + + lifeCycleEvent.setAttribute( + "Type", + _type.toString()); + + lifeCycleEvent.setAttribute( + Names.TIMEMILLIS_ATTRIBUTE_NAME, + String.valueOf(System.currentTimeMillis())); + + Element resource = XmlUtils.createElement(factory, Names.RESOURCE_QNAME); + lifeCycleEvent.appendChild(resource); + + Element id = XmlUtils.createElement(factory, Names.RES_ID_QNAME); + id.setTextContent(_resourceId); + resource.appendChild(id); + + Element packageName = XmlUtils.createElement(factory, Names.PACKAGE_NAME_QNAME); + packageName.setTextContent(_packageName); + resource.appendChild(packageName); + + Element name = XmlUtils.createElement(factory, Names.ENTITY_NAME_QNAME); + name.setTextContent(_name); + resource.appendChild(name); + + return lifeCycleEvent; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java new file mode 100644 index 0000000000..9ce7bfc743 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/notifications/LifeCycleEventType.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.notifications; + +/** + * Event type enumeration. + * Event type are used as part of event WS-Notifications in order to inform + * the interested listeners about the lifecycle of a QMan managed entity (object or event instance). + * + * @author Andrea Gazzarini + */ +public enum LifeCycleEventType +{ + CREATED, + REMOVED; +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java b/java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java new file mode 100644 index 0000000000..398a69817b --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/qman/debug/WsdlDebugger.java @@ -0,0 +1,49 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.qman.debug; + +import javax.management.ObjectName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.qpid.transport.util.Logger; +import org.w3c.dom.Node; + +/** + * Utility class used for debbugging WSDL documents + * + * @author Andrea Gazzarini + */ +public class WsdlDebugger { + public final static Logger LOGGER = Logger.get(WsdlDebugger.class); + + /** + * Prints out to log the given node. + * + * @param node the xml node to be printed out. + */ + public static void debug(ObjectName resourceId, Node node) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(resourceId+" : "+XmlUtils.toString(node, false,true)); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java b/java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java new file mode 100644 index 0000000000..600bb51858 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/qman/debug/XmlDebugger.java @@ -0,0 +1,92 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.qman.debug; + +import javax.management.ObjectName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.qpid.transport.util.Logger; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * Utility class used for debbugging XML messages + * + * @author Andrea Gazzarini + */ +public class XmlDebugger { + public final static Logger LOGGER = Logger.get(XmlDebugger.class); + + /** + * Prints out to log the given node. + * + * @param node the xml node to be printed out. + */ + public static void debug(Node node) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(XmlUtils.toString(node, false,true)); + } + } + + /** + * Prints out to log the given node. + * + * @param node the xml node to be printed out. + */ + public static void debug(ObjectName resourceId, Node node) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(resourceId+" : "+XmlUtils.toString(node, false,true)); + } + } + + + /** + * Prints out to log the given element array. + * + * @param elements the element array to be printed out. + */ + public static void debug(Element [] elements) + { + if (LOGGER.isDebugEnabled()) + { + StringBuilder builder = new StringBuilder(); + for (Element element : elements) { + builder.append(XmlUtils.toString(element,false,true)); + builder.append(System.getProperty("line.separator")); + } + LOGGER.debug(builder.toString()); + } + } + + /** + * Prints out to log the given node. + * + * @param node the xml node to be printed out. + */ + public static void debug(String node) + { + LOGGER.debug(node); + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml b/java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml new file mode 100644 index 0000000000..062791fa3f --- /dev/null +++ b/java/management/client/src/main/java/router-entries/adapter/resource-instance-1.xml @@ -0,0 +1,23 @@ + + + + diff --git a/java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml b/java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml new file mode 100644 index 0000000000..062791fa3f --- /dev/null +++ b/java/management/client/src/main/java/router-entries/consumer/resource-instance-1.xml @@ -0,0 +1,23 @@ + + + + diff --git a/java/management/client/src/main/java/wsdl/QManAdapter.rmd b/java/management/client/src/main/java/wsdl/QManAdapter.rmd new file mode 100644 index 0000000000..31e921a06b --- /dev/null +++ b/java/management/client/src/main/java/wsdl/QManAdapter.rmd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/QManAdapter.wsdl b/java/management/client/src/main/java/wsdl/QManAdapter.wsdl new file mode 100644 index 0000000000..4b26862604 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/QManAdapter.wsdl @@ -0,0 +1,694 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Connects QMan with a new broker. + + + + + + + Returns an array containing values for the requested properties. + Note that using this method it's possibile to retrieve only the value of the QManService properties. + That is : this method is not supposed to be used for retrieve attributes of the QMan managed entities. For that, the GetManagedEntityAttributeValue must be used. + + + + + + + + + Returns resource's entire WS-RP document, with the most up-to-date values of all properties. Note that using this method it's possibile to retrieve only the value of the QManService properties. + That is : this method is not supposed to be used for retrieve attributes of the QMan managed entities. For that, the GetManagedEntityAttributeValue must be used. + + + + + + + + Returns the value of the given property. Note that using this method it's possibile to retrieve only the value of the QManService properties. + That is : this method is not supposed to be used for retrieve attributes of the QMan managed entities. For that, the GetManagedEntityAttributeValue must be used. + + + + + + + + + + Implementation of the WS-MetadataExchange GetMetadata port type. Note that the only supported metadata type (dialect) is WSDL. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/QManWsResource.rmd b/java/management/client/src/main/java/wsdl/QManWsResource.rmd new file mode 100644 index 0000000000..c4944440e0 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/QManWsResource.rmd @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/QManWsResource.wsdl b/java/management/client/src/main/java/wsdl/QManWsResource.wsdl new file mode 100644 index 0000000000..16169c9b78 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/QManWsResource.wsdl @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd b/java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd new file mode 100644 index 0000000000..ab38b1b7f2 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/SOAP-Envelope-1_2.xsd @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Elements replacing the wildcard MUST be namespace qualified, but can be in the targetNamespace + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fault reporting structure + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd b/java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd new file mode 100644 index 0000000000..04b4a688b3 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-Addressing-2005_08.xsd @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd new file mode 100644 index 0000000000..665797e486 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-BaseFaults-1_2.xsd @@ -0,0 +1,84 @@ + + + + + + + + + + Get access to the xml: attribute groups for xml:lang as declared on 'schema' + and 'documentation' below + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl new file mode 100644 index 0000000000..d53bf60f3a --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.wsdl @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd new file mode 100644 index 0000000000..9e10282759 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-BaseNotification-1_3.xsd @@ -0,0 +1,577 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd b/java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd new file mode 100644 index 0000000000..4cef35b510 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-MetadataExchange-2004_09.xsd @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl new file mode 100644 index 0000000000..ed1c309211 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.wsdl @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd new file mode 100644 index 0000000000..5d50284a33 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-Resource-1_2.xsd @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl new file mode 100644 index 0000000000..adea5800fc --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.wsdl @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd new file mode 100644 index 0000000000..3338faf191 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ResourceLifetime-1_2.xsd @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd b/java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd new file mode 100644 index 0000000000..2c5952264b --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ResourceMetadataDescriptor-CD-01.xsd @@ -0,0 +1,325 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To form a QName, the name of any MetadataDescriptor must be + unique within a Definitions element. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl new file mode 100644 index 0000000000..5d9d7562f4 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.wsdl @@ -0,0 +1,395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd new file mode 100644 index 0000000000..c408b36db1 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ResourceProperties-1_2.xsd @@ -0,0 +1,394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl new file mode 100644 index 0000000000..a75cd59728 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.wsdl @@ -0,0 +1,269 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd new file mode 100644 index 0000000000..87238f90e5 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ServiceGroup-1_2.xsd @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl b/java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl new file mode 100644 index 0000000000..379382c18d --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-ServiceGroupEntry-1_2.wsdl @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd b/java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd new file mode 100644 index 0000000000..df98513131 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WS-Topics-1_3.xsd @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TopicPathExpression ::= TopicPath ( '|' TopicPath )* + TopicPath ::= RootTopic ChildTopicExpression* + RootTopic ::= NamespacePrefix? ('//')? (NCName | '*') + NamespacePrefix ::= NCName ':' + ChildTopicExpression ::= '/' '/'? (QName | NCName | '*'| '.') + + + + + + + + + + + + + The pattern allows strings matching the following EBNF: + ConcreteTopicPath ::= RootTopic ChildTopic* + RootTopic ::= QName + ChildTopic ::= '/' (QName | NCName) + + + + + + + + + + + + + The pattern allows strings matching the following EBNF: + RootTopic ::= QName + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd new file mode 100644 index 0000000000..c24e97a9ce --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part1-1_1.xsd @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd new file mode 100644 index 0000000000..5ea0954734 --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WSDM-MUWS-Part2-1_1.xsd @@ -0,0 +1,677 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/WsResource.rmd b/java/management/client/src/main/java/wsdl/WsResource.rmd new file mode 100644 index 0000000000..b15f7eca1c --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WsResource.rmd @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl b/java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl new file mode 100644 index 0000000000..83a7e5ad8c --- /dev/null +++ b/java/management/client/src/main/java/wsdl/WsResourceFactory.wsdl @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + diff --git a/java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd b/java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd new file mode 100644 index 0000000000..f51b67f78f --- /dev/null +++ b/java/management/client/src/main/java/wsdl/XML-Namespace-1998.xsd @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java b/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java new file mode 100644 index 0000000000..9abcd08eef --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Collects all literal constants used in test cases. + */ +public interface TestConstants +{ + UUID BROKER_ID = UUID.randomUUID(); + Binary OBJECT_ID = new Binary(new byte []{1,2,3,2,1,1,2,3}); + + DomainModel DOMAIN_MODEL = new DomainModel(BROKER_ID); + + String AGE_ATTRIBUTE_NAME = "age"; + String AGE_ATTRIBUTE_DESCRIPTION = "The age of a person."; + String SURNAME_ATTRIBUTE_NAME = "surname"; + String SURNAME_ATTRIBUTE_DESCRIPTION = "The surname of a person."; + Integer _1 = new Integer(1); + + byte [] TEST_RAW_DATA= new byte []{1,4,5,7,8,9,4,44}; + long NOW = System.currentTimeMillis(); + int SEVERITY = _1; + + String QPID_PACKAGE_NAME = "qpid"; + String EXCHANGE_CLASS_NAME = "exchange"; + String BIND_EVENT_NAME = "bind"; + Binary HASH = new Binary(new byte []{1,2,3,4,5,6,7,8,9}); + int VALID_CODE = _1; + + List> EMPTY_PROPERTIES_SCHEMA = new LinkedList>(); + List> EMPTY_STATISTICS_SCHEMA = new LinkedList>(); + List EMPTY_METHODS_SCHEMA = new LinkedList(); + List> EMPTY_ARGUMENTS_SCHEMA = new LinkedList>(); + int _0 = 0; + int SAMPLE_ACCESS_CODE = 1; + String YEARS = "years"; + int SAMPLE_MIN_VALUE = 1; + int SAMPLE_MAX_VALUE = 120; +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java new file mode 100644 index 0000000000..72bd45f70f --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfigurationTest.java @@ -0,0 +1,181 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.Map; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.management.TestConstants; +import org.apache.qpid.management.domain.handler.base.IMessageHandler; +import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler; + +/** + * Test case for Configuration singleton. + */ +public class ConfigurationTest extends TestCase +{ + /** + * Tests the singleton behaviour of the configuration object. + */ + public void testSingleton() + { + assertSame(Configuration.getInstance(),Configuration.getInstance()); + } + + /** + * Tests the execution of getType() method when a unknown code is supplied. + * + *
precondition : the requested type doesn't exist on the configuration. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testGetTypeKO() + { + try + { + Configuration.getInstance().getType(TestConstants.VALID_CODE*10001); + fail("If an unknwon code is supplied an exception must be thrown."); + } catch (UnknownTypeCodeException expected) + { + assertEquals(TestConstants.VALID_CODE*10001,expected.getCode()); + } + } + + /** + * Tests the execution of getAccessMode() method when a unknown code is supplied. + * + *
precondition : the requested access mode doesn't exist on the configuration. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testGetAccessModeKO() + { + try + { + Configuration.getInstance().getAccessMode(TestConstants.VALID_CODE*1528); + fail("If an unknwon code is supplied an exception must be thrown."); + } catch (UnknownAccessCodeException expected) + { + assertEquals(TestConstants.VALID_CODE*1528,expected.getCode()); + } + } + + /** + * Tests the execution of the getBrokerConnectionData when a valid broker id is supplied. + * + *
precondition : on configuration a connection data is stored and associated with the supplied id. + *
postcondition : the requested connection data is returned and no exception is thrown. + */ + public void testGetBrokerConnectionDataOK() throws Exception + { + BrokerConnectionData connectionData = new BrokerConnectionData(); + connectionData.setHost("host"); + connectionData.setPort("7001"); + connectionData.setInitialPoolCapacity("0"); + connectionData.setMaxPoolCapacity("10"); + connectionData.setMaxWaitTimeout("1"); + Configuration.getInstance().addBrokerConnectionData(TestConstants.BROKER_ID, connectionData); + + BrokerConnectionData result = Configuration.getInstance().getBrokerConnectionData(TestConstants.BROKER_ID); + assertSame(connectionData, result); + } + + /** + * Tests the execution of the getBrokerConnectionData when a unknown broker id is supplied. + * + *
precondition : on configuration there's no connection data associated with the supplied id. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testGetBrokerConnectionDataKO_withUnknownBrokerId() + { + UUID brokerId = UUID.randomUUID(); + try + { + Configuration.getInstance().getBrokerConnectionData(brokerId); + fail("If an unknown broker id is supplied then an exception must be thrown."); + } catch(UnknownBrokerException expected) + { + assertEquals(brokerId.toString(),expected.getMessage()); + } + } + + /** + * Tests the execution of the getBrokerConnectionData when a null id is supplied. + * + *
precondition : a null broker is given. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testGetBrokerConnectionDataKO_withNullBrokerId() + { + try + { + Configuration.getInstance().getBrokerConnectionData(null); + fail("If a null broker id is supplied then an exception must be thrown."); + } catch(UnknownBrokerException expected) + { + } + } + + /** + * Tests the behaviour of the getManagementQueueHandlers() method. + * + *
precondition: 2 management handlers are in stored configuration + *
postcondition : 2 management handlers are returned. + */ + public void testGetManagementQueueHandlersOk() + { + IMessageHandler instrMessageHandler = new InstrumentationMessageHandler(); + IMessageHandler configMessageHandler = new ConfigurationMessageHandler(); + + MessageHandlerMapping instrMapping = new MessageHandlerMapping('i',instrMessageHandler); + MessageHandlerMapping configMapping = new MessageHandlerMapping('c',configMessageHandler); + + Configuration.getInstance().addManagementMessageHandlerMapping(instrMapping); + Configuration.getInstance().addManagementMessageHandlerMapping(configMapping); + + Map handlerMappings = Configuration.getInstance().getManagementQueueHandlers(); + + assertEquals(2,handlerMappings.size()); + assertEquals(instrMessageHandler,handlerMappings.get(instrMapping.getOpcode())); + assertEquals(configMessageHandler,handlerMappings.get(configMapping.getOpcode())); + } + + /** + * Tests the behaviour of the getManagementQueueHandlers() method. + * + *
precondition: 2 management handlers are in stored configuration + *
postcondition : 2 management handlers are returned. + */ + public void testGetMethodReplyQueueHandlersOk() + { + IMessageHandler schemaMessageHandler = new SchemaResponseMessageHandler(); + + MessageHandlerMapping schemaMapping = new MessageHandlerMapping('s',schemaMessageHandler); + + Configuration.getInstance().addMethodReplyMessageHandlerMapping(schemaMapping); + + Map handlerMappings = Configuration.getInstance().getMethodReplyQueueHandlers(); + + assertEquals(schemaMessageHandler,handlerMappings.get(schemaMapping.getOpcode())); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java new file mode 100644 index 0000000000..1e464bf6ae --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/configuration/ConfiguratorTest.java @@ -0,0 +1,163 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.Map; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.domain.handler.base.IMessageHandler; +import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.EventContentMessageHandler; +import org.apache.qpid.management.domain.handler.impl.HeartBeatIndicationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler; +import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler; +import org.apache.qpid.management.domain.model.AccessMode; +import org.apache.qpid.management.domain.model.type.AbsTime; +import org.apache.qpid.management.domain.model.type.DeltaTime; +import org.apache.qpid.management.domain.model.type.ObjectReference; +import org.apache.qpid.management.domain.model.type.Str16; +import org.apache.qpid.management.domain.model.type.Str8; +import org.apache.qpid.management.domain.model.type.Uint16; +import org.apache.qpid.management.domain.model.type.Uint32; +import org.apache.qpid.management.domain.model.type.Uint64; +import org.apache.qpid.management.domain.model.type.Uint8; +import org.xml.sax.SAXException; + +/** + * Test case for configurator. + * + * @author Andrea Gazzarini + * + */ +public class ConfiguratorTest extends TestCase +{ + /** + * Tests the execution of the configure() method when no configuration file is given. + * + *
precondition : configuration file option is not set + *
postcondition : no exception is thrown, the configuration is holding no broker data and the predefined mappings are + * stored in configuration. + */ + public void testConfigureOK_WithNoConfigurationFile() throws Exception + { + Configurator configurator = new Configurator(); + configurator.configure(); + Configuration configuration = Configuration.getInstance(); + + assertEquals(new Uint8(), configuration.getType(1)); + assertEquals(new Uint16(), configuration.getType(2)); + assertEquals(new Uint32(), configuration.getType(3)); + assertEquals(new Uint64(), configuration.getType(4)); + assertEquals(new Str8(), configuration.getType(6)); + assertEquals(new Str16(), configuration.getType(7)); + assertEquals(new AbsTime(), configuration.getType(8)); + assertEquals(new DeltaTime(), configuration.getType(9)); + assertEquals(new ObjectReference(), configuration.getType(10)); + assertEquals(new org.apache.qpid.management.domain.model.type.Boolean(), configuration.getType(11)); + assertEquals(new org.apache.qpid.management.domain.model.type.Uuid(), configuration.getType(14)); + assertEquals(new org.apache.qpid.management.domain.model.type.Map(), configuration.getType(15)); + + assertEquals(AccessMode.RC,configuration.getAccessMode(1)); + assertEquals(AccessMode.RW,configuration.getAccessMode(2)); + assertEquals(AccessMode.RO,configuration.getAccessMode(3)); + + Map managementHandlers = configuration.getManagementQueueHandlers(); + assertEquals(4,managementHandlers.size()); + assertEquals( + InstrumentationMessageHandler.class, + managementHandlers.get(Protocol.INSTRUMENTATION_CONTENT_RESPONSE_OPCODE).getClass()); + + assertEquals( + ConfigurationMessageHandler.class, + managementHandlers.get(Protocol.CONFIGURATION_CONTENT_RESPONSE_OPCDE).getClass()); + + assertEquals( + EventContentMessageHandler.class, + managementHandlers.get(Protocol.EVENT_CONTENT_RESPONSE_OPCDE).getClass()); + + assertEquals( + HeartBeatIndicationMessageHandler.class, + managementHandlers.get(Protocol.HEARTBEAT_INDICATION_RESPONSE_OPCODE).getClass()); + + Map methodReplyHandlers = configuration.getMethodReplyQueueHandlers(); + assertEquals(2, methodReplyHandlers.size()); + + assertEquals( + MethodResponseMessageHandler.class, + methodReplyHandlers.get(Protocol.OPERATION_INVOCATION_RESPONSE_OPCODE).getClass()); + + assertEquals( + SchemaResponseMessageHandler.class, + methodReplyHandlers.get(Protocol.SCHEMA_RESPONSE_OPCODE).getClass()); + } + + /** + * Tests the changes of the configurator internal state while configuration file is parsed. + * + *
precondition: N.A. + *
postcondition: N.A. + */ + public void testDirectorParsing() throws SAXException{ + Configurator configurator = new Configurator(); + + assertSame(Configurator.DEFAULT_PARSER,configurator._currentParser); + + configurator.startElement(null, null, Tag.BROKERS.toString(), null); + assertSame(configurator._brokerConfigurationParser,configurator._currentParser); + } + + /** + * It's not possibile to add twice the same broker connection data. + * Is so an exception must be thrown indicating that the given broker is already connected. + * + *
precondition : the given data identifies an already connected broker. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testAddTwoIdenticalBrokers() throws ConfigurationException, BrokerConnectionException + { + Configurator configurator = new Configurator(); + configurator.configure(); + + BrokerConnectionData data = new BrokerConnectionData("sofia.gazzax.com",5672,"virtualHost","user","pwd",1,4,-1); + + Configuration.getInstance()._brokerConnectionInfos.put(UUID.randomUUID(),data); + + try { + configurator.createAndReturnBrokerConnectionData( + UUID.randomUUID(), + data.getHost(), + data.getPort(), + "anotherUser", + "anotherPassword", + data.getVirtualHost(), + 33, + 12, + 1000); + fail("If a broker is added twice an exception must be thrown."); + } catch (BrokerAlreadyConnectedException expected) { + assertEquals(data,expected.getBrokerConnectionData()); + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java b/java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java new file mode 100644 index 0000000000..af261024bd --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/configuration/MappingParsersTest.java @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.configuration; + +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.management.TestConstants; + +/** + * Test case for mapping parsers. + * + * @author Andrea Gazzarini. + */ +public class MappingParsersTest extends TestCase +{ + /** + * Tests the execution of the broker connection data mapping parser. + * + *
precondition: A broker connection datamapping is built by the parser; + *
postcondition: the corresponding connection data is available on the configuration. + */ + public void testBrokerConnectionDataParser() throws UnknownBrokerException + { + String host = "127.0.0.1"; + String port = "7001"; + String virtualHost = "test"; + String username = "username_guest"; + String password ="password_guest"; + + BrokerConnectionDataParser parser = new BrokerConnectionDataParser() + { + @Override + UUID getUUId () + { + return TestConstants.BROKER_ID; + } + }; + + parser.setCurrrentAttributeValue(host); + parser.setCurrentAttributeName(Tag.HOST.toString()); + parser.setCurrrentAttributeValue(port); + parser.setCurrentAttributeName(Tag.PORT.toString()); + parser.setCurrrentAttributeValue(virtualHost); + parser.setCurrentAttributeName(Tag.VIRTUAL_HOST.toString()); + parser.setCurrrentAttributeValue(username); + parser.setCurrentAttributeName(Tag.USER.toString()); + parser.setCurrrentAttributeValue(password); + parser.setCurrentAttributeName(Tag.PASSWORD.toString()); + parser.setCurrentAttributeName(Tag.BROKER.toString()); + + BrokerConnectionData result = Configuration.getInstance().getBrokerConnectionData(TestConstants.BROKER_ID); + + assertEquals(host,result.getHost()); + assertEquals(Integer.parseInt(port),result.getPort()); + assertEquals(virtualHost,result.getVirtualHost()); + assertEquals(username,result.getUsername()); + assertEquals(password,result.getPassword()); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java new file mode 100644 index 0000000000..d6b51b64fc --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandlerTest.java @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.handler.base; + +import junit.framework.TestCase; + +import org.apache.qpid.management.domain.model.type.Binary; + +/** + * Test case for Content indication message handler (base class). + * + * @author Andrea Gazzarini + */ +public class ContentIndicationMessageHandlerTest extends TestCase +{ + /** + * Tests the behaviour of the objectHasBeenRemoved method(). + */ + public void testObjectHasBeenRemoved() + { + ContentIndicationMessageHandler mockHandler = new ContentIndicationMessageHandler() + { + @Override + protected void updateDomainModel (String packageName, String className, Binary classHash, Binary objectId, + long timeStampOfCurrentSample, long timeObjectWasCreated, long timeObjectWasDeleted, byte[] contentData) + { + } + }; + + long deletionTimestamp = 0; + long now = System.currentTimeMillis(); + + assertFalse(mockHandler.objectHasBeenRemoved(deletionTimestamp, now)); + + deletionTimestamp = now + 1000; + assertFalse(mockHandler.objectHasBeenRemoved(deletionTimestamp, now)); + + deletionTimestamp = now - 1000; + assertTrue(mockHandler.objectHasBeenRemoved(deletionTimestamp, now)); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java new file mode 100644 index 0000000000..c528392a93 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseDomainModelTestCase.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import org.apache.qpid.management.configuration.Configurator; + +import junit.framework.TestCase; + +/** + * Layer supertype for all domain model related test cases. + * + * @author Andrea Gazzarini + */ +public abstract class BaseDomainModelTestCase extends TestCase +{ + /** + * Set up fixture for this test case. + * In order to execute tests on domain model we need to build the configuration. + */ + @Override + protected void setUp () throws Exception + { + Configurator configurator = new Configurator(); + configurator.configure(); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java new file mode 100644 index 0000000000..3d3783eb04 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/BaseQpidFeatureBuilderTestCase.java @@ -0,0 +1,96 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.desc; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.name; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.management.configuration.Configurator; +import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute; + +/** + * Layer supertype for feature builder test cases. + * + * @author Andrea Gazzarini + */ +public abstract class BaseQpidFeatureBuilderTestCase extends TestCase +{ + protected final static String NAME = "aName"; + + protected final static String DESCRIPTION = "A description."; + + protected Map _featureDefinition; + protected QpidFeatureBuilder _builder; + + /** + * Set up fixture for all concrete builder test cases. + */ + @Override + protected void setUp () throws Exception + { + Configurator configurator = new Configurator(); + configurator.configure(); + _featureDefinition = new HashMap(); + _featureDefinition.put(name.name(),NAME); + _featureDefinition.put(desc.name(), DESCRIPTION); + } + + // Internal test used to avoid code duplication. + protected void internalTestForMissingMandatoryAttribute(Attribute ...toBeRemoved) + { + try + { + for (Attribute attribute : toBeRemoved) + { + _featureDefinition.remove(attribute.name()); + } + _builder.build(); + fail("If a mandatory attribute is missing an exception must be thrown!"); + } catch (UnableToBuildFeatureException expected) + { + assertTrue(expected instanceof MissingFeatureAttributesException); + for (Attribute attribute : toBeRemoved) + { + assertTrue(expected.getMessage().contains(attribute.name())); + } + } + } + + // Internal test used to avoid code duplication. + protected void internalTestForMissingOptionalAttribute(Attribute ...toBeRemoved) throws UnableToBuildFeatureException + { + for (Attribute attribute : toBeRemoved) + { + _featureDefinition.remove(attribute.name()); + } + _builder.build(); + + assertNotNull(_builder.getQpidFeature()); + assertNotNull(_builder.getManagementFeature()); + } + + +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java new file mode 100644 index 0000000000..578fa36bc7 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/DomainModelTest.java @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.UUID; + +import org.apache.qpid.management.TestConstants; + +/** + * Test case for domain model entity. + * + * @author Andrea Gazzarini + */ +public class DomainModelTest extends BaseDomainModelTestCase +{ + private DomainModel _model; + + @Override + protected void setUp () throws Exception + { + _model = new DomainModel(UUID.randomUUID()); + } + + /** + * Tests the execution of the getPackage() method. + */ + public void testGetPackage() + { + assertFalse(_model.containsPackage(TestConstants.QPID_PACKAGE_NAME)); + + QpidPackage qpidPackage = _model.getPackageByName(TestConstants.QPID_PACKAGE_NAME); + assertEquals(TestConstants.QPID_PACKAGE_NAME,qpidPackage.getName()); + + QpidPackage theSameAsPreviousOne = _model.getPackageByName(TestConstants.QPID_PACKAGE_NAME); + assertSame(qpidPackage, theSameAsPreviousOne); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java new file mode 100644 index 0000000000..553c1c21de --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/OptionalPropertiesTest.java @@ -0,0 +1,187 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.qpid.management.domain.model.type.Uint64; +import org.apache.qpid.transport.codec.BBDecoder; + +public class OptionalPropertiesTest extends TestCase +{ + public void testDecoderStateChange() + { + QpidProperty property = new QpidProperty(); + assertSame( + "Default decoder for properties is the one for mandatory properties.", + property._mandatoryPropertyDecoder, + property._decoder); + + property.markAsOptional(1); + assertSame( + "After a property has been marked as optional the corresponding decoder must be installed.", + property._optionalPropertyDecoder, + property._decoder); + } + + /** + * Tests the execution of the decode() method when the current property is optional but in the presence bitmask + * there's no the corresponding bit set. + * + *
precondition : property is optional and corresponding presence bit is not set. + *
postcondition : result must be null. + */ + public void testDecodeValueWithOptionalPropertyAndMissingValue() + { + byte [] presenceBytes = {2}; + + QpidProperty property = new QpidProperty(); + + // We don't need a decoder so in order to be sure that it won't be invoked set it to null. + BBDecoder nullDecoder = null; + + for (int i = 0; i < 8; i++) + { + // Property number 1 is declaring a value so skip it! + if (i != 1) + { + property.markAsOptional(i); + assertNull(property.decodeValue(nullDecoder, presenceBytes)); + } + } + } + + /** + * Tests the execution of the decode() method when the current property is optional but in the presence bitmask + * there's no the corresponding bit set. + * + *
precondition : property is optional and corresponding presence bit is not set. + *
postcondition : result must be null. + */ + public void testDecodeValueWithOptionalPropertyAndDeclaredValue() + { + byte [] presenceBytes = {4}; + Long _44 = new Long(44); + + QpidProperty property = new QpidProperty(); + property.setType(new Uint64()); + property.markAsOptional(2); + + ByteBuffer buffer = ByteBuffer.allocate(8); + buffer.putLong(_44); + buffer.rewind(); + BBDecoder decoder = new BBDecoder(); + + decoder.init(buffer); + assertEquals(_44,property.decodeValue(decoder, presenceBytes)); + } + + /** + * Tests the execution of the decode() method with a real scenario where there are mandatory and optional + * properties. + */ + public void testDecodeValueWithOptionalAndMandatoryProperties() + { + // With this bitset : + // + // 1th opt property is null; + // 2th opt property is null; + // 3th opt property is not null; + // 4th opt property is null; + // 5th opt propertyis null; + // 6th opt property is null; + // 7th opt property is null; + // 8th opt property is not null; + byte [] presenceBytes = {4,1}; + + List properties = new LinkedList(); + + properties.add(createProperty(false, -1)); + properties.add(createProperty(false, -1)); + properties.add(createProperty(true, 0)); + properties.add(createProperty(false, -1)); + properties.add(createProperty(false, -1)); + properties.add(createProperty(true, 1)); + properties.add(createProperty(false, -1)); + properties.add(createProperty(false, -1)); + properties.add(createProperty(true, 2)); + properties.add(createProperty(true, 3)); + properties.add(createProperty(true, 4)); + properties.add(createProperty(true, 5)); + properties.add(createProperty(true, 6)); + properties.add(createProperty(true, 7)); + properties.add(createProperty(false, -1)); + properties.add(createProperty(true, 8)); + + Long expectedResults [] = { + 1L, // p1 + 22L, // p2 + null, // p3 + 232L, // p4 + 211L, // p5 + null, // p6 + 232L, // p7 + 211L, // p8 + 999L, // p9 + null, // p10 + null, // p11 + null, // p12 + null, // p13 + null, // p14 + 626L, // p15 + 969L // p16 + }; + + + ByteBuffer buffer = ByteBuffer.allocate(expectedResults.length * 8); + for (Long expected : expectedResults) + { + if (expected != null) + { + buffer.putLong(expected); + } + } + buffer.rewind(); + BBDecoder decoder = new BBDecoder(); + + decoder.init(buffer); + int index = 0; + for (QpidProperty property : properties) + { + assertEquals(expectedResults[index++],property.decodeValue(decoder, presenceBytes)); + } + } + + private QpidProperty createProperty(boolean isOptional, int optionalIndex) + { + QpidProperty property = new QpidProperty(); + property.setType(new Uint64()); + if (isOptional) + { + property.markAsOptional(optionalIndex); + } + return property; + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java new file mode 100644 index 0000000000..9d6e176912 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java @@ -0,0 +1,408 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.domain.model; + +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.MBeanAttributeInfo; +import javax.management.MBeanInfo; + +import junit.framework.TestCase; + +import org.apache.qpid.management.TestConstants; +import org.apache.qpid.management.configuration.ConfigurationException; +import org.apache.qpid.management.configuration.Configurator; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.domain.model.QpidClass.QManManagedObject; + +/** + * Test case for Qpid Class. + * + * @author Andrea Gazzarini + */ +public class QpidClassTest extends TestCase +{ + private QpidClass _class; + private QpidPackage _package; + + @Override + protected void setUp () throws ConfigurationException + { + Configurator configurator = new Configurator(); + configurator.configure(); + _package = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL); + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package); + } + + /** + * Tests the execution of the getObjectInstance() method. + * Basically it tests the addition of a new object instance. + * + *
precondition: class has no object instances. + *
precondition : class contains the added object instance. + */ + public void testGetObjectInstance() + { + assertFalse ( + "Nobody set instance #"+TestConstants.OBJECT_ID+" into this class so why is it there?", + _class._objectInstances.containsKey(TestConstants.OBJECT_ID)); + + QManManagedObject instance = _class.getObjectInstance(TestConstants.OBJECT_ID, false); + + assertTrue ( + "Now the instance #"+TestConstants.OBJECT_ID+" should be there...", + _class._objectInstances.containsKey(TestConstants.OBJECT_ID)); + + assertEquals(instance,_class.getObjectInstance(TestConstants.OBJECT_ID, false)); + } + + /** + * Tests the injection of instrumentation and configuration data (related to a specific object instance) before the + * schema is installed. + * + *
precondition : the schema hasn't yet installed on this class. + *
postcondition : incoming configuration & instrumentation data is stored into the corresponding object instance. + */ + public void testAddInstrumentationAndConfigurationDataBeforeSchemaInstallation() + { + _class._state = _class._schemaRequestedButNotYetInjected; + QManManagedObject objectInstance = _class.getObjectInstance(TestConstants.OBJECT_ID,false); + + assertTrue( + "This object instance is a new one so how is it possible that it has already instrumentation data? ", + objectInstance._rawInstrumentationData.isEmpty()); + assertTrue( + "This object instance is a new one so how is it possible that it has already configuration data? ", + objectInstance._rawConfigurationData.isEmpty()); + + byte [] dummyConfigurationData = {1,2,3,4,5,6,7,8}; + byte [] dummyInstrumentationData = {11,21,31,41,51,61,71,81}; + + _class.addConfigurationData(TestConstants.OBJECT_ID, dummyConfigurationData); + _class.addInstrumentationData(TestConstants.OBJECT_ID, dummyInstrumentationData); + + assertEquals("Now configuration data should be there...",1,objectInstance._rawConfigurationData.size()); + assertEquals("Now instrumentation data should be there...",1,objectInstance._rawInstrumentationData.size()); + + assertTrue( + "Object instance configuration data should be the previously set...", + Arrays.equals(objectInstance._rawConfigurationData.get(0), + dummyConfigurationData)); + + assertTrue( + "Object instance instrumentation data should be the previously set...", + Arrays.equals(objectInstance._rawInstrumentationData.get(0), + dummyInstrumentationData)); + } + + /** + * Tests the internal state change of a class definition. + */ + public void testStateChange() throws UnableToBuildFeatureException + { + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception { + _state = _schemaRequestedButNotYetInjected; + } + + @Override + void setSchema(List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException { + _state = _schemaInjected; + } + }; + + assertSame( + "Initial state doesn't match.", + _class._schemaNotRequested, + _class._state); + + _class.addConfigurationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + + _class.setSchema( + TestConstants.EMPTY_PROPERTIES_SCHEMA, + TestConstants.EMPTY_STATISTICS_SCHEMA, + new LinkedList()); + + assertSame( + "Request schema has been injected. The current state is not indicating that!", + _class._schemaInjected, + _class._state); + } + + /** + * Tests the injection of a valid schema on a QpidClass. + * + *
precondition : a valid arguments is injected on the qpid class. + *
postcondition : class definition is built successfully. + */ + public void testSchemaInjectionOk() throws UnableToBuildFeatureException + { + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception + { + // DO NOTHING : QMan is not running and therefore the schema will be manually injected. + } + + @Override + void updateInstanceWithConfigurationData(QManManagedObject instance, byte[] rawData) + { + // DO NOTHING Given raw data is not valid so it cannot be converted. + } + }; + + // Incoming configuration data : that will fire the schema request and a state change + // from schema-not-requested to schema-requested-but-not-injected + _class.addConfigurationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + // I must be sure that what is obvious for me it's obvious for QMan... :) + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + + List> propertyDefinitions = new ArrayList>(2); + propertyDefinitions.add( + createProperty( + TestConstants.AGE_ATTRIBUTE_NAME, + 1, + TestConstants.YEARS, + TestConstants.SAMPLE_MIN_VALUE, + TestConstants.SAMPLE_MAX_VALUE, + null, + TestConstants.AGE_ATTRIBUTE_DESCRIPTION, + TestConstants._1, + false, + TestConstants._0)); + + propertyDefinitions.add( + createProperty( + TestConstants.SURNAME_ATTRIBUTE_NAME, + TestConstants.SAMPLE_ACCESS_CODE, + null, + null, + null, + TestConstants.SAMPLE_MAX_VALUE, + TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION, + TestConstants._1, + true, + TestConstants._1)); + + _class.setSchema(propertyDefinitions, TestConstants.EMPTY_STATISTICS_SCHEMA, TestConstants.EMPTY_METHODS_SCHEMA); + + assertEquals(2,_class._properties.size()); + + QpidProperty property = _class._properties.get(TestConstants.AGE_ATTRIBUTE_NAME); + assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,property.getName()); + assertEquals(AccessMode.RC,property.getAccessMode()); + assertEquals(TestConstants.YEARS,property.getUnit()); + assertEquals(TestConstants.SAMPLE_MIN_VALUE,property.getMinValue()); + assertEquals(TestConstants.SAMPLE_MAX_VALUE,property.getMaxValue()); + assertEquals(Integer.MIN_VALUE,property.getMaxLength()); + assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,property.getDescription()); + assertEquals(Short.class,property.getJavaType()); + assertFalse(property.isOptional()); + + property = _class._properties.get(TestConstants.SURNAME_ATTRIBUTE_NAME); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,property.getName()); + assertEquals(AccessMode.RC,property.getAccessMode()); + assertNull(property.getUnit()); + assertEquals(Integer.MIN_VALUE,property.getMinValue()); + assertEquals(Integer.MIN_VALUE,property.getMaxValue()); + assertEquals(TestConstants.SAMPLE_MAX_VALUE,property.getMaxLength()); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,property.getDescription()); + assertEquals(Short.class,property.getJavaType()); + assertTrue(property.isOptional()); + + MBeanInfo mbeanInfo = _class._metadata; + assertEquals(TestConstants.EXCHANGE_CLASS_NAME,mbeanInfo.getClassName()); + + MBeanAttributeInfo [] attributes = mbeanInfo.getAttributes(); + assertEquals(2,attributes.length); + + MBeanAttributeInfo attribute = attributes[0]; + assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,attribute.getName()); + assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,attribute.getDescription()); + assertFalse(attribute.isWritable()); + assertTrue(attribute.isReadable()); + assertEquals(Short.class.getName(),attribute.getType()); + + attribute = attributes[1]; + assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,attribute.getName()); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,attribute.getDescription()); + assertFalse(attribute.isWritable()); + assertTrue(attribute.isReadable()); + assertEquals(Short.class.getName(),attribute.getType()); + } + + /** + * Tests the behaviour of the class when a schema request can't be made. + * + *
precondition : class must be in "schema-not-requested" state when incoming data arrives. + *
postcondition : no exception is thrown and no state transition happens. + */ + public void testStateChange_withRequestSchemaFailure() + { + _class= new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception { + throw new Exception(); + } + + @Override + void setSchema( + List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) throws UnableToBuildFeatureException + { + } + }; + + assertSame( + "Initial state must be schema-not-requested.", + _class._schemaNotRequested, + _class._state); + + _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + assertSame( + "Current state must be still schema-not-requested.", + _class._schemaNotRequested, + _class._state); + } + + /** + * Tests the behaviour of the class when a schema injection fails. + * + *
precondition : class must be in "schema-not-requested" state when incoming data arrives. + *
postcondition : an exception is thrown and no state transition happens. + */ + public void testStateChange_withSchemaInjectionFailure() + { + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception + { + // DO NOTHING. + } + + @Override + void setSchema(List> propertyDefinitions, + List> statisticDefinitions, + List methodDefinitions) + throws UnableToBuildFeatureException + { + throw new UnableToBuildFeatureException(""); + } + }; + + assertSame( + "Initial state must be schema-not-requested.", + _class._schemaNotRequested, + _class._state); + + _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + + try { + _class.setSchema( + TestConstants.EMPTY_PROPERTIES_SCHEMA, + TestConstants.EMPTY_STATISTICS_SCHEMA, + TestConstants.EMPTY_METHODS_SCHEMA); + fail("If we are here something was wrong becuase the setSchema() of this event is throwing an exception..."); + } catch (UnableToBuildFeatureException expected) { + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + } + } + + private Map createProperty( + String name, + Integer accessCode, + String unit, + Integer min, + Integer max, + Integer maxLength, + String description, + Integer type, + boolean optional, + Integer index) + { + Map result = new HashMap(); + result.put(QpidFeatureBuilder.Attribute.name.name(),name); + result.put(QpidFeatureBuilder.Attribute.access.name(), accessCode); + + if (unit != null) + { + result.put(QpidFeatureBuilder.Attribute.unit.name(),unit); + } + + if (min != null) + { + result.put(QpidFeatureBuilder.Attribute.min.name(), min); + } + + if (max != null) + { + result.put(QpidFeatureBuilder.Attribute.max.name(),max); + } + + if (maxLength != null) + { + result.put(QpidFeatureBuilder.Attribute.maxlen.name(),maxLength); + } + + result.put(QpidFeatureBuilder.Attribute.desc.name(), description); + result.put(QpidFeatureBuilder.Attribute.type.name(), type); + result.put(QpidFeatureBuilder.Attribute.optional.name(),optional ? 1 : 0); + + if (index != null) + { + result.put(QpidFeatureBuilder.Attribute.index.name(), index); + } + return result; + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java new file mode 100644 index 0000000000..4b36d9e5cc --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java @@ -0,0 +1,293 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanException; +import javax.management.ObjectName; +import javax.management.ReflectionException; + +import junit.framework.TestCase; + +import org.apache.qpid.management.TestConstants; +import org.apache.qpid.management.configuration.ConfigurationException; +import org.apache.qpid.management.configuration.Configurator; +import org.apache.qpid.management.domain.model.QpidEvent.QManManagedEvent; + +/** + * Test case for qpid class entity. + * + * @author Andrea Gazzarini + */ +public class QpidEventTest extends TestCase +{ + private QpidEvent _event; + private QpidPackage _qpidPackage; + + @Override + protected void setUp () throws Exception + { + _qpidPackage = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL); + _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage); + } + + /** + * Tests the execution of the createEventInstance() method. + * Basically it tests the addition of a new event instance. + * + *
precondition: event deifinition has no object instances. + *
precondition : event definition contains the new object instance. + */ + public void testCreateEventInstance() + { + assertTrue( + "A just created event should be empty. I mean there shouldn't be event instances inside.", + _event.hasNoInstances()); + + QManManagedEvent instance = createEventInstance(); + + assertFalse ( + "Now a new instance should be there...", + _event.hasNoInstances()); + + assertEquals(TestConstants.TEST_RAW_DATA,instance._rawEventData); + assertEquals(TestConstants.NOW,instance._timestamp); + assertEquals(TestConstants.SEVERITY, instance._severity); + } + + /** + * Tests the internal state change of an event definition. + */ + public void testStateChange() throws UnableToBuildFeatureException + { + // Let's override this class because this is not an online tests and therefore + // QMan is not supposed to be up. + _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage) + { + @Override + void requestSchema() throws Exception { + // Do Nothing. + } + + @Override + void setSchema(List> argumentDefinitions)throws UnableToBuildFeatureException { + _state = _schemaInjected; + } + }; + + assertSame( + "Initial state doesn't match.", + _event._schemaNotRequested, + _event._state); + + _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY); + + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _event._schemaRequestedButNotYetInjected, + _event._state); + + _event.setSchema(TestConstants.EMPTY_ARGUMENTS_SCHEMA); + + assertSame( + "Request schema has been injected. The current state is not indicating that!", + _event._schemaInjected, + _event._state); + } + + /** + * Tests the injection of a valid schema on a QpidEvent. + * + *
precondition : a valid arguments is injected on the qpid event. + *
postcondition : event definition is built successfully. + */ + public void testSchemaInjectionOK() throws UnableToBuildFeatureException, ConfigurationException, InstanceNotFoundException, MBeanException, ReflectionException + { + _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage) + { + @Override + void requestSchema() throws Exception + { + // DO NOTHING : QMan is not running and therefore the schema will be manually injected. + } + + @Override + void updateEventInstanceWithData(QManManagedEvent instance) + { + // DO NOTHING : otherwise we should supply a valid raw data to be converted. ;-) + } + }; + + Configurator configurator = new Configurator(); + configurator.configure(); + + List> arguments = new ArrayList>(); + arguments.add(createArgument(TestConstants.AGE_ATTRIBUTE_NAME, TestConstants.AGE_ATTRIBUTE_DESCRIPTION)); + arguments.add(createArgument(TestConstants.SURNAME_ATTRIBUTE_NAME, TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION)); + + // Incoming data : that will fire the schema request and a state change from schema-not-requested to schema-requested-but-not-injected + _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY); + + // I must be sure that what is obvious for me it's obvious for QMan... :) + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _event._schemaRequestedButNotYetInjected, + _event._state); + + // Inject schema + _event.setSchema(arguments); + + // Arguments must be 2 + 2 (severity) + assertEquals(2,_event._arguments.size()); + + QpidProperty argument = _event._arguments.get(TestConstants.AGE_ATTRIBUTE_NAME); + assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,argument.getName()); + assertEquals(AccessMode.RO,argument.getAccessMode()); + assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,argument.getDescription()); + assertEquals(Short.class,argument.getJavaType()); + assertFalse(argument.isOptional()); + + argument = _event._arguments.get(TestConstants.SURNAME_ATTRIBUTE_NAME); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,argument.getName()); + assertEquals(AccessMode.RO,argument.getAccessMode()); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,argument.getDescription()); + assertEquals(Short.class,argument.getJavaType()); + assertFalse(argument.isOptional()); + + assertEquals(1,_event._eventInstances.size()); + + JmxService service = new JmxService(); + Set objectNames = service.getEventMBeans(); + + assertEquals(1,objectNames.size()); + } + + /** + * Tests the behaviour of the event class when a schema request can't be made. + * + *
precondition : event must be in "schema-not-requested" state when incoming data arrives. + *
postcondition : no exception is thrown and no state transition happens. + */ + public void testStateChange_withRequestSchemaFailure() + { + _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage) + { + @Override + void requestSchema() throws Exception { + throw new Exception(); + } + + @Override + void setSchema(List> argumentDefinitions)throws UnableToBuildFeatureException { + _state = _schemaInjected; + } + }; + + assertSame( + "Initial state must be schema-not-requested.", + _event._schemaNotRequested, + _event._state); + + _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY); + + assertSame( + "Current state must be still schema-not-requested.", + _event._schemaNotRequested, + _event._state); + } + + /** + * Tests the behaviour of the event class when a schema injection fails. + * + *
precondition : event must be in "schema-not-requested" state when incoming data arrives. + *
postcondition : an exception is thrown and no state transition happens. + */ + public void testStateChange_withSchemaInjectionFailure() + { + _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage) + { + @Override + void requestSchema() throws Exception { + // DO NOTHING. + } + + @Override + void setSchema(List> argumentDefinitions)throws UnableToBuildFeatureException { + throw new UnableToBuildFeatureException(""); + } + }; + + assertSame( + "Initial state must be schema-not-requested.", + _event._schemaNotRequested, + _event._state); + + _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY); + + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _event._schemaRequestedButNotYetInjected, + _event._state); + + try { + _event.setSchema(TestConstants.EMPTY_ARGUMENTS_SCHEMA); + fail("If we are here something was wrong becuase the setSchema() of this event is throwing an exception..."); + } catch (UnableToBuildFeatureException expected) { + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _event._schemaRequestedButNotYetInjected, + _event._state); + } + } + + /** + * Factory method for qpid managed event instances. + * + * @return a new QpidManagedEvent with test data inside. + */ + private QManManagedEvent createEventInstance() + { + return _event.createEventInstance( + TestConstants.TEST_RAW_DATA, + TestConstants.NOW, + TestConstants.SEVERITY); + } + + /** + * Factory method for event argument. + * + * @return a new argument metadata. + */ + private Map createArgument(String name,String desc) + { + Map argument = new HashMap(); + argument.put(QpidFeatureBuilder.Attribute.name.name(),name); + argument.put(QpidFeatureBuilder.Attribute.desc.name(), desc); + argument.put(QpidFeatureBuilder.Attribute.type.name(), TestConstants._1); + return argument; + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java new file mode 100644 index 0000000000..06dc35b0b1 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidMethodBuilderTest.java @@ -0,0 +1,147 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.dir; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.name; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.type; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.unit; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.management.MBeanOperationInfo; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; +import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute; + +/** + * Test case for Qpid Statistic builder. + * + * @author Andrea Gazzarini + */ +public class QpidMethodBuilderTest extends BaseQpidFeatureBuilderTestCase +{ + private final static Integer ARG_COUNT = 3; + private MethodOrEventDataTransferObject _methodDefinition; + + private List> _argumentsDefinitons = new ArrayList>(); + + @Override + protected void setUp () throws Exception + { + super.setUp(); + _featureDefinition.put(Names.ARG_COUNT_PARAM_NAME, ARG_COUNT); + + Map arg1 = new HashMap(); + arg1.put(name.name(), "arg1"); + arg1.put(type.name(),1); + arg1.put(dir.name(),Direction.I.name()); + arg1.put(unit.name(), "bytes"); + + Map arg2 = new HashMap(); + arg2.put(name.name(), "arg2"); + arg2.put(type.name(),1); + arg2.put(dir.name(),Direction.O.name()); + arg2.put(unit.name(), "bytes"); + + Map arg3 = new HashMap(); + arg3.put(name.name(), "arg3"); + arg3.put(type.name(),1); + arg3.put(dir.name(),Direction.IO.name()); + arg3.put(unit.name(), "bytes"); + + /* + dir yes no yes Direction code for method arguments + unit yes yes yes Units for numeric values (i.e. seconds, bytes, etc.) + min yes no yes Minimum value for numerics + max yes no yes Maximum value for numerics + maxlen yes no yes Maximum length for strings + desc yes yes yes Description of the argument + default yes no yes Default value for the argument + */ + _argumentsDefinitons.add(arg1); + _argumentsDefinitons.add(arg2); + + _methodDefinition = new MethodOrEventDataTransferObject(_featureDefinition,_argumentsDefinitons); + _builder = QpidFeatureBuilder.createMethodBuilder(_methodDefinition); + } + + /** + * Tests the build process for a statistic when the definition map doesn't contains type attribute. + * + *
precondition: definition map doesn't contains type attribute. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attribute. + */ + public void testMethodBuilderKO_WithMissingName() + { + internalTestForMissingMandatoryAttribute(Attribute.name); + } + + /** + * Tests the build process for a statistic when the definition map doesn't contain type, name, index & optional attributes. + * + *
precondition: definition map doesn't contain type, name, index & optional attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testMethodBuilderOK_WithMissingUnit() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.unit); + } + + /** + * Tests the build process for a statistic when the definition map doesn't unit attribute. + * Note that this attribute is optional and therefore the build must succeed. + * + *
precondition: definition map doesn't contain unit attribute. + *
postcondition : no exception is thrown and the statistic is built. + */ + public void testMethodBuilderOK_WithMissingDescription() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.desc); + } + + /** + * Tests the build process for a statistic when the definition map contains valid values. + * + *
precondition : the statistic definiton map contains valid values. + *
postcondition : no exception is thrown and the statistisc is built as expected. + */ + public void testMethodBuilderOK() throws UnableToBuildFeatureException + { + _builder.build(); + + QpidMethod method = (QpidMethod) _builder.getQpidFeature(); + MBeanOperationInfo info = (MBeanOperationInfo) _builder.getManagementFeature(); + + assertEquals(NAME,method.getName()); + + assertEquals(DESCRIPTION,method.getDescription()); + + assertEquals(method.getDescription(),info.getDescription()); + assertEquals(method.getName(),info.getName()); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java new file mode 100644 index 0000000000..374011d150 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidNumberPropertyTest.java @@ -0,0 +1,171 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import junit.framework.TestCase; + +import org.apache.qpid.management.configuration.Configurator; +import org.apache.qpid.management.domain.model.type.Uint8; + +public class QpidNumberPropertyTest extends TestCase +{ + private QpidProperty _property; + private Long _value = 55432L; + + @Override + protected void setUp () throws Exception + { + Configurator configurator = new Configurator(); + configurator.configure(); + _property = new QpidProperty(); + _property.setName("average"); + _property.setAccessMode(AccessMode.RW); + _property.setType(new Uint8()); + } + + /** + * Tests the validation of a qpid property when the type is a number and no constraint has been set. + * + *
precondition : property type is a string, no constraint has been set. + *
postcondition : no exception is thrown and the validation succeeds. + */ + public void testValidationWithoutConstraints() { + try + { + _property.validate(_value); + } catch (ValidationException notExpected) + { + fail("If no constraint has been set on this property why the validation is failing?"); + } + } + + /** + * Tests the validation of a qpid property when the type is a number and a max value constraint has been set. + * + *
precondition : property type is a number, max value has been set and property value is greater than max value. + *
postcondition : an exception is thrown indicating the validation failure. + */ + public void testValidationKO_withMaxValue() { + int maxValue = (int)(_value-1); + _property.setMaxValue(maxValue); + + try + { + _property.validate(_value); + fail("The given value is violating the installed constraint so an exception must be thrown."); + } catch (ValidationException expected) + { + assertEquals(ValidationException.MAX_VALUE,expected.getConstraintName()); + assertEquals(maxValue,expected.getConstraintValue()); + assertEquals((double)_value,expected.getFeatureValue()); + assertEquals(_property.getName(),expected.getFeatureName()); + } + } + + /** + * Tests the validation of a qpid property when the type is a number and a min value constraint has been set. + * + *
precondition : property type is a number, min value has been set and property value is lesser than min value. + *
postcondition : an exception is thrown indicating the validation failure. + */ + public void testValidationKO_withMinValue() { + int minValue = (int)(_value+1); + _property.setMinValue(minValue); + + try + { + _property.validate(_value); + fail("The given value is violating the installed constraint so an exception must be thrown."); + } catch (ValidationException expected) + { + assertEquals(ValidationException.MIN_VALUE,expected.getConstraintName()); + assertEquals(minValue,expected.getConstraintValue()); + assertEquals((double)_value,expected.getFeatureValue()); + assertEquals(_property.getName(),expected.getFeatureName()); + } + } + + + /** + * Tests the validation of a qpid property when the number is a string and the property value is null. + * + *
precondition : property type is a number and property value is null.. + *
postcondition : no exception is thrown. That is : the validation succeeds. + */ + public void testValidationOK_withNullValue() { + try + { + _property.validate(null); + } catch (ValidationException notExpected) + { + fail("No constraint has been violated so validate() shouldn't raise an exception."); + } + + _property.setMinValue(1); + _property.setMaxValue(10); + + try + { + _property.validate(null); + } catch (ValidationException notExpected) + { + fail("No constraint has been violated so validate() shouldn't raise an exception."); + } + } + + /** + * Tests the validation of a qpid property when the type is a number and a max / min constraints have been set. + * + *
precondition : property type is a number, max / min constraint have been set and property value is wrong. + *
postcondition : an exception is thrown indicating the validation failure. + */ + public void testValidationOK_withMinAndMaxConstraint() { + int minValue = (int)(_value+1); + int maxValue = (int)(_value-1); + _property.setMinValue(minValue); + _property.setMaxValue(maxValue); + + try + { + _property.validate(_value); + fail("The given value is violating the installed constraint so an exception must be thrown."); + } catch (ValidationException expected) + { + assertEquals(ValidationException.MIN_VALUE,expected.getConstraintName()); + assertEquals(minValue,expected.getConstraintValue()); + assertEquals((double)_value,expected.getFeatureValue()); + assertEquals(_property.getName(),expected.getFeatureName()); + } + + _property.setMinValue(0); + try + { + _property.validate(_value); + fail("The given value is violating the installed constraint so an exception must be thrown."); + } catch (ValidationException expected) + { + assertEquals(ValidationException.MAX_VALUE,expected.getConstraintName()); + assertEquals(maxValue,expected.getConstraintValue()); + assertEquals((double)_value,expected.getFeatureValue()); + assertEquals(_property.getName(),expected.getFeatureName()); + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java new file mode 100644 index 0000000000..b7eb9055ba --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPackageTest.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import org.apache.qpid.management.TestConstants; + +/** + * Test case for Qpid package entity. + * + * @author Andrea Gazzarini + */ +public class QpidPackageTest extends BaseDomainModelTestCase +{ + private QpidPackage _qpidPackage; + + @Override + protected void setUp () throws Exception + { + _qpidPackage = new QpidPackage(TestConstants.QPID_PACKAGE_NAME, TestConstants.DOMAIN_MODEL); + } + + /** + * Tests the association of a new class with a qpid package. + * + *
precondition : the package is not associated with any class. + *
postcondition : the package is now associated with the given class. + */ + public void testAddClass() throws UnableToBuildFeatureException { + assertFalse(_qpidPackage.alreadyContainsClassDefinition(TestConstants.EXCHANGE_CLASS_NAME, TestConstants.HASH)); + + _qpidPackage.getQpidClass(TestConstants.EXCHANGE_CLASS_NAME, TestConstants.HASH, true); + + assertTrue(_qpidPackage.alreadyContainsClassDefinition(TestConstants.EXCHANGE_CLASS_NAME, TestConstants.HASH)); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java new file mode 100644 index 0000000000..8ad177645c --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidPropertyBuilderTest.java @@ -0,0 +1,269 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.access; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.index; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.max; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.min; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.optional; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.type; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.unit; + +import javax.management.MBeanAttributeInfo; + +import org.apache.qpid.management.configuration.UnknownTypeCodeException; +import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute; + +/** + * Test case for Qpid Property builder. + * + * @author Andrea Gazzarini + */ +public class QpidPropertyBuilderTest extends BaseQpidFeatureBuilderTestCase +{ + private final static Integer MIN = 0; + private final static Integer MAX = 120; + private final static String UNIT = "bytes"; + + private Integer _access; + + @Override + protected void setUp () throws Exception + { + super.setUp(); + + _access = 1; + _featureDefinition.put(access.name(), _access); + _featureDefinition.put(unit.name(),UNIT); + _featureDefinition.put(min.name(), MIN); + _featureDefinition.put(max.name(),MAX); + + _featureDefinition.put(type.name(), 1); + _featureDefinition.put(optional.name(),0); + _featureDefinition.put(index.name(), 0); + + _builder = QpidFeatureBuilder.createPropertyBuilder(_featureDefinition); + } + + /** + * Tests the build process for a statistic when the definition map contains an unknown type code. + * + *
precondition : the statistic definiton map contains an unknown type code. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testStatisticBuilderKO_WithUnknownType() + { + int unknownTypeCode =999; + try + { + _featureDefinition.put(type.name(), unknownTypeCode); + _builder.build(); + fail("An unknown type code should raise an exception to indicate a failure."); + } catch (UnableToBuildFeatureException expected) + { + assertEquals(unknownTypeCode,((UnknownTypeCodeException)expected.getCause()).getCode()); + } + } + + /** + * Tests the build process for a statistic when the definition map contains a null value for a metadata attribute. + * + *
precondition : the statistic definiton map contains a null value for a metadata attribute. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testMethodBuilderKO_WithNullMetadataValue() + { + try + { + _featureDefinition.put(type.name(), null); + _builder.build(); + fail("An null value for a metadata attribute should raise an exception to indicate a failure."); + } catch (UnableToBuildFeatureException expected) + { + assertTrue(expected.getCause() instanceof NullPointerException); + } + } + + /** + * Tests the build process for a property when the definition map contains an invalid metadata type. + * + *
precondition : the property definiton map contains a wrong type for a metadata attribute. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testPropertyBuilderKO_WithClassCastException() + { + try + { + _featureDefinition.put(access.name(), new String("a")); + _builder.build(); + fail("A wrong metadata attribute type should raise an exception to indicate a failure."); + } catch (UnableToBuildFeatureException expected) + { + assertTrue(expected.getCause() instanceof ClassCastException); + } + } + + /** + * Tests the build process for a property when the definition map contains an unknown type code. + * + *
precondition : the property definiton map contains an unknown type code. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testPropertyBuilderKO_WithUnknownType() + { + int unknownTypeCode = 999; + try + { + _featureDefinition.put(type.name(), unknownTypeCode); + _builder.build(); + fail("An unknown type code should raise an exception to indicate a failure."); + } catch (UnableToBuildFeatureException expected) + { + assertEquals(unknownTypeCode,((UnknownTypeCodeException)expected.getCause()).getCode()); + } + } + + /** + * Tests the build process for a property when the definition map doesn't contains type attribute. + * + *
precondition: definition map doesn't contains type attribute. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attribute. + */ + public void testPropertyBuilderKO_WithMissingType() + { + internalTestForMissingMandatoryAttribute(Attribute.type); + } + + /** + * Tests the build process for a property when the definition map doesn't contain type & name attributes. + * + *
precondition: definition map doesn't contain type & name attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testPropertyBuilderKO_WithMissingTypeAndName() + { + internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name); + } + + /** + * Tests the build process for a property when the definition map doesn't contain type & name & index attributes. + * + *
precondition: definition map doesn't contain type & name & index attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testPropertyBuilderKO_WithMissingTypeAndNameAndIndex() + { + internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name,Attribute.index); + } + + /** + * Tests the build process for a property when the definition map doesn't contain type, name, index & optional attributes. + * + *
precondition: definition map doesn't contain type, name, index & optional attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testPropertyBuilderKO_WithMissingTypeAndNameAndIndexAndOptional() + { + internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name,Attribute.index,Attribute.optional); + } + + /** + * Tests the build process for a property when the definition map doesn't contain type, name, index, optional and access + * attributes. + * + *
precondition: definition map doesn't contain type, name, index, optional and access attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testPropertyBuilderKO_WithMissingTypeAndNameAndIndexAndOptionalAndAccess() + { + internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name,Attribute.index,Attribute.optional,Attribute.access); + } + + /** + * Tests the build process for a property when the definition map doesn't unit attribute. + * Note that this attribute is optional and therefore the build must succeed. + * + *
precondition: definition map doesn't contain unit attribute. + *
postcondition : no exception is thrown and the property is built. + */ + public void testBuilderOK_WithMissingUnit() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.unit); + } + + /** + * Tests the build process for a property when the definition map doesn't min and max attributes. + * Note that those attributes are optional and therefore the build must succeed. + * + *
precondition: definition map doesn't contain min and max attributes. + *
postcondition : no exception is thrown and the property is built. + */ + public void testBuilderOK_WithMissingMinAndMax() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.min,Attribute.max); + } + + /** + * Tests the build process for a property when the definition map doesn't description attribute. + * Note that this attribute is optional and therefore the build must succeed. + * + *
precondition: definition map doesn't contain description attribute. + *
postcondition : no exception is thrown and the property is built. + */ + public void testBuilderOK_WithMissingDescription() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.desc); + } + + /** + * Tests the build process for a property when the definition map contains valid values. + * + *
precondition : the property definiton map contains valid values. + *
postcondition : no exception is thrown and the property is built as expected. + */ + public void testPropertyBuilderOK() throws UnableToBuildFeatureException + { + _builder.build(); + + QpidProperty property = (QpidProperty) _builder.getQpidFeature(); + MBeanAttributeInfo info = (MBeanAttributeInfo) _builder.getManagementFeature(); + + assertEquals(NAME,property.getName()); + assertEquals(AccessMode.RC,property.getAccessMode()); + assertEquals(UNIT,property.getUnit()); + assertEquals(MIN.intValue(),property.getMinValue()); + assertEquals(MAX.intValue(),property.getMaxValue()); + assertEquals(Integer.MIN_VALUE,property.getMaxLength()); + assertEquals(DESCRIPTION,property.getDescription()); + assertEquals(Short.class,property.getJavaType()); + assertFalse(property.isOptional()); + + assertEquals(property.getDescription(),info.getDescription()); + assertEquals(property.getName(),info.getName()); + assertEquals(property.getJavaType().getName(),info.getType()); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java new file mode 100644 index 0000000000..b7a8540b2d --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStatisticBuilderTest.java @@ -0,0 +1,159 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.type; +import static org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute.unit; + +import javax.management.MBeanAttributeInfo; + +import org.apache.qpid.management.configuration.UnknownTypeCodeException; +import org.apache.qpid.management.domain.model.QpidFeatureBuilder.Attribute; + +/** + * Test case for Qpid Statistic builder. + * + * @author Andrea Gazzarini + */ +public class QpidStatisticBuilderTest extends BaseQpidFeatureBuilderTestCase +{ + private final static String UNIT = "bytes"; + + @Override + protected void setUp () throws Exception + { + super.setUp(); + _featureDefinition.put(unit.name(),UNIT); + _featureDefinition.put(type.name(), 1); + + _builder = QpidFeatureBuilder.createStatisticBuilder(_featureDefinition); + } + + /** + * Tests the build process for a statistic when the definition map contains an unknown type code. + * + *
precondition : the statistic definiton map contains an unknown type code. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testStatisticBuilderKO_WithUnknownType() + { + int unknownTypeCode = 999; + try + { + _featureDefinition.put(type.name(), unknownTypeCode); + _builder.build(); + fail("An unknown type code should raise an exception to indicate a failure."); + } catch (UnableToBuildFeatureException expected) + { + assertEquals(unknownTypeCode,((UnknownTypeCodeException)expected.getCause()).getCode()); + } + } + + /** + * Tests the build process for a statistic when the definition map contains a null value for a metadata attribute. + * + *
precondition : the statistic definiton map contains a null value for a metadata attribute. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testMethodBuilderKO_WithNullMetadataValue() + { + try + { + _featureDefinition.put(type.name(), null); + _builder.build(); + fail("An null value for a metadata attribute should raise an exception to indicate a failure."); + } catch (UnableToBuildFeatureException expected) + { + assertTrue(expected.getCause() instanceof NullPointerException); + } + } + + /** + * Tests the build process for a statistic when the definition map doesn't contains type attribute. + * + *
precondition: definition map doesn't contains type attribute. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attribute. + */ + public void testStatisticBuilderKO_WithMissingType() + { + internalTestForMissingMandatoryAttribute(Attribute.type); + } + + /** + * Tests the build process for a statistic when the definition map doesn't contain type & name attributes. + * + *
precondition: definition map doesn't contain type & name attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testStatisticBuilderKO_WithMissingTypeAndName() + { + internalTestForMissingMandatoryAttribute(Attribute.type, Attribute.name); + } + + /** + * Tests the build process for a statistic when the definition map doesn't contain type, name, index & optional attributes. + * + *
precondition: definition map doesn't contain type, name, index & optional attributes. + *
postcondition : an exception should be thrown indicating the failure. That exception must contain the name of the + * missing attributes. + */ + public void testStatisticBuilderOK_WithMissingUnit() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.unit); + } + + /** + * Tests the build process for a statistic when the definition map doesn't unit attribute. + * Note that this attribute is optional and therefore the build must succeed. + * + *
precondition: definition map doesn't contain unit attribute. + *
postcondition : no exception is thrown and the statistic is built. + */ + public void testBuilderOK_WithMissingDescription() throws UnableToBuildFeatureException + { + internalTestForMissingOptionalAttribute(Attribute.desc); + } + + /** + * Tests the build process for a statistic when the definition map contains valid values. + * + *
precondition : the statistic definiton map contains valid values. + *
postcondition : no exception is thrown and the statistisc is built as expected. + */ + public void testStatisticBuilderOK() throws UnableToBuildFeatureException + { + _builder.build(); + + QpidStatistic statistic= (QpidStatistic) _builder.getQpidFeature(); + MBeanAttributeInfo info = (MBeanAttributeInfo) _builder.getManagementFeature(); + + assertEquals(NAME,statistic.getName()); + assertEquals(UNIT,statistic.getUnit()); + assertEquals(DESCRIPTION,statistic.getDescription()); + assertEquals(Short.class,statistic.getJavaType()); + + assertEquals(statistic.getDescription(),info.getDescription()); + assertEquals(statistic.getName(),info.getName()); + assertEquals(statistic.getJavaType().getName(),info.getType()); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java new file mode 100644 index 0000000000..8aeb7c8550 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidStringPropertyTest.java @@ -0,0 +1,127 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model; + +import junit.framework.TestCase; + +import org.apache.qpid.management.configuration.Configurator; +import org.apache.qpid.management.domain.model.type.Str16; + +public class QpidStringPropertyTest extends TestCase +{ + private QpidProperty _property; + private final String _5LettersString = "12345"; + + @Override + protected void setUp () throws Exception + { + Configurator configurator = new Configurator(); + configurator.configure(); + _property = new QpidProperty(); + _property.setName("name"); + _property.setAccessMode(AccessMode.RW); + _property.setType(new Str16()); + } + + /** + * Tests the validation of a qpid property when the type is a string and a max length constraint hasn't been set. + * + *
precondition : property type is a string, max length hasn't been set. + *
postcondition : no exception is thrown. That is : the validation succeeds. + */ + public void testValidationWithoutMaxLength() { + try + { + _property.validate(_5LettersString); + } catch (ValidationException notExpected) + { + fail("No max length has been set on property so validation must succeed."); + } + } + + /** + * Tests the validation of a qpid property when the type is a string and a max length constraint has been set. + * + *
precondition : property type is a string, max length has been set and property value is longer than max length. + *
postcondition : an exception is thrown indicating the validation failure. + */ + public void testValidationKO_withMaxLength() { + int maxLength = 2; + _property.setMaxLength(maxLength); + + try + { + _property.validate(_5LettersString); + fail("No max length has been set on property so validation must proceed."); + } catch (ValidationException expected) + { + assertEquals(ValidationException.MAX_LENGTH,expected.getConstraintName()); + assertEquals(maxLength,expected.getConstraintValue()); + assertEquals(_5LettersString.length(),expected.getFeatureValue()); + assertEquals(_property.getName(),expected.getFeatureName()); + } + } + + /** + * Tests the validation of a qpid property when the type is a string and the property value is null. + * + *
precondition : property type is a string and property value is null.. + *
postcondition : no exception is thrown. That is : the validation succeeds. + */ + public void testValidationOK_withNullValue() { + try + { + _property.validate(null); + } catch (ValidationException notExpected) + { + fail("No constraint has been violated so validate() shouldn't raise an exception."); + } + + _property.setMaxLength(1); + + try + { + _property.validate(null); + } catch (ValidationException notExpected) + { + fail("No constraint has been violated so validate() shouldn't raise an exception."); + } + } + + /** + * Tests the validation of a qpid property when the type is a string and a max length constraint has been set. + * + *
precondition : property type is a string, max length has been set and property value is not violating that. + *
postcondition : no exception is thrown. That is : the validation succeeds. + */ + public void testValidationOK_withMaxLength() { + int maxLength = (_5LettersString.length()+1); + _property.setMaxLength(maxLength); + + try + { + _property.validate(_5LettersString); + } catch (ValidationException notExpected) + { + fail("No constraint has been violated so validate() shouldn't raise an exception."); + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java new file mode 100644 index 0000000000..6636c08710 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/model/type/BinaryTest.java @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.model.type; + +import junit.framework.TestCase; + +/** + * Test case for "Binary" type. + * + * @author Andrea Gazzarini + */ +public class BinaryTest extends TestCase +{ + /** + * Tests the lazy & once hash code computation behaviour of the binary type. + */ + public void testHashCodeComputation(){ + Binary binary = new Binary(new byte[]{1,2,3,4,5,6,7,6,3,3}); + assertSame(binary.state,binary.hashCodeNotYetComputed); + + int firstResult = binary.hashCode(); + assertSame(binary.state,binary.hashCodeAlreadyComputed); + + int secondResult = binary.hashCode(); + assertSame(binary.state,binary.hashCodeAlreadyComputed); + assertEquals(firstResult,secondResult); + } + + /** + * Tests the equals() method of the binary class. + * Two binary must be equals only if they contain the same array (that is, two arrays with the same size & content) + */ + public void testIdentity() { + Binary binary = new Binary(new byte[]{1,2,3,4,5,6,7,6,3,3}); + Binary theSame= new Binary(new byte[]{1,2,3,4,5,6,7,6,3,3}); + Binary aDifferentOne = new Binary(new byte[]{4,2,3,3,4,4,5,3,3,2}); + + assertTrue(binary.equals(theSame)); + assertFalse(binary.equals(aDifferentOne)); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java new file mode 100644 index 0000000000..805c039a6f --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java @@ -0,0 +1,241 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.domain.services; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import junit.framework.TestCase; + +import org.apache.qpid.api.Message; +import org.apache.qpid.management.TestConstants; +import org.apache.qpid.management.domain.handler.base.IMessageHandler; +import org.apache.qpid.management.domain.model.DomainModel; +import org.apache.qpid.nclient.util.ByteBufferMessage; +import org.apache.qpid.transport.codec.Decoder; + +/** + * Test case for Broker Message Listener. + * + * @author Andrea Gazzarini + */ +public class BrokerMessageListenerTest extends TestCase +{ + // An empty message handler user for test. + private IMessageHandler _emptyMessageHandler = new IMessageHandler() + { + public void process (Decoder decoder, int sequenceNumber) + { + } + public void setDomainModel (DomainModel domainModel) + { + } + }; + + // Another empty message handler user for test. + private IMessageHandler _anotherEmptyMessageHandler = new IMessageHandler() + { + public void process (Decoder decoder, int sequenceNumber) + { + } + public void setDomainModel (DomainModel domainModel) + { + } + }; + + private Map _handlers = new HashMap(); + private BrokerMessageListener _listener; + private final char opcode1 = 'x'; + private final char opcode2 = 'y'; + + + @Override + protected void setUp () throws Exception + { + DomainModel domainModel = new DomainModel(TestConstants.BROKER_ID); + _listener = new BrokerMessageListener(domainModel); + + _handlers.put(opcode1, _emptyMessageHandler); + _handlers.put(opcode2, _anotherEmptyMessageHandler); + } + + /** + * Tests the installation of message handlers on a broker message listener. + * + *
precondition : no message handler has been installed on message listener. + *
postcondition : two message handlers are installed on message listener. + */ + public void testSetHandlersOK() + { + assertTrue( + "No handler has yet been installed so how is it possible that the handlers map is not empty?", + _listener._handlers.isEmpty()); + + _listener.setHandlers(_handlers); + + assertEquals("Now we should have two handlers configured.",2,_listener._handlers.size()); + assertSame(_listener._handlers.get(opcode1),_emptyMessageHandler); + assertSame(_listener._handlers.get(opcode2),_anotherEmptyMessageHandler); + } + + /** + * Tests the installation of message handlers on a broker message listener. + * Specifically it tries to install three message handlers and one of them is throwing an exception at installation time. + * + *
precondition : no message handler has been installed on message listener. + *
postcondition : two message handlers are installed on message listener. (the one that thrown exception has been + * discarded). + */ + public void testSetHandlerOK() + { + IMessageHandler wrongMessageHandler = new IMessageHandler() + { + + public void process (Decoder decoder, int sequenceNumber) + { + } + + public void setDomainModel (DomainModel domainModel) + { + throw new RuntimeException(); + } + }; + + char opcodeForWrongHandler = 'k'; + + assertTrue( + "No handler has yet been installed so how is it possible that the handlers map is not empty?", + _listener._handlers.isEmpty()); + + _handlers.put(opcodeForWrongHandler,wrongMessageHandler); + + _listener.setHandlers(_handlers); + + assertEquals("Now we should have two handlers configured.",2,_listener._handlers.size()); + assertSame(_listener._handlers.get(opcode1),_emptyMessageHandler); + assertSame(_listener._handlers.get(opcode2),_anotherEmptyMessageHandler); + assertNull(_listener._handlers.get(opcodeForWrongHandler)); + } + + /** + * Tests the execution of the onMessage() method when a message with a bad magic number is received. + * + *
precondition : a message with a bad magic number is received. + *
postcondition : the processing of the incoming message is skipped and therefore no handler will be called. + */ + public void testOnMessageKO_withBadMagicNumber() throws IOException + { + IMessageHandler neverCallMe = new IMessageHandler() + { + + public void process (Decoder decoder, int sequenceNumber) + { + fail("This test shouldn't never arrive at this point..."); + } + + public void setDomainModel (DomainModel domainModel) + { + } + }; + + String opcodeForNeverCallMeHandler = "w"; + + _handlers.put('w',neverCallMe); + _listener.setHandlers(_handlers); + + Message message = new ByteBufferMessage(); + message.appendData( ("AMG"+opcodeForNeverCallMeHandler).getBytes()); + + _listener.onMessage(message); + } + + /** + * Tests the execution of the onMessage() method when the incoming message is a compound message. + * + *
precondition : the incoming message is a compound message. + *
postcondition : each tokenized message is forwarded to the appropriate handler. + */ + public void testOnMessageOK_WithCompoundMessage() throws Exception + { + final Map handlersMap = new HashMap(); + char [] opcodes = {'a','b','c','d','e'}; + + class MockMessageHandler implements IMessageHandler + { + private final char _opcode; + + public MockMessageHandler(char opcode) + { + this._opcode = opcode; + } + + public void process (Decoder decoder, int sequenceNumber) + { + handlersMap.remove(_opcode); + } + + public void setDomainModel (DomainModel domainModel) + { + // Do nothing here. It's just a mock handler. + } + }; + + for (char opcode : opcodes) + { + handlersMap.put(opcode, new MockMessageHandler(opcode)); + } + + // Removes previously injected handlers (i.e. x & y) + _listener._handlers.clear(); + _listener.setHandlers(handlersMap); + + Message compoundMessage = createCompoundMessage(opcodes); + _listener.onMessage(compoundMessage); + + assertTrue(handlersMap.isEmpty()); + } + + // Creates a (non valid) compound message. + private Message createCompoundMessage(char[] opcodes) throws IOException { + byte [] compoundMessageData = new byte [12 * opcodes.length]; + Random randomizer = new Random(); + int position = 0; + + for (char opcode : opcodes) { + System.arraycopy(MessageTokenizer.MAGIC_NUMBER_BYTES, 0, compoundMessageData, position, MessageTokenizer.MAGIC_NUMBER_BYTES.length); + position+=MessageTokenizer.MAGIC_NUMBER_BYTES.length; + + compoundMessageData[position++] = (byte)opcode; + + for (int c = 4; c < 12; c++) + { + byte aByte = (byte)randomizer.nextInt(127); + compoundMessageData[position++] = aByte; + } + } + + Message compoundMessage = new ByteBufferMessage(); + compoundMessage.appendData(compoundMessageData); + return compoundMessage; + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java new file mode 100644 index 0000000000..55b8b17f9d --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/domain/services/MessageTokenizerTest.java @@ -0,0 +1,140 @@ +/* +* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.management.domain.services; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.*; + +import junit.framework.TestCase; + +import org.apache.qpid.api.Message; +import org.apache.qpid.nclient.util.ByteBufferMessage; +import org.apache.qpid.transport.codec.BBDecoder; + +/** + * Tests case for messaeg tokenizer. + * + * @author Andrea Gazzarini + */ +public class MessageTokenizerTest extends TestCase { + + /** + * Tests the execution of the message tokenizer when the given message is not a valid AMQP message. + * + *
precondition : the incoming message is not a valid AMQP message. + *
postcondition : no exception is thrown and there will be exactly one token with the given message. + */ + public void testOK_WithNoMessage() throws IOException{ + byte [] noMessage = {2,10,120,23,23,23,4,10,11,12,2,1,3,-22}; + + Message multiMessage = new ByteBufferMessage(); + multiMessage.appendData(noMessage); + MessageTokenizer tokenizer = new MessageTokenizer(multiMessage); + + assertEquals(1, tokenizer.countTokens()); + assertEquals(tokenizer.nextElement(),noMessage); + assertFalse(tokenizer.hasMoreElements()); + } + + /** + * Tests the execution of the message tokenizer when the given message contains only one message. + * + *
precondition : the incoming message contains only one message. + *
postcondition : no exception is thrown and there will be exactly one token with the given message. + */ + public void testOK_WithOneMessage() throws IOException{ + byte [] oneEncodedMessage = {'A','M','2',23,23,23,4,10,11,12,2,1,3,-22}; + + Message multiMessage = new ByteBufferMessage(); + multiMessage.appendData(oneEncodedMessage); + MessageTokenizer tokenizer = new MessageTokenizer(multiMessage); + + assertEquals(1, tokenizer.countTokens()); + assertEquals(tokenizer.nextElement(),oneEncodedMessage); + assertFalse(tokenizer.hasMoreElements()); + } + + /** + * Tests the execution of the message tokenizer when the given message contains a random number of messages. + * + *
precondition : the incoming message contains a random number of messages. + *
postcondition : no exception is thrown and each built token is a valid message starting with right header. + */ + public void testOK_WithRandomNUmberOfMessages() throws IOException{ + Random randomizer = new Random(); + + int howManyLoops = randomizer.nextInt(10000); + howManyLoops = (howManyLoops == 0) ? 10 : howManyLoops; + byte [] compoundMessageData = new byte [12 * howManyLoops]; + + List messages = new ArrayList(howManyLoops); + + int position = 0; + for (int i = 0; i < howManyLoops; i++) + { + byte [] message = new byte[12]; + System.arraycopy(MessageTokenizer.MAGIC_NUMBER_BYTES, 0, compoundMessageData, position, MessageTokenizer.MAGIC_NUMBER_BYTES.length); + System.arraycopy(MessageTokenizer.MAGIC_NUMBER_BYTES, 0, message, 0, MessageTokenizer.MAGIC_NUMBER_BYTES.length); + position+=MessageTokenizer.MAGIC_NUMBER_BYTES.length; + + for (int c = 3; c < 12; c++) + { + byte aByte = (byte)randomizer.nextInt(127); + aByte = (aByte == 77) ? (byte)c : aByte; + compoundMessageData[position++] = aByte; + message[c] = aByte; + } + messages.add(message); + } + + Message multiMessage = new ByteBufferMessage(); + multiMessage.appendData(compoundMessageData); + MessageTokenizer tokenizer = new MessageTokenizer(multiMessage); + + int howManyTokens = tokenizer.countTokens(); + assertEquals(howManyLoops, howManyTokens); + + int index = 0; + while (tokenizer.hasMoreElements()) + { + assertEquals(tokenizer.nextElement(),messages.get(index++)); + } + + assertEquals((index),howManyTokens); + } + + /** + * Internal method used for comparison of two messages. + * + * @param message the token message just built by the tokenizer. + * @param expected the expected result. + */ + private void assertEquals(Message message, byte [] expected) throws IOException + { + ByteBuffer messageContent = message.readData(); + BBDecoder decoder = new BBDecoder(); + decoder.init(messageContent); + byte [] content = decoder.readReaminingBytes(); + assertTrue(Arrays.equals(content, expected)); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java new file mode 100644 index 0000000000..900d14c72e --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/BaseWsDmAdapterTestCase.java @@ -0,0 +1,143 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.lang.management.ManagementFactory; +import java.net.URI; +import java.util.UUID; + +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import junit.framework.TestCase; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.remote.WsResourceClient; +import org.apache.muse.ws.resource.sg.remote.ServiceGroupClient; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.TestConstants; + +/** + * Test case for WS-Resource lifecycle management. + * + * @author Andrea Gazzarini + */ +public abstract class BaseWsDmAdapterTestCase extends TestCase implements TestConstants{ + + protected MBeanServer _managementServer; + protected ObjectName _resourceObjectName; + + protected WsResourceClient _resourceClient; + protected MBeanInfo _mbeanInfo; + + /** + * Set up fixture for this test case. + * + * @throws Exception when the test case intialization fails. + */ + protected void setUp() throws Exception + { + _managementServer = ManagementFactory.getPlatformMBeanServer(); + + ServiceGroupClient serviceGroup = getServiceGroupClient(); + WsResourceClient [] members = serviceGroup.getMembers(); + + assertEquals( + "No resource has been yet created so how is " + + "it possible that service group children list is not empty?", + 0, + members.length); + + _managementServer.invoke( + Names.QPID_EMULATOR_OBJECT_NAME, + "createQueue", + new Object[]{_resourceObjectName = createResourceName()}, + new String[]{ObjectName.class.getName()}); + + members = serviceGroup.getMembers(); + assertEquals( + "One resource has just been created so " + + "I expect to find it on service group children list...", + 1, + members.length); + + _resourceClient = members[0]; + _mbeanInfo = _managementServer.getMBeanInfo(_resourceObjectName); + } + + /** + * Shutdown procedure for this test case. + * + * @throws Exception when either the server or some resource fails to shutdown. + */ + @Override + protected void tearDown() throws Exception + { + ServiceGroupClient serviceGroup = getServiceGroupClient(); + WsResourceClient [] members = serviceGroup.getMembers(); + + _managementServer.invoke( + Names.QPID_EMULATOR_OBJECT_NAME, + "unregister", + new Object[]{_resourceObjectName}, + new String[]{ObjectName.class.getName()}); + + members = serviceGroup.getMembers(); + + assertEquals( + "No resource has been yet created so how is it possible that service group children list is not empty?", + 0, + members.length); + } + + /** + * Creates a service group client reference. + * + * @return a service group client reference. + */ + private ServiceGroupClient getServiceGroupClient() + { + URI address = URI.create( + Protocol.DEFAULT_ENDPOINT_URI.replaceFirst("8080",System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME))); + return new ServiceGroupClient(new EndpointReference(address)); + } + + /** + * In order to test the behaviour of the WS-DM adapter, at + * least one resource must be created. This is the method that + * returns the name (ObjectName on JMX side, Resource-ID on WSDM side) + * of that resource + * + * @return the name of the MBean instance that will be created. + * @throws Exception when the name if malformed. Practically never. + */ + private ObjectName createResourceName() throws Exception + { + return new ObjectName( + "Q-MAN:objectId="+UUID.randomUUID()+ + ", brokerID="+UUID.randomUUID()+ + ",class=queue"+ + ",package=org.apache.qpid"+ + ",name="+System.currentTimeMillis()); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java new file mode 100644 index 0000000000..615d744546 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/EnhancedReflectionProxyHandler.java @@ -0,0 +1,72 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer; +import org.w3c.dom.Element; + +/** + * Custom implementation of Muse ReflectionProxyHandler + * that uses a base64 serializer for byte arrays. + * Note that this proxy handler is only needed for tests because it provides + * client side Base64 serializer capability. + * In a concrete scenario we don't mind what instrument the client is using in order to + * propertly serialize byte arrays. + * + * @author Andrea Gazzarini + */ +public class EnhancedReflectionProxyHandler extends ReflectionProxyHandler +{ + @Override + protected Element serialize(Object obj, QName qname) throws SoapFault + { + if (obj == null) + { + return XmlUtils.createElement(qname); + } + + if (obj.getClass() == byte[].class) + { + return new ByteArraySerializer().toXML(obj, qname); + } else + { + return super.serialize(obj, qname); + } + } + + @SuppressWarnings("unchecked") + @Override + protected Object deserialize(Element xml, Class theClass) throws SoapFault + { + if (theClass == byte[].class) + { + return new ByteArraySerializer().fromXML(xml); + } else + { + return super.deserialize(xml, theClass); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java new file mode 100644 index 0000000000..d59e7a39e5 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetMultipleResourcePropertiesTestCase.java @@ -0,0 +1,125 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.util.Date; +import java.util.UUID; + +import javax.management.MBeanAttributeInfo; +import javax.xml.namespace.QName; + +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.resource.WsrfConstants; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +/** + * Test case for Web Service Resource Properties interfaces. + * Those interfaces are defined on http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-os.pdf + * (Web Services Resource Properties 1.2 - (WS-ResourceProperties). + * For a better explanation see chapter 5 of the specification above. + * + * @author Andrea Gazzarini + */ +public class GetMultipleResourcePropertiesTestCase extends BaseWsDmAdapterTestCase +{ + /** + * Tests the GetMultipleResourceProperties interface when the request contains + * an unknwon target resource. + * + *
precondition : the GetMultipleResourceProperties request contains an unknwon resource. + *
postcondition : a SoapFault is thrown and the corresponding detail contains an + * UnknownResourceFault element. + */ + public void testGetMultipleResourcePropertiesKO_WithUnknownResourceFault() throws Exception + { + try + { + _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME); + _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal"); + + _resourceClient.getMultipleResourceProperties(new QName[]{}); + } catch(SoapFault expected) + { + assertEquals( + WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(), + expected.getDetail().getLocalName()); + } + } + + /** + * Test the WS-RP GetResourceProperties interface of the WS-DM adapter. + * + *
precondition : a ws resource exists and is registered. + *
postcondition : Properties are correctly returned according to WSRP interface and they (their value) + * are matching with corresponding MBean properties. + */ + public void testGetMultipleResourcePropertiesOK() throws Exception + { + MBeanAttributeInfo [] attributesMetadata = _mbeanInfo.getAttributes(); + QName[] names = new QName[attributesMetadata.length]; + + int index = 0; + for (MBeanAttributeInfo attributeMetadata : _mbeanInfo.getAttributes()) + { + QName qname = new QName(Names.NAMESPACE_URI,attributeMetadata.getName(),Names.PREFIX); + names[index++] = qname; + } + + Element[] properties =_resourceClient.getMultipleResourceProperties(names); + for (Element element : properties) + { + String name = element.getLocalName(); + Object value = _managementServer.getAttribute(_resourceObjectName, name); + if ("Name".equals(name)) + { + assertEquals( + value, + element.getTextContent()); + } else if ("Durable".equals(name)) + { + assertEquals( + value, + Boolean.valueOf(element.getTextContent())); + } else if ("ExpireTime".equals(name)) + { + assertEquals( + value, + new Date(Long.valueOf(element.getTextContent()))); + } else if ("MsgTotalEnqueues".equals(name)) + { + assertEquals( + value, + Long.valueOf(element.getTextContent())); + } else if ("ConsumerCount".equals(name)) + { + assertEquals( + value, + Integer.valueOf(element.getTextContent())); + }else if ("VhostRef".equals(name)) + { + assertEquals( + value, + UUID.fromString(element.getTextContent())); + } + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java new file mode 100644 index 0000000000..e18e928cf4 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertiesTestCase.java @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.lang.reflect.Array; + +import javax.management.MBeanAttributeInfo; +import javax.xml.namespace.QName; + +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.resource.WsrfConstants; +import org.apache.qpid.management.Names; + +/** + * Test case for Web Service Resource Properties interfaces. + * Those interfaces are defined on http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-os.pdf + * (Web Services Resource Properties 1.2 - (WS-ResourceProperties). + * For a better explanation see chapter 5 of the specification above. + * + * @author Andrea Gazzarini + */ +public class GetResourcePropertiesTestCase extends BaseWsDmAdapterTestCase +{ + + /** + * Test the WS-RP GetResourceProperty interface of the WS-DM adapter. + * + *
precondition : a ws resource exists and is registered. + *
postcondition : property values coming from WS-DM resource are the same of the JMX interface. + */ + public void testGetResourcePropertiesOK() throws Exception + { + MBeanAttributeInfo [] attributesMetadata = _mbeanInfo.getAttributes(); + for (MBeanAttributeInfo attributeMetadata : attributesMetadata) + { + String name = attributeMetadata.getName(); + Object propertyValues = _resourceClient.getPropertyAsObject( + new QName( + Names.NAMESPACE_URI, + name, + Names.PREFIX), + Class.forName(attributeMetadata.getType())); + + int length = Array.getLength(propertyValues); + if (length != 0) + { + Object propertyValue = Array.get(propertyValues, 0); + + assertEquals( + "Comparison failed for property "+name, + _managementServer.getAttribute(_resourceObjectName,name), + propertyValue); + } else { + assertNull( + String.format( + "\"%s\" property value shouldn't be null. Its value is %s", + name, + _managementServer.getAttribute(_resourceObjectName,name)), + _managementServer.getAttribute(_resourceObjectName,name)); + } + } + } + + /** + * Tests the GetMultipleResourceProperties interface when the request contains + * an unknwon target resource. + * + *
precondition : the GetMultipleResourceProperties request contains an unknwon resource. + *
postcondition : a SoapFault is thrown and the corresponding detail contains an + * UnknownResourceFault element. + */ + public void testGetResourcePropertiesKO_WithUnknownResourceFault() throws Exception + { + try + { + _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME); + _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal"); + + _resourceClient.getResourceProperty(new QName("a","b","c")); + } catch(SoapFault expected) + { + assertEquals( + WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(), + expected.getDetail().getLocalName()); + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java new file mode 100644 index 0000000000..862115f841 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/GetResourcePropertyDocumentTestCase.java @@ -0,0 +1,134 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import javax.xml.namespace.QName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.resource.WsrfConstants; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +/** + * Test case for Web Service Resource Properties interfaces. + * Those interfaces are defined on http://docs.oasis-open.org/wsrf/wsrf-ws_resource_properties-1.2-spec-os.pdf + * (Web Services Resource Properties 1.2 - (WS-ResourceProperties). + * For a better explanation see chapter 5 of the specification above. + * + * @author Andrea Gazzarini + */ +public class GetResourcePropertyDocumentTestCase extends BaseWsDmAdapterTestCase +{ + /** + * Tests the GetResourcePropertyDocument interface when the request contains + * an unknwon target resource. + * + *
precondition : the GetResourcePropertyDocument contains an unknwon resource. + *
postcondition : a SoapFault is thrown and the corresponding detail contains an + * UnknownResourceFault element. + */ + public void testGetResourcePropertyDocumentKO_WithUnknownResourceFault() throws Exception + { + try + { + _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME); + _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal"); + _resourceClient.setTrace(true); + + _resourceClient.getResourcePropertyDocument(); + } catch(SoapFault expected) + { + assertEquals( + WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(), + expected.getDetail().getLocalName()); + } + } + + /** + * Tests the WS-RP PutResourcePropertyDocument interface of the WS-DM adapter. + * + *
precondition : a ws resource exists and is registered. + *
postcondition : A read / write property is correctly set according to WSRP interface. + */ + public void testGetAndPutResourcePropertyDocumentOK() throws Exception + { + String expectedMgmtPubIntervalValue = "4321"; + String propertyName = "MgmtPubInterval"; + + Element propertiesDocument = _resourceClient.getResourcePropertyDocument(); + Element [] properties = XmlUtils.getAllElements(propertiesDocument); + + for (Element element : properties) + { + if (propertyName.equals(element.getLocalName())) { + element.setTextContent(expectedMgmtPubIntervalValue); + } else { + propertiesDocument.removeChild(element); + } + } + + _resourceClient.putResourcePropertyDocument(propertiesDocument); + + Element newProperties = _resourceClient.getResourcePropertyDocument(); + + Element mgmtPubInterval = XmlUtils.getElement( + newProperties, new QName( + Names.NAMESPACE_URI, + propertyName, + Names.PREFIX)); + + assertEquals(expectedMgmtPubIntervalValue,mgmtPubInterval.getTextContent()); + } + + /** + * Tests the WS-RP PutResourcePropertyDocument interface of the WS-DM adapter. + * Specifically it tries to update the value of a read-only property. + * + *
precondition : a ws resource exists, it is registered and has at least one read-only property. + *
postcondition : An exception is thrown indicating the failure. + */ + public void testGetAndPutResourcePropertyDocumentKO_WithReadOnlyProperty() throws Exception + { + String propertyName = "Name"; + + Element propertiesDocument = _resourceClient.getResourcePropertyDocument(); + Element [] properties = XmlUtils.getAllElements(propertiesDocument); + + for (Element element : properties) + { + if (propertyName.equals(element.getLocalName())) { + element.setTextContent("ThisIsTheNewValueOfNameProperty"); + } else { + propertiesDocument.removeChild(element); + } + } + + try + { + _resourceClient.putResourcePropertyDocument(propertiesDocument); + fail("It's not possible to update the value of a read-only property."); + } catch (SoapFault expected) + { + + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java new file mode 100644 index 0000000000..046f2226e6 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/MetadataExchangeInterfaceTestCase.java @@ -0,0 +1,169 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.metadata.WsxConstants; +import org.apache.muse.ws.resource.WsrfConstants; +import org.apache.muse.ws.resource.metadata.WsrmdConstants; +import org.apache.qpid.management.Names; +import org.w3c.dom.Element; + +/** + * Test case for QMan metadata exchange interface. + * + * @author Andrea Gazzarini + */ +public class MetadataExchangeInterfaceTestCase extends BaseWsDmAdapterTestCase +{ + /** + * Test the MetadataExchange interface when the corresponding + * request doesn't contain a dialect. According to WS-MetadataExchange specs this should be + * intended as a "give-me-all-metadata" for that resource. + * + *
precondition : the GetMetadata request doesn't contain a dialect. + *
postcondition : the whole metadata document is returned with all metadata . + * It will contain both WSDL and RMD. + */ + @SuppressWarnings("unchecked") + public void testGetMetadataOK_WithoutDialect() throws Exception + { + Element[] result = (Element[]) _resourceClient.invoke( + getProxyHandler(), + new Object[]{""}); + + assertEquals(2,result.length); + + Element rmdMetadataSection = result[0]; + Element wsdlMetadataSection = result[1]; + + Element rmd = XmlUtils.getFirstElement(rmdMetadataSection); + Element wsdl = XmlUtils.getFirstElement(wsdlMetadataSection); + + assertEquals("MetadataDescriptor",rmd.getLocalName()); + assertEquals("definitions",wsdl.getLocalName()); + } + + /** + * Test the MetadataExchange interface when the WSDL dialect is specified on the request. + * + *
precondition : the GetMetadata request contains WSDL dialect. + *
postcondition : the resource WSDL metadata document is returned. + */ + @SuppressWarnings("unchecked") + public void testGetMetadataOK_WithWSDLDialect() throws Exception + { + Element[] result = (Element[]) _resourceClient.invoke( + getProxyHandler(), + new Object[]{WsxConstants.WSDL_DIALECT}); + + assertEquals(1,result.length); + + Element wsdlMetadataSection = result[0]; + + Element wsdl = XmlUtils.getFirstElement(wsdlMetadataSection); + + assertEquals("definitions",wsdl.getLocalName()); + } + + /** + * Test the MetadataExchange interface when the RMD dialect is specified on the request. + * + *
precondition : the GetMetadata request contains RMD dialect. + *
postcondition : the RMD metadata document is returned. + */ + @SuppressWarnings("unchecked") + public void testGetMetadataOK_WithRMDDialect() throws Exception + { + Element[] result = (Element[]) _resourceClient.invoke( + getProxyHandler(), + new Object[]{WsrmdConstants.NAMESPACE_URI}); + + assertEquals(1,result.length); + + Element rmdMetadataSection = result[0]; + + Element wsdl = XmlUtils.getFirstElement(rmdMetadataSection); + + assertEquals("MetadataDescriptor",wsdl.getLocalName()); + } + + /** + * Test the MetadataExchange interface with an unknown metadata dialect. + * + *
precondition : the GetMetadata request contains an unknown dialect. + *
postcondition : the returned metadata section is empty. + */ + @SuppressWarnings("unchecked") + public void testGetMetadataKO_WithoutUnknownDialect() throws Exception + { + Element [] metadata = (Element[]) _resourceClient.invoke( + getProxyHandler(), + new Object[]{"HopeThisIsAnUnknownDialect"}); + + assertEquals(0,metadata.length); + } + + /** + * Test the MetadataExchange interface with an unknown metadata dialect. + * + *
precondition : the GetMetadata request contains an unknown dialect. + *
postcondition : the returned metadata section is empty. + */ + @SuppressWarnings("unchecked") + public void testGetMetadataKO_WithoutUnknownResourceFault() throws Exception + { + try + { + _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME); + _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal"); + + _resourceClient.invoke(getProxyHandler(), new Object[]{""}); + } catch(SoapFault expected) + { + assertEquals( + WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(), + expected.getDetail().getLocalName()); + } + } + + /** + * Returns a proxy handler used for working with metadata exchange + * interface. + * + * @return a metadata proxy handler. + */ + private ProxyHandler getProxyHandler() + { + ProxyHandler getMetadataHandler = new ReflectionProxyHandler(); + getMetadataHandler.setAction("http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata"); + getMetadataHandler.setRequestName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "GetMetadata", "wsx")); + getMetadataHandler.setRequestParameterNames(new QName[]{new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Dialect", "wsx")}); + getMetadataHandler.setResponseName(new QName("http://schemas.xmlsoap.org/ws/2004/09/mex", "Metadata", "wsx")); + getMetadataHandler.setReturnType(Element[].class); + return getMetadataHandler; + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java new file mode 100644 index 0000000000..afc4a62085 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/OperationInvocationInterfaceTestCase.java @@ -0,0 +1,580 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.proxy.ProxyHandler; +import org.apache.muse.core.proxy.ReflectionProxyHandler; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.wsdm.capabilities.Result; + +/** + * Test case for QMan operation invocation interface. + * + * @author Andrea Gazzarini + */ +public class OperationInvocationInterfaceTestCase extends BaseWsDmAdapterTestCase +{ + private Map _invocationHandlers = createInvocationHandlers(); + + /** + * Test operation invocation on WS-Resource. + * This method tests the exchange of a byte type array between requestor + * and service provider. + * + *
precondition : a WS-Resource exists and is registered and the requested + * operation is available on that. + *
postcondition : invocations are executed successfully, no exception is thrown + * and byte array are correctly returned. + */ + @SuppressWarnings("unchecked") + public void testOperationInvocationOK_withByteArray() throws Exception + { + byte [] expectedByteResult = {1,3,4,2,2,44,22,3,3,55,66}; + + Object result = _resourceClient.invoke( + _invocationHandlers.get("echoWithByteArray"), + new Object[]{expectedByteResult}); + + Method getOutputParameters = result.getClass().getMethod("getOutputParameters"); + + Map out = (Map) getOutputParameters.invoke(result); + + assertEquals("Output parameters must be 1.",1,out.size()); + assertArrayEquals(expectedByteResult, out.get(byte[].class.getName())); + } + + /** + * Test a simple operation invocation on a WS-Resource. + * This method tests a simple operation without any input and output parameters. + * + *
precondition : a ws resource exists and is registered and the requested operation + * is available on that. + *
postcondition : invocations are executed successfully an no exception is thrown. + */ + @SuppressWarnings("unchecked") + public void testSimpleOperationInvocationOK() throws Exception + { + Object result = _resourceClient.invoke( + _invocationHandlers.get("voidWithoutArguments"), + null); + + assertNotNull(result); + } + + /** + * Test a the invocation on a WS-Resource with a method that throws an exception.. + * + *
precondition : a ws resource exists and is registered and the requested + * operation is available on that. + *
postcondition : an exception is thrown by the requested method. + */ + @SuppressWarnings("unchecked") + public void testInvocationException_OK() throws Exception + { + try + { + _resourceClient.invoke( + _invocationHandlers.get("throwsException"), + null); + fail("The requested operation has thrown an exception so a Soap Fault is expected..."); + } catch(SoapFault expected) + { + } + } + + /** + * Test operation invocation on WS-Resource. + * This method tests the exchange of UUID type between requestor and service provider. + * + *
precondition : a WS-Resource exists and is registered and the requested operation + * is available on that. + *
postcondition : invocations are executed successfully, no exception is thrown + * and parameters are correctly returned. + */ + @SuppressWarnings("unchecked") + public void testOperationInvocationOK_withUUID() throws Exception + { + UUID expectedUuid = UUID.randomUUID(); + + Object result = _resourceClient.invoke( + _invocationHandlers.get("echoWithUUID"), + new Object[]{expectedUuid}); + + Method getOutputParameters = result.getClass().getMethod("getOutputParameters"); + + Map out = (Map) getOutputParameters.invoke(result); + + assertEquals("Output parameters must be 1.",1,out.size()); + assertEquals(expectedUuid, out.get("uuid")); + } + + /** + * Test operation invocation on WS-Resource. + * This method tests the exchange of Map type between requestor and service provider. + * For this test exchanged arrays contain : + * + *
precondition : a ws resource exists and is registered and the requested + * operation is available on that. + *
postcondition : invocations are executed successfully, no exception is + * thrown and parameters are correctly returned. + */ + @SuppressWarnings("unchecked") + public void testOperationInvocationOK_withMap() throws Exception + { + Map expectedMap = new HashMap(); + expectedMap.put("p1", new Long(1)); + expectedMap.put("p2", Boolean.TRUE); + expectedMap.put("p3", 1234d); + expectedMap.put("p4", 11.2f); + expectedMap.put("p5", 1272); + expectedMap.put("p6", (short)12); + expectedMap.put("p7", "aString"); + expectedMap.put("p8", "http://qpid.apache.org"); + expectedMap.put("p9", new Date(12383137128L)); + expectedMap.put("p10", new byte[]{1,2,2,3,3,4}); + + Object result = _resourceClient.invoke( + _invocationHandlers.get("echoWithMap"), + new Object[]{expectedMap}); + + Method getOutputParameters = result.getClass().getMethod("getOutputParameters"); + + Map out = (Map) ((Map) getOutputParameters.invoke(result)).get("map"); + + assertEquals("Output parameters must be 10.",10,out.size()); + assertEquals(expectedMap.get("p1"),out.get("p1")); + assertEquals(expectedMap.get("p2"),out.get("p2")); + assertEquals(expectedMap.get("p3"),out.get("p3")); + assertEquals(expectedMap.get("p4"),out.get("p4")); + assertEquals(expectedMap.get("p5"),out.get("p5")); + assertEquals(expectedMap.get("p6"),out.get("p6")); + assertEquals(expectedMap.get("p7"),out.get("p7")); + assertEquals(expectedMap.get("p8"),out.get("p8")); + assertEquals(expectedMap.get("p9"),out.get("p9")); + assertTrue( Arrays.equals((byte[])expectedMap.get("p10"),(byte[])out.get("p10"))); + } + + /** + * Test operation invocation on WS-Resource. + * This method tests the exchange of simple types between requestor and + * service provider. + * + * With simple types we mean : + * + *
    + *
  • java.lang.Long / long (xsd:long) + *
  • java.lang.Integer / int (xsd:int / xsd:integer) + *
  • java.lang.Double/ double (xsd:double) + *
  • java.lang.Float / float (xsd:float) + *
  • java.lang.Short / short (xsd:short) + *
  • java.lang.Boolean / boolean (xsd:boolean) + *
  • java.lang.String (xsd:string) + *
  • java.net.URI (xsd:anyURI) + *
  • java.util.Date(xsd:dateTime) + *
+ * + *
precondition : a ws resource exists and is registered and the requested operation is + * available on that. + *
postcondition : invocations are executed successfully, no exception is thrown and + * parameters are correctly returned. + */ + @SuppressWarnings("unchecked") + public void testOperationInvocationOK_withSimpleTypes() throws Exception + { + Long expectedLongResult = new Long(1373); + Boolean expectedBooleanResult = Boolean.TRUE; + Double expectedDoubleResult = new Double(12763.44); + Float expectedFloatResult = new Float(2727.233f); + Integer expectedIntegerResult = new Integer(28292); + Short expectedShortResult = new Short((short)227); + String expectedStringResult = "expectedStringResult"; + URI expectedUriResult = URI.create("http://qpid.apache.org/"); + Date expectedDateResult = new Date(); + + Object result = _resourceClient.invoke( + _invocationHandlers.get("echoWithSimpleTypes"), + new Object[]{ + expectedLongResult, + expectedBooleanResult, + expectedDoubleResult, + expectedFloatResult, + expectedIntegerResult, + expectedShortResult, + expectedStringResult, + expectedUriResult, + expectedDateResult}); + + Method getOutputParameters = result.getClass().getMethod("getOutputParameters"); + Map out = (Map) getOutputParameters.invoke(result); + + assertEquals("Output parameters must be 9.",9,out.size()); + assertTrue("Long output parameter not found on result object.",out.containsValue(expectedLongResult)); + assertTrue("Boolean output parameter not found on result object.",out.containsValue(expectedBooleanResult)); + assertTrue("Double output parameter not found on result object.",out.containsValue(expectedDoubleResult)); + assertTrue("Float output parameter not found on result object.",out.containsValue(expectedFloatResult)); + assertTrue("Integer output parameter not found on result object.",out.containsValue(expectedIntegerResult)); + assertTrue("Short output parameter not found on result object.",out.containsValue(expectedShortResult)); + assertTrue("String output parameter not found on result object.",out.containsValue(expectedStringResult)); + assertTrue("URI output parameter not found on result object.",out.containsValue(expectedUriResult)); + assertTrue("Date output parameter not found on result object.",out.containsValue(expectedDateResult)); + } + + /** + * Test operation invocation on WS-Resource. + * This method tests the exchange of arrays between requestor and service provider. + * For this test exchanged arrays contain : + * + *
    + *
  • java.lang.Long (xsd:long) + *
  • java.lang.Integer (xsd:int / xsd:integer) + *
  • java.lang.Double (xsd:double) + *
  • java.lang.Float (xsd:float) + *
  • java.lang.Short (xsd:short) + *
  • java.lang.Boolean (xsd:boolean) + *
  • java.lang.String (xsd:string) + *
  • java.net.URI (xsd:anyURI) + *
  • java.util.Date(xsd:dateTime) + *
+ * + *
precondition : a ws resource exists and is registered and the requested operation is available on that. + *
postcondition : invocations are executed successfully, no exception is thrown and parameters are correctly returned. + */ + @SuppressWarnings("unchecked") + public void testOperationInvocationOK_withWrapperArrays() throws Exception + { + Long [] expectedLongResult = {new Long(2),new Long(1),new Long(3),new Long(4)}; + Boolean [] expectedBooleanResult = { Boolean.TRUE,Boolean.FALSE,Boolean.FALSE}; + Double [] expectedDoubleResult = {12763.44d,2832.33d,2292.33d,22293.22d}; + Float [] expectedFloatResult = {2727.233f,1f,2f,4f,5.4f,33.2f}; + Integer [] expectedIntegerResult = {1,2,3,4,55,66,77,88,99}; + Short [] expectedShortResult = {(short)227,(short)23,(short)9}; + String [] expectedStringResult = {"s1","s2","s333","s4"}; + URI [] expectedUriResult = { + URI.create("http://qpid.apache.org/"), + URI.create("http://www.apache.org"), + URI.create("http://projects.apache.org")}; + + Date [] expectedDateResult = { + new Date(), + new Date(38211897), + new Date(903820382)}; + + Object result = _resourceClient.invoke( + _invocationHandlers.get("echoWithArrays"), + new Object[]{ + expectedLongResult, + expectedBooleanResult, + expectedDoubleResult, + expectedFloatResult, + expectedIntegerResult, + expectedShortResult, + expectedStringResult, + expectedUriResult, + expectedDateResult}); + + Method getOutputParameters = result.getClass().getMethod("getOutputParameters"); + Map out = (Map) getOutputParameters.invoke(result); + + assertEquals("Output parameters must be 9.",9,out.size()); + assertTrue("Long array doesn't match.",Arrays.equals(expectedLongResult, (Long[])out.get(Long.class.getName()))); + assertTrue("Boolean array doesn't match.",Arrays.equals(expectedBooleanResult, (Boolean[])out.get(Boolean.class.getName()))); + assertTrue("Double array doesn't match.",Arrays.equals(expectedDoubleResult, (Double[])out.get(Double.class.getName()))); + assertTrue("Float array doesn't match.",Arrays.equals(expectedFloatResult, (Float[])out.get(Float.class.getName()))); + assertTrue("Integer array doesn't match.", Arrays.equals(expectedIntegerResult, (Integer[])out.get(Integer.class.getName()))); + assertTrue("Short array doesn't match.",Arrays.equals(expectedShortResult, (Short[])out.get(Short.class.getName()))); + assertTrue("String array doesn't match.",Arrays.equals(expectedStringResult, (String[])out.get(String.class.getName()))); + assertTrue("URI array doesn't match.",Arrays.equals(expectedUriResult, (URI[])out.get(URI.class.getName()))); + assertTrue("Date array doesn't match.",Arrays.equals(expectedDateResult, (Date[])out.get(Date.class.getName()))); + } + + /** + * Test operation invocation on WS-Resource. + * This method tests the exchange of primitive type arrays between requestor and service provider. + * NOte that even the sent array contain primtiive type QMan deals only with objects so in the result + * object you will find the corresponding wrapper types. + * + * For this test exchanged arrays contain : + * + *
    + *
  • java.lang.Long / long (xsd:long) + *
  • java.lang.Integer / int (xsd:int / xsd:integer) + *
  • java.lang.Double/ double (xsd:double) + *
  • java.lang.Float / float (xsd:float) + *
  • java.lang.Short / short (xsd:short) + *
  • java.lang.Boolean / boolean (xsd:boolean) + *
+ * + *
precondition : a ws resource exists and is registered and the requested operation is available on that. + *
postcondition : invocations are executed successfully, no exception is thrown and parameters are correctly returned. + */ + @SuppressWarnings("unchecked") + public void testOperationInvocationOK_withPrimitiveArrays() throws Exception + { + long [] expectedLongResult = {1L,2L,3L,4L}; + boolean [] expectedBooleanResult = { true,false,false}; + double [] expectedDoubleResult = {12763.44d,2832.33d,2292.33d,22293.22d}; + float [] expectedFloatResult = {2727.233f,1f,2f,4f,5.4f,33.2f}; + int [] expectedIntegerResult = {1,2,3,4,55,66,77,88,99}; + short [] expectedShortResult = {(short)227,(short)23,(short)9}; + + Object result = _resourceClient.invoke( + _invocationHandlers.get("echoWithSimpleTypeArrays"), + new Object[]{ + expectedLongResult, + expectedBooleanResult, + expectedDoubleResult, + expectedFloatResult, + expectedIntegerResult, + expectedShortResult}); + + Method getOutputParameters = result.getClass().getMethod("getOutputParameters"); + Map out = (Map) getOutputParameters.invoke(result); + + assertEquals("Output parameters must be 6.",6,out.size()); + assertArrayEquals(expectedLongResult, out.get(long.class.getName())); + assertArrayEquals(expectedBooleanResult, out.get(boolean.class.getName())); + assertArrayEquals(expectedDoubleResult, out.get(double.class.getName())); + assertArrayEquals(expectedFloatResult, out.get(float.class.getName())); + assertArrayEquals(expectedIntegerResult, out.get(int.class.getName())); + assertArrayEquals(expectedShortResult, out.get(short.class.getName())); + } + + /** + * Internal method used for array comparison using reflection. + * + * @param expectedArray the expected array. + * @param resultArray the array that must match the expected one. + */ + private void assertArrayEquals(Object expectedArray, Object resultArray) + { + int expectedArrayLength = Array.getLength(expectedArray); + int resultArrayLength = Array.getLength(resultArray); + + assertEquals(expectedArrayLength,resultArrayLength); + + for (int index = 0; index < expectedArrayLength; index++) + { + Object expected = Array.get(expectedArray, index); + Object result = Array.get(resultArray, index); + + assertEquals(expected,result); + } + } + + private Map createInvocationHandlers() + { + Map handlers = new HashMap(); + + ProxyHandler handler = new ReflectionProxyHandler(); + handler.setAction(Names.NAMESPACE_URI+"/"+"voidWithoutArguments"); + handler.setRequestName( + new QName( + Names.NAMESPACE_URI, + "voidWithoutArgumentsRequest", + Names.PREFIX)); + handler.setRequestParameterNames(new QName[]{}); + handler.setResponseName( + new QName( + Names.NAMESPACE_URI, + "voidWithoutArgumentsResponse", + Names.PREFIX)); + handler.setReturnType(Result.class); + + ProxyHandler exceptionHandler = new ReflectionProxyHandler(); + exceptionHandler.setAction(Names.NAMESPACE_URI+"/"+"throwsException"); + exceptionHandler.setRequestName( + new QName( + Names.NAMESPACE_URI, + "throwsExceptionRequest", + Names.PREFIX)); + + exceptionHandler.setRequestParameterNames(new QName[]{}); + exceptionHandler.setResponseName( + new QName( + Names.NAMESPACE_URI, + "throwsExceptionResponse", + Names.PREFIX)); + + exceptionHandler.setReturnType(Result.class); + + ProxyHandler echoWithWrapperTypesHandler = new ReflectionProxyHandler(); + echoWithWrapperTypesHandler.setAction(Names.NAMESPACE_URI+"/"+"echoWithSimpleTypes"); + echoWithWrapperTypesHandler.setRequestName( + new QName( + Names.NAMESPACE_URI, + "echoWithSimpleTypesRequest", + Names.PREFIX)); + + echoWithWrapperTypesHandler.setRequestParameterNames(new QName[]{ + new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p2",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p3",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p4",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p5",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p6",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p7",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p8",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p9",Names.PREFIX), + }); + + echoWithWrapperTypesHandler.setResponseName( + new QName( + Names.NAMESPACE_URI, + "echoWithSimpleTypesResponse", + Names.PREFIX)); + + echoWithWrapperTypesHandler.setReturnType(Result.class); + + ProxyHandler echoWithArrayOfWrapperTypes = new ReflectionProxyHandler(); + echoWithArrayOfWrapperTypes.setAction(Names.NAMESPACE_URI+"/"+"echoWithArrays"); + echoWithArrayOfWrapperTypes.setRequestName( + new QName( + Names.NAMESPACE_URI, + "echoWithArraysRequest", + Names.PREFIX)); + + echoWithArrayOfWrapperTypes.setRequestParameterNames(new QName[]{ + new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p2",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p3",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p4",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p5",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p6",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p7",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p8",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p9",Names.PREFIX), + }); + + echoWithArrayOfWrapperTypes.setResponseName( + new QName( + Names.NAMESPACE_URI, + "echoWithArraysResponse", + Names.PREFIX)); + + echoWithArrayOfWrapperTypes.setReturnType(Result.class); + + ProxyHandler echoWithArrayOfPrimitiveTypes = new ReflectionProxyHandler(); + echoWithArrayOfPrimitiveTypes.setAction(Names.NAMESPACE_URI+"/"+"echoWithSimpleTypeArrays"); + echoWithArrayOfPrimitiveTypes.setRequestName( + new QName( + Names.NAMESPACE_URI, + "echoWithSimpleTypeArraysRequest", + Names.PREFIX)); + + echoWithArrayOfPrimitiveTypes.setRequestParameterNames(new QName[]{ + new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p2",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p3",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p4",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p5",Names.PREFIX), + new QName(Names.NAMESPACE_URI,"p6",Names.PREFIX)}); + + echoWithArrayOfPrimitiveTypes.setResponseName( + new QName( + Names.NAMESPACE_URI, + "echoWithSimpleTypeArraysResponse", + Names.PREFIX)); + + echoWithArrayOfPrimitiveTypes.setReturnType(Result.class); + + ProxyHandler echoWithByteArray = new EnhancedReflectionProxyHandler(); + echoWithByteArray.setAction(Names.NAMESPACE_URI+"/"+"echoWithByteArray"); + echoWithByteArray.setRequestName( + new QName( + Names.NAMESPACE_URI, + "echoWithByteArrayRequest", + Names.PREFIX)); + + echoWithByteArray.setRequestParameterNames( + new QName[]{ + new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX)}); + + echoWithByteArray.setResponseName( + new QName( + Names.NAMESPACE_URI, + "echoWithByteArrayResponse", + Names.PREFIX)); + + echoWithByteArray.setReturnType(Result.class); + + ProxyHandler echoWithUUID = new EnhancedReflectionProxyHandler(); + echoWithUUID.setAction(Names.NAMESPACE_URI+"/"+"echoWithUUID"); + echoWithUUID.setRequestName( + new QName( + Names.NAMESPACE_URI, + "echoWithUUIDRequest", + Names.PREFIX)); + + echoWithUUID.setRequestParameterNames( + new QName[]{ + new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX)}); + + echoWithUUID.setResponseName( + new QName( + Names.NAMESPACE_URI, + "echoWithUUIDResponse", + Names.PREFIX)); + + echoWithUUID.setReturnType(Result.class); + + ProxyHandler echoWithMap = new EnhancedReflectionProxyHandler(); + echoWithMap.setAction(Names.NAMESPACE_URI+"/"+"echoWithMap"); + echoWithMap.setRequestName( + new QName( + Names.NAMESPACE_URI, + "echoWithMapRequest", + Names.PREFIX)); + + echoWithMap.setRequestParameterNames( + new QName[]{ + new QName(Names.NAMESPACE_URI,"p1",Names.PREFIX)}); + + echoWithMap.setResponseName( + new QName( + Names.NAMESPACE_URI, + "echoWithMapResponse", + Names.PREFIX)); + + echoWithMap.setReturnType(Result.class); + + handlers.put("voidWithoutArguments",handler); + handlers.put("echoWithSimpleTypes",echoWithWrapperTypesHandler); + handlers.put("echoWithArrays",echoWithArrayOfWrapperTypes); + handlers.put("echoWithSimpleTypeArrays", echoWithArrayOfPrimitiveTypes); + handlers.put("echoWithByteArray", echoWithByteArray); + handlers.put("echoWithUUID", echoWithUUID); + handlers.put("echoWithMap", echoWithMap); + handlers.put("throwsException",exceptionHandler); + return handlers; + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java new file mode 100644 index 0000000000..6574c278ff --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/ServerThread.java @@ -0,0 +1,118 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.io.File; + +import org.apache.qpid.management.Names; +import org.mortbay.component.LifeCycle.Listener; +import org.mortbay.jetty.Connector; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.nio.SelectChannelConnector; +import org.mortbay.jetty.webapp.WebAppContext; +import org.mortbay.start.Monitor; + +/** + * Web Server startup thread. + * It is used on adapter test case in order to start the embedded + * web server as a separated thread. + * + * @author Andrea Gazzarini + */ +class ServerThread extends Thread +{ + private final Listener _lifecycleListener; + private Server _server; + + private SelectChannelConnector _connector; + + /** + * Builds a new server thread with the given lifecycle listener. + * + * @param listener the lifecycle listener. + */ + ServerThread(Listener listener) + { + this._lifecycleListener = listener; + } + + /** + * Starts the server. + */ + @Override + public void run() + { + try + { + Monitor.monitor(); + _server = new Server(); + _server.setStopAtShutdown(true); + + _connector=new SelectChannelConnector(); + _connector.setPort(Integer.parseInt(System.getProperty(Names.ADAPTER_PORT_PROPERTY_NAME))); + _connector.setHost(System.getProperty(Names.ADAPTER_HOST_PROPERTY_NAME)); + + + _server.setConnectors(new Connector[]{_connector}); + + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/qman"); + + // Additional web application descriptor containing test components. + webapp.setDefaultsDescriptor("/org/apache/qpid/management/wsdm/web.xml"); + + String webApplicationPath = System.getProperty("qman.war"); + File rootFolderPath = (webApplicationPath != null) ? new File(webApplicationPath) : new File("."); + + webapp.setWar(rootFolderPath.toURI().toURL().toExternalForm()); + webapp.addLifeCycleListener(_lifecycleListener); + _server.setHandler(webapp); + _server.start(); + System.setProperty(Names.ADAPTER_PORT_PROPERTY_NAME,String.valueOf( _connector.getLocalPort())); + _server.join(); + + } catch(Exception exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Shutdown the server. + * + * @throws Exception when a problem is encountered during shutdown. + */ + void shutdown() throws Exception + { + _server.stop(); + } + + /** + * Returns the port number where the server is running. + * + * @return the port number where the server is running. + */ + int getPort() + { + return _connector.getLocalPort(); + } + +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java new file mode 100644 index 0000000000..87f8905e01 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/SetResourcePropertiesTestCase.java @@ -0,0 +1,219 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.lang.reflect.Array; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.management.MBeanAttributeInfo; +import javax.xml.namespace.QName; + +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.muse.ws.resource.WsrfConstants; +import org.apache.qpid.management.Names; + +/** + * Test case for Set Resource Properties interfaces. + * + * @author Andrea Gazzarini + */ +public class SetResourcePropertiesTestCase extends BaseWsDmAdapterTestCase +{ + /** + * Test the WS-RP SetResourceProperty interface of the WS-DM adapter. + * + *
precondition : a WS-Resource exists and is registered. + *
postcondition : property values are correctly updated on the target WS-Resource.. + */ + public void testSetResourcePropertiesOK() throws Exception + { + Map sampleMap = new HashMap(); + sampleMap.put("Key1", "BLABALABLABALBAL"); + sampleMap.put("Key2", 182838484l); + sampleMap.put("Key3", -928376362); + sampleMap.put("Key4", 23762736276.33D); + sampleMap.put("Key4", 2327363.2F); + + Map sampleValues = new HashMap(); + sampleValues.put(String.class.getName(),"SAMPLE_STRING"); + sampleValues.put(UUID.class.getName(),UUID.randomUUID()); + sampleValues.put(Boolean.class.getName(),Boolean.FALSE); + sampleValues.put(Map.class.getName(),sampleMap); + sampleValues.put(Long.class.getName(),283781273L); + sampleValues.put(Integer.class.getName(),12727); + sampleValues.put(Short.class.getName(),new Short((short)22)); + sampleValues.put(Date.class.getName(),new Date()); + + MBeanAttributeInfo [] attributesMetadata = _mbeanInfo.getAttributes(); + boolean atLeastThereIsOneWritableProperty = false; + + for (MBeanAttributeInfo attributeMetadata : attributesMetadata) + { + String name = attributeMetadata.getName(); + + if (attributeMetadata.isWritable()) + { + atLeastThereIsOneWritableProperty = true; + Object sampleValue = sampleValues.get(attributeMetadata.getType()); + Object []values = new Object[]{sampleValue}; + + Object result = _managementServer.getAttribute(_resourceObjectName, name); + if (result == null) + { + _resourceClient.insertResourceProperty( + new QName( + Names.NAMESPACE_URI, + name, + Names.PREFIX), + values); + } else + { + _resourceClient.updateResourceProperty( + new QName( + Names.NAMESPACE_URI, + name, + Names.PREFIX), + values); + } + + Object propertyValues = _resourceClient.getPropertyAsObject( + new QName( + Names.NAMESPACE_URI, + name, + Names.PREFIX), + Class.forName(attributeMetadata.getType())); + int length = Array.getLength(propertyValues); + if (length != 0) + { + Object propertyValue = Array.get(propertyValues, 0); + + assertEquals( + "Comparison failed for property "+name, + sampleValue, + propertyValue); + } else { + assertNull( + String.format( + "\"%s\" property value shouldn't be null. Its value is %s", + name, + _managementServer.getAttribute(_resourceObjectName,name)), + sampleValue); + } + } + } + assertTrue( + "It's not possibile to run successfully this test case if " + + "the target WS-Resource has no at least one writable property", + atLeastThereIsOneWritableProperty); + } + + /** + * Test the WS-RP SetResourceProperty interface of the WS-DM adapter when the + * target property is null. + * According to WS-RP specs this operation is not allowed because in this case a SetResourceProperty with an "Insert" + * message should be sent in order to initialize the property. + * + *
precondition : a ws resource exists and is registered. The value of the target property is null. + *
postcondition : a Soap fault is received indicating the failuire. + */ + public void testSetResourcePropertiesKO() throws Exception + { + Object typePropertyValue = _managementServer.getAttribute(_resourceObjectName, "Type"); + assertNull(typePropertyValue); + + try + { + _resourceClient.updateResourceProperty( + new QName( + Names.NAMESPACE_URI, + "Type", + Names.PREFIX), + new Object[]{"sampleValue"}); + fail( + "If the property is null on the target ws resource, according " + + "to WS-RP specs, an update of its value is not possible."); + } catch(SoapFault expected) + { + + } + } + + /** + * Tests the SetResourceProperties (update) interface when the request contains + * an unknwon target resource. + * + *
precondition : the SetResourceProperties contains an unknwon resource. + *
postcondition : a SoapFault is thrown and the corresponding detail contains an + * UnknownResourceFault element. + */ + public void testUpdateResourcePropertiesKO_WithUnknownResourceFault() throws Exception + { + try + { + _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME); + _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal"); + + _resourceClient.updateResourceProperty( + new QName( + Names.NAMESPACE_URI, + "Type", + Names.PREFIX), + new Object[]{"sampleValue"}); + } catch(SoapFault expected) + { + assertEquals( + WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(), + expected.getDetail().getLocalName()); + } + } + + /** + * Tests the SetResourceProperties (insert) interface when the request contains + * an unknwon target resource. + * + *
precondition : the SetResourceProperties contains an unknwon resource. + *
postcondition : a SoapFault is thrown and the corresponding detail contains an + * UnknownResourceFault element. + */ + public void testInsertResourcePropertiesKO_WithUnknownResourceFault() throws Exception + { + try + { + _resourceClient.getEndpointReference().removeParameter(Names.RESOURCE_ID_QNAME); + _resourceClient.getEndpointReference().addParameter(Names.RESOURCE_ID_QNAME,"lablabalbal"); + + _resourceClient.insertResourceProperty( + new QName( + Names.NAMESPACE_URI, + "Type", + Names.PREFIX), + new Object[]{"sampleValue"}); + } catch(SoapFault expected) + { + assertEquals( + WsrfConstants.RESOURCE_UNKNOWN_QNAME.getLocalPart(), + expected.getDetail().getLocalName()); + } + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java new file mode 100644 index 0000000000..91c646467e --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WebApplicationLifeCycleListener.java @@ -0,0 +1,61 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import org.mortbay.component.LifeCycle; +import org.mortbay.component.LifeCycle.Listener; + +/** + * Adapter class used to provide an empty (base) implementation of + * Lifecycle listener interface. + * + * Adapter test case needs to be informed about the lifecycle of the + * deployed QMan application. Only when its deployment is completed the test + * case can run successfully. + * + * So, following the same logic of Swng event model, this is an adapter that provides + * empty implementation of the listener interface (see for example MouseAdapter + * for mouse events listener) + * + * @author Andrea Gazzarini + */ +public class WebApplicationLifeCycleListener implements Listener +{ + public void lifeCycleFailure(LifeCycle event, Throwable cause) + { + } + + public void lifeCycleStarted(LifeCycle event) + { + } + + public void lifeCycleStarting(LifeCycle event) + { + } + + public void lifeCycleStopped(LifeCycle event) + { + } + + public void lifeCycleStopping(LifeCycle event) + { + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java new file mode 100644 index 0000000000..f12288c91d --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/WsDmAdapterTest.java @@ -0,0 +1,156 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm; + +import java.io.IOException; +import java.net.ServerSocket; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; +import org.apache.qpid.management.wsdm.capabilities.Result; +import org.apache.qpid.management.wsdm.muse.serializer.DateSerializer; +import org.apache.qpid.management.wsdm.muse.serializer.InvocationResultSerializer; +import org.apache.qpid.management.wsdm.muse.serializer.MapSerializer; +import org.apache.qpid.management.wsdm.muse.serializer.ObjectSerializer; +import org.apache.qpid.management.wsdm.muse.serializer.UUIDSerializer; +import org.mortbay.component.LifeCycle; +import org.mortbay.component.LifeCycle.Listener; + +import junit.extensions.TestSetup; +import junit.framework.Test; +import junit.framework.TestSuite; + +public class WsDmAdapterTest +{ + + /** + * Test case wide set up. + * Provides Server startup & shutdown global procedure. + * + * @author Andrea Gazzarini + */ + private static class WsDmAdapterTestSetup extends TestSetup + { + private Object _serverMonitor = new Object(); + + Listener listener = new WebApplicationLifeCycleListener() + { + public void lifeCycleStarted(LifeCycle event) + { + synchronized (_serverMonitor) + { + _serverMonitor.notify(); + } + } + }; + + private ServerThread _server; + + /** + * Builds a new test setup with for the given test. + * + * @param test the decorated test. + */ + public WsDmAdapterTestSetup(Test test) + { + super(test); + } + + /** + * Starts up Web server. + * + * @throws Exception when the server startup fails. + */ + @Override + protected void setUp() throws Exception + { + SerializerRegistry.getInstance().registerSerializer(Object.class, new ObjectSerializer()); + SerializerRegistry.getInstance().registerSerializer(Date.class, new DateSerializer()); + SerializerRegistry.getInstance().registerSerializer(Map.class, new MapSerializer()); + SerializerRegistry.getInstance().registerSerializer(HashMap.class, new MapSerializer()); + SerializerRegistry.getInstance().registerSerializer(UUID.class, new UUIDSerializer()); + SerializerRegistry.getInstance().registerSerializer(Result.class, new InvocationResultSerializer()); + + System.setProperty( + Names.ADAPTER_HOST_PROPERTY_NAME, + Protocol.DEFAULT_QMAN_HOSTNAME); + + System.setProperty( + Names.ADAPTER_PORT_PROPERTY_NAME, + String.valueOf(getFreePort())); + + _server = new ServerThread(listener); + _server.start(); + + synchronized(_serverMonitor) { + _serverMonitor.wait(); + Thread.sleep(2000); + } + } + + @Override + protected void tearDown() throws Exception + { + _server.shutdown(); + } + }; + + /** + * Gets the test suite composition. + * + * @return the test suite composition. + */ + public static Test suite() + { + TestSuite suite = new TestSuite("Test suite for QMan WS-DM."); + /*suite.addTestSuite(MetadataExchangeInterfaceTestCase.class); + suite.addTestSuite(OperationInvocationInterfaceTestCase.class); + suite.addTestSuite(GetResourcePropertyDocumentTestCase.class); + suite.addTestSuite(SetResourcePropertiesTestCase.class); + suite.addTestSuite(GetMultipleResourcePropertiesTestCase.class); + suite.addTestSuite(GetResourcePropertiesTestCase.class); */ + return new WsDmAdapterTestSetup(suite); + } + + /** + * Finds a free port that will be used to run the embedded + * web server. + * + * @return a free port that will be used to run the + * embedded web server. + */ + private static int getFreePort() throws IOException { + ServerSocket server = null; + try + { + server = new ServerSocket(0); + return server.getLocalPort(); + } finally + { + server.close(); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java new file mode 100644 index 0000000000..68c9930ecd --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilderTest.java @@ -0,0 +1,335 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.management.ManagementFactory; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javassist.CtClass; +import javassist.CtMethod; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.xml.namespace.QName; + +import junit.framework.TestCase; + +import org.apache.qpid.management.domain.handler.impl.QpidDomainObject; +import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault; +import org.apache.qpid.management.wsdm.common.MethodInvocationFault; +import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault; +import org.apache.qpid.management.wsdm.common.QManFault; + +/** + * Test case for MBean capability builder. + * + * @author Andrea Gazzarini + */ +public class MBeanCapabilityBuilderTest extends TestCase +{ + + /** + * Management interface for an mbean that has no properties and no + * methods. + * + * @author Andrea Gazzarini + */ + public interface NoPropertiesNoMethodsMBean + { + } + + /** + * Implementation of the managenent interface described above. + * + * @author Andrea Gazzarini + */ + public class NoPropertiesNoMethods implements NoPropertiesNoMethodsMBean + { + } + + private MBeanCapabilityBuilder _builder; + private ObjectName _objectName; + + /** + * Set up fixture for this test case. + */ + protected void setUp() throws Exception + { + _builder = new MBeanCapabilityBuilder(); + _objectName = new ObjectName("Test:Name=aName,class=DomainObject"); + } + + /** + * Tests that state change that occcurs on the begin() method when the requested + * class has not been defined. + */ + public void testBegin_withClassNotYetDefined() throws Exception + { + _builder.begin(_objectName); + assertEquals(_builder._state,_builder._classNotAvailable); + } + + /** + * Tests that state change that occcurs on the begin() method when the requested + * class has not been defined. + */ + public void testBegin_withClassAlreadyDefined() throws Exception + { + _objectName = new ObjectName("Test:Name=aString,class=MBeanCapabilityBuilder"); + _builder.begin(_objectName); + + assertTrue(_builder._state instanceof DummyCapabilityBuilder); + assertSame(_builder._endAttributeHandler, _builder._noPropertyHasBeenDefined); + } + + /** + * Tests the generateGetter method(). + */ + public void testGenerateGetter() + { + String name ="MyProperty"; + String type = Long.class.getName(); + String expected = + "public "+ + type+ + " get"+ + name+ + "() throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault { return ("+ + type+ + ") getAttribute(\""+ + name+ + "\"); }"; + + String result = _builder.generateGetter(type, name,name); + assertEquals(expected,result); + } + + /** + * Tests the generateGetter method(). + */ + public void testGenerateSetter() + { + String name ="MyProperty"; + String type = Long.class.getName(); + String expected = + "public void setMyProperty("+ + type+ + " newValue) throws NoSuchAttributeFault,EntityInstanceNotFoundFault,QManFault { setAttribute(\""+ + name+ + "\", newValue); }"; + + String result = _builder.generateSetter(type, name,name); + assertEquals(expected,result); + } + + /** + * Tests buils of a capability that has no properties and methods + * + *
precondition : the incoming entity definition is empty (no properties and no methods) + *
postcondition : the capability class is built successfully and has no props and methods. + * The getPropertyNames returns an empty QName array. + */ + public void testOK_WithNoPropertiesNoMethods() throws Exception { + + ObjectName name = new ObjectName("Test:Name=NoPropertiesNoMethods"); + + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + server.registerMBean(new NoPropertiesNoMethods(), name); + + _builder.begin(name); + _builder.endAttributes(); + _builder.endOperations(); + Class capabilityClass = _builder.getCapabilityClass(); + + Field[] fields = capabilityClass.getDeclaredFields(); + Method [] methods = capabilityClass.getDeclaredMethods(); + + assertEquals(Arrays.toString(fields),0,fields.length); + assertEquals(Arrays.toString(methods),1,methods.length); + + Method getPropertyNames = methods[0]; + assertEquals("getPropertyNames",getPropertyNames.getName()); + + + MBeanCapability capability = capabilityClass.newInstance(); + QName [] properties = (QName[]) getPropertyNames.invoke(capability); + assertEquals(0,properties.length); + } + + /** + * Tests the whole execution of the builder. + */ + @SuppressWarnings("unchecked") + public void testBuildOK() throws Exception + { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + QpidDomainObject mbean = new QpidDomainObject(); + server.registerMBean(mbean, _objectName); + + _builder.begin(_objectName); + + CtClass definition = _builder._capabilityClassDefinition; + assertEquals( + MBeanCapability.class.getName(), + definition.getSuperclass().getName()); + + MBeanInfo metadata = server.getMBeanInfo(_objectName); + + for (MBeanAttributeInfo attribute : metadata.getAttributes()) + { + _builder.onAttribute(attribute); + checkAttribute(attribute, definition); + + assertSame( + _builder._endAttributeHandler, + _builder._atLeastThereIsOneProperty); + } + + for (MBeanOperationInfo operation : metadata.getOperations()) + { + _builder.onOperation(operation); + checkOperation(operation,definition); + } + + _builder.endAttributes(); + _builder.endOperations(); + + assertNotNull(_builder.getCapabilityClass()); + } + + /** + * Checks an operation / method after that it has been declared on + * capability definition. + * + * @param operation the (JMX) operation metadata. + * @param definition the capability class definition. + * @throws Exception when something goes wrong during introspection. + */ + private void checkOperation(MBeanOperationInfo operation, CtClass definition) throws Exception + { + CtMethod method = definition.getDeclaredMethod(operation.getName()); + assertNotNull(method); + + checkExceptionTypes( + method.getExceptionTypes(), + new String[]{ + QManFault.class.getName(), + EntityInstanceNotFoundFault.class.getName(), + MethodInvocationFault.class.getName()}); + + assertEquals(Result.class.getName(),method.getReturnType().getName()); + + CtClass [] parameterTypes = method.getParameterTypes(); + MBeanParameterInfo [] parameterMetadata = operation.getSignature(); + + assertEquals(parameterTypes.length, parameterMetadata.length); + for (int i = 0; i < parameterMetadata.length; i++) + { + assertEquals( + parameterTypes[i].getName(), + Class.forName(parameterMetadata[i].getType()).getCanonicalName()); + } + } + + /** + * Checks the exception types associated with a method. + * + * @param exceptionTypes the exception types actually thrown. + * @param expectedExceptionNames the expected exception types (as strings). + */ + private void checkExceptionTypes(CtClass [] exceptionTypes, String [] expectedExceptionNames) + { + List exceptionNames = new ArrayList(exceptionTypes.length); + for (CtClass exception : exceptionTypes) + { + exceptionNames.add(exception.getName()); + } + + for (String expectedExceptionName : expectedExceptionNames) + { + exceptionNames.remove(expectedExceptionName); + } + + assertTrue(exceptionNames.isEmpty()); + } + + /** + * Checks an attribute after that it has been declared on capability definition. + * + * @param attribute the (JMX) attribute metadata. + * @param definition the capability class definition. + * @throws Exception when something goes wrong during introspection. + */ + private void checkAttribute(MBeanAttributeInfo attribute, CtClass definition) throws Exception + { + String name = _builder.getNameForAccessors(attribute.getName()); + + String newPropertyDeclaration = + new StringBuilder("new QName(Names.NAMESPACE_URI, \"") + .append(attribute.getName()) + .append("\", Names.PREFIX),") + .toString(); + assertTrue(_builder._properties.indexOf(newPropertyDeclaration) != -1); + + if (attribute.isReadable()) + { + CtMethod getter = definition.getDeclaredMethod("get"+name); + assertNotNull(getter); + + checkExceptionTypes( + getter.getExceptionTypes(), + new String[]{ + QManFault.class.getName(), + NoSuchAttributeFault.class.getName(), + EntityInstanceNotFoundFault.class.getName()}); + + assertEquals(0,getter.getParameterTypes().length); + assertEquals(attribute.getType(),getter.getReturnType().getName()); + } + + if (attribute.isWritable()) + { + CtMethod setter = definition.getDeclaredMethod("set"+name); + assertNotNull(setter); + + checkExceptionTypes( + setter.getExceptionTypes(), + new String[]{ + QManFault.class.getName(), + NoSuchAttributeFault.class.getName(), + EntityInstanceNotFoundFault.class.getName()}); + + CtClass [] parameterTypes = setter.getParameterTypes(); + + assertEquals(1,parameterTypes.length); + assertEquals(attribute.getType(),parameterTypes[0].getName()); + assertEquals(void.class.getName(),setter.getReturnType().getName()); + } + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java new file mode 100644 index 0000000000..a9a6491209 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityTest.java @@ -0,0 +1,204 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.management.ManagementFactory; +import java.net.URI; + +import javax.management.ObjectName; + +import junit.framework.TestCase; + +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.muse.ws.resource.WsResource; +import org.apache.muse.ws.resource.impl.SimpleWsResource; +import org.apache.qpid.management.domain.handler.impl.QpidDomainObject; +import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault; +import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault; +import org.apache.qpid.management.wsdm.common.QManFault; + +/** + * Test case for MBeanCapability supertype layer.. + * + * @author Andrea Gazzarini + */ +public class MBeanCapabilityTest extends TestCase +{ + private final String _typeAttributeName = "Type"; + private final String _newTypeValue = "DomainObject"; + + private ObjectName _objectName; + private ObjectName _unknownObjectName; + + private MBeanCapability _capability; + + @Override + protected void setUp() throws Exception + { + _objectName = new ObjectName("Test:Name=aName"); + _unknownObjectName = new ObjectName("Test:Type=unknown"); + + _capability = new MBeanCapability(){ + @Override + public WsResource getWsResource() + { + return new SimpleWsResource(){ + @Override + public EndpointReference getEndpointReference() + { + return new EndpointReference(URI.create("http://qpid.apache.org/qman")); + } + }; + } + }; + _capability.setResourceObjectName(_objectName); + ManagementFactory.getPlatformMBeanServer().registerMBean(new QpidDomainObject(), _objectName); + } + + /** + * Tests the execution of the getAttribute() and setAttribute() method. + * + *
precondition : the mbean is registered and a _capability is associated with it. + *
postcondition : the set value of the requested attribute is correctly returned. + */ + public void testGetAndSetAttributeOK() throws Exception + { + Object name = _capability.getAttribute(_typeAttributeName); + assertNull("Name has an initial value of null so how is possibile that is not null?",name); + + _capability.setAttribute(_typeAttributeName,_newTypeValue); + + name = _capability.getAttribute(_typeAttributeName); + assertEquals("Now the name attribute must be set to \""+_newTypeValue+"\"",_newTypeValue,name); + } + + /** + * Tests the execution of the getAttribute() and setAttribte() methods when an unknown attribute is given.. + * + *
precondition : the mbean is registered, a _capability is associated with it and the requested attribute doesn't exist. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testNoSuchAttributeFault() throws Exception + { + // I suppose that we shouldn't have an attribute with this name... + String unknownAttribute = String.valueOf(System.currentTimeMillis()); + + try + { + _capability.getAttribute(unknownAttribute); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(NoSuchAttributeFault expected) + { + } + + try + { + _capability.setAttribute(unknownAttribute,null); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(NoSuchAttributeFault expected) + { + } + } + + /** + * Tests the execution of the setAttribute,getAttribute and invoke methods when the target mbean + * doesn't exists. + * + *
precondition : the object name associated with the capability is not pointing to an existent MBean. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testEntityInstanceNotFoundFault() throws Exception + { + _capability.setResourceObjectName(_unknownObjectName); + + try + { + _capability.getAttribute(_typeAttributeName); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(EntityInstanceNotFoundFault expected) + { + } + + try + { + _capability.setAttribute(_typeAttributeName,_newTypeValue); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(EntityInstanceNotFoundFault expected) + { + } + + try + { + _capability.invoke("operationName", null,null); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(EntityInstanceNotFoundFault expected) + { + } + } + + /** + * Tests the execution of the setAttribute,getAttribute and invoke methods when an unknown / unexpected + * exception is thrown. + * + *
precondition : the mbean is registered and a capability is associated with it. Something + * unexpected happens during method invocation. + *
postcondition : an exception is thrown indicating the failure. + */ + public void testQManFault() throws Exception + { + // Emulate a RuntimeException (which is the best example of uncaught exception... :) ) + _capability.setResourceObjectName(null); + + try + { + _capability.getAttribute(_typeAttributeName); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(QManFault expected) + { + } + + try + { + _capability.setAttribute(_typeAttributeName,_newTypeValue); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(QManFault expected) + { + } + + try + { + _capability.invoke("operationName", null,null); + fail("An exception must be thrown here in order to indicate that the attribute is unknown."); + } catch(QManFault expected) + { + } + } + + + /** + * Shutdown procedure for this test case. + */ + @Override + protected void tearDown() throws Exception + { + ManagementFactory.getPlatformMBeanServer().unregisterMBean(_objectName); + } +} diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java new file mode 100644 index 0000000000..648c7b2f60 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapabilityTest.java @@ -0,0 +1,81 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import org.apache.muse.ws.notification.NotificationProducer; +import org.apache.qpid.management.Names; + +import junit.framework.TestCase; + +/** + * Test case for QMan adapter capability. + * + * @author Andrea Gazzarini + */ +public class QManAdapterCapabilityTest extends TestCase +{ + /** + * Tests the execution of the getTopicName() method. + * + *
precondition : an object type is given to the method (null is allowed). + *
postcondition : according to getTopicName() specs, the name of the + * topic associated with the given object type must be returned. + */ + public void testGetTopicName() + { + final InvocationHandler invocationHandler = new InvocationHandler(){ + + public Object invoke(Object proxy, Method method, Object[] args) + { + return null; + } + }; + + QManAdapterCapability capability = new QManAdapterCapability(){ + @Override + NotificationProducer getPublisherCapability() + { + return (NotificationProducer) Proxy.newProxyInstance( + getClass().getClassLoader(), + new Class[]{NotificationProducer.class}, + invocationHandler); + } + }; + + capability.createLifeCycleTopics(); + + assertEquals( + Names.EVENTS_LIFECYLE_TOPIC_NAME, + capability.getTopicName(Names.EVENT)); + + assertEquals( + Names.OBJECTS_LIFECYLE_TOPIC_NAME, + capability.getTopicName(Names.CLASS)); + + assertEquals( + Names.UNKNOWN_OBJECT_TYPE_LIFECYLE_TOPIC_NAME, + capability.getTopicName("This is an unknown object Type @#!--!!@#")); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java new file mode 100644 index 0000000000..77cda1c2c1 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/capabilities/RmdBuilderTest.java @@ -0,0 +1,110 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.lang.management.ManagementFactory; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.qpid.management.Names; +import org.apache.qpid.management.domain.handler.impl.QpidDomainObject; +import org.w3c.dom.Element; + +import junit.framework.TestCase; + +/** + * Test case for Resource Metadata Descriptor Builder. + * + * @author Andrea Gazzarini + */ +public class RmdBuilderTest extends TestCase +{ + private MBeanInfo _metadata; + private RmdBuilder _builder; + private ObjectName _objectName; + + @Override + protected void setUp() throws Exception + { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + _objectName = new ObjectName("Test:Name=QpidDomainObject"); + + server.registerMBean(new QpidDomainObject(), _objectName); + _metadata = server.getMBeanInfo(_objectName); + + _builder = new RmdBuilder(); + _builder.begin(_objectName); + + assertEquals(_objectName,_builder._objectName); + } + + /** + * Tests the execution of the onOperation() method. + */ + public void testOnOperation() throws Exception + { + MBeanAttributeInfo [] attributes = _metadata.getAttributes(); + for (MBeanAttributeInfo attribute : attributes) + { + _builder.onAttribute(attribute); + } + + Element [] rmd = _builder.getResourceMetadataDescriptor(); + + assertEquals(attributes.length,rmd.length); + + for (MBeanAttributeInfo attribute: _metadata.getAttributes()) + { + Element propertyMetadataDescriptor = getPropertyMetadatDescriptor(attribute.getName(), rmd); + + String modifiability = propertyMetadataDescriptor.getAttribute(Names.MODIFIABILITY); + String expectedValue = + attribute.isWritable() + ? Names.READ_WRITE + : Names.READ_ONLY; + assertEquals(expectedValue,modifiability); + } + } + + /** + * Returns the property metadata descriptor associated with the given attribute name. + * + * @param name the attribute name. + * @param rmd the resource metadata descriptor. + * @return the property metadata descriptor associated with the given attribute name. + * @throws RuntimeException if metadata for the given attribute is not found. + */ + private Element getPropertyMetadatDescriptor(String name, Element [] rmd) + { + for (Element propertyMetadataDescriptor : rmd) + { + if ((Names.PREFIX+":"+name).equals( + propertyMetadataDescriptor.getAttribute(Names.NAME_ATTRIBUTE))) + { + return propertyMetadataDescriptor; + } + } + throw new RuntimeException("Property MetadataDescriptor not found for attribute "+name); + } +} \ No newline at end of file diff --git a/java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml new file mode 100644 index 0000000000..df273bd841 --- /dev/null +++ b/java/management/client/src/test/java/org/apache/qpid/management/wsdm/web.xml @@ -0,0 +1,32 @@ + + + + + + Qpid emulator startip + QEmu + org.apache.qpid.management.wsdm.QEmuInitializer + 1 + + -- cgit v1.2.1