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 --- 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 ++ 173 files changed, 25462 insertions(+) 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 (limited to 'java/management/client/src/main') 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.1