summaryrefslogtreecommitdiff
path: root/java/client/src
diff options
context:
space:
mode:
authorArnaud Simon <arnaudsimon@apache.org>2008-09-29 12:02:54 +0000
committerArnaud Simon <arnaudsimon@apache.org>2008-09-29 12:02:54 +0000
commit32c96c8a723712b74a3b7b2331cc3b1b75d6cc3e (patch)
tree8a85f9d9ea3b0a0ac617d89e884077708b8983b4 /java/client/src
parent5d140890605743357347a0c0326ed4cf78117d8d (diff)
downloadqpid-python-32c96c8a723712b74a3b7b2331cc3b1b75d6cc3e.tar.gz
qpid-1284: Qman on behalf Andrea
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@700077 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/client/src')
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/Constants.java32
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/Names.java52
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/Protocol.java34
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/config.xml106
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMapping.java94
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMappingParser.java74
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java211
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java133
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java343
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java41
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java145
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/IParser.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/ManagementQueueMessageListenerParser.java72
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java72
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/MethodReplyQueueMessageListenerParser.java72
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java276
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/Tag.java42
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/TypeMapping.java103
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/TypeMappingParser.java77
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java53
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java43
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java53
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java54
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java116
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java52
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java58
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java58
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java68
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java41
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java158
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java33
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java33
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java174
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java38
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java158
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java35
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java77
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java104
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java855
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java26
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java88
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java444
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java103
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java227
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java295
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java34
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java51
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java105
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java129
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java95
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java44
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java46
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java181
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java256
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java103
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java270
-rw-r--r--java/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java42
67 files changed, 7263 insertions, 0 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/management/Constants.java b/java/client/src/main/java/org/apache/qpid/management/Constants.java
new file mode 100644
index 0000000000..7be1bda776
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/Constants.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management;
+
+/**
+ * Enumeration of literal values used to avoid code duplication.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface Constants
+{
+ /** No expiration (used for timeout) */
+ long NO_EXPIRATION = 0;
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/Names.java b/java/client/src/main/java/org/apache/qpid/management/Names.java
new file mode 100644
index 0000000000..8ab9e13d4f
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/Names.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;
+
+/**
+ * Enumeration of literal strings to avoid code duplication.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface Names
+{
+ /** Name of the qpid management exchange. */
+ String MANAGEMENT_EXCHANGE = "qpid.management";
+ String MANAGEMENT_ROUTING_KEY = "mgmt.#";
+
+ String MANAGEMENT_QUEUE_PREFIX = "management.";
+ String METHOD_REPLY_QUEUE_PREFIX = "reply.";
+
+ String AMQ_DIRECT_QUEUE = "amq.direct";
+ String AGENT_ROUTING_KEY = "agent.0";
+
+ String BROKER_ROUTING_KEY = "broker";
+
+ // Attributes
+ String PACKAGE = "package";
+ String CLASS = "class";
+ String OBJECT_ID="objectID";
+ String BROKER_ID = "brokerID";
+ String DOMAIN_NAME = "Q-MAN";
+
+ String CONFIGURATION_FILE_NAME = "/org/apache/qpid/management/config.xml";
+
+ String ARG_COUNT_PARAM_NAME = "argCount";
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/Protocol.java b/java/client/src/main/java/org/apache/qpid/management/Protocol.java
new file mode 100644
index 0000000000..f50a85f28a
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/Protocol.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;
+
+/**
+ * Protocol defined constants.
+ *
+ * @author Andrea Gazzarini
+ */
+public interface Protocol
+{
+ String MAGIC_NUMBER = "AM1";
+
+ byte [] METHOD_REQUEST_FIRST_FOUR_BYTES = (MAGIC_NUMBER+"M").getBytes();
+ byte [] SCHEMA_REQUEST_FIRST_FOUR_BYTES = (MAGIC_NUMBER+"S").getBytes();
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/config.xml b/java/client/src/main/java/org/apache/qpid/management/config.xml
new file mode 100644
index 0000000000..590e33a0f7
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/config.xml
@@ -0,0 +1,106 @@
+<configuration>
+ <message-handlers>
+ <management-queue>
+ <handler>
+ <opcode>i</opcode>
+ <class-name>org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler</class-name>
+ </handler>
+ <handler>
+ <opcode>c</opcode>
+ <class-name>org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler</class-name>
+ </handler>
+ </management-queue>
+ <method-reply-queue>
+ <handler>
+ <opcode>m</opcode>
+ <class-name>org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler</class-name>
+ </handler>
+ <handler>
+ <opcode>s</opcode>
+ <class-name>org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler</class-name>
+ </handler>
+ </method-reply-queue>
+ </message-handlers>
+ <type-mappings>
+ <mapping>
+ <code>1</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Uint8</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$NumberValidator</validator-class-name>
+ </mapping>
+ <mapping>
+ <code>2</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Uint16</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$NumberValidator</validator-class-name>
+ </mapping>
+ <mapping>
+ <code>3</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Uint32</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$NumberValidator</validator-class-name>
+ </mapping>
+ <mapping>
+ <code>4</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Uint64</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$NumberValidator</validator-class-name>
+ </mapping>
+ <mapping>
+ <code>6</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Str8</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$StringValidator</validator-class-name>
+ </mapping>
+ <mapping>
+ <code>7</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Str16</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$StringValidator</validator-class-name>
+ </mapping>
+ <mapping>
+ <code>8</code>
+ <class-name>org.apache.qpid.management.domain.model.type.AbsTime</class-name>
+ </mapping>
+ <mapping>
+ <code>9</code>
+ <class-name>org.apache.qpid.management.domain.model.type.DeltaTime</class-name>
+ </mapping>
+ <mapping>
+ <code>10</code>
+ <class-name>org.apache.qpid.management.domain.model.type.ObjectReference</class-name>
+ </mapping>
+ <mapping>
+ <code>11</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Boolean</class-name>
+ </mapping>
+ <mapping>
+ <code>14</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Uuid</class-name>
+ </mapping>
+ <mapping>
+ <code>15</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Map</class-name>
+ </mapping>
+ </type-mappings>
+ <access-mode-mappings>
+ <mapping>
+ <code>1</code>
+ <value>RC</value>
+ </mapping>
+ <mapping>
+ <code>2</code>
+ <value>RW</value>
+ </mapping>
+ <mapping>
+ <code>3</code>
+ <value>RO</value>
+ </mapping>
+ </access-mode-mappings>
+ <brokers>
+ <broker>
+ <host>localhost</host>
+ <port>5672</port>
+ <virtual-host>test</virtual-host>
+ <user>guest</user>
+ <password>guest</password>
+ <max-pool-capacity>4</max-pool-capacity>
+ <initial-pool-capacity>4</initial-pool-capacity>
+ <max-wait-timeout>-1</max-wait-timeout>
+ </broker>
+ </brokers>
+</configuration>
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMapping.java b/java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMapping.java
new file mode 100644
index 0000000000..899462a648
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMapping.java
@@ -0,0 +1,94 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.model.AccessMode;
+
+/**
+ * Class used to encapsulate a mapping between an access mode and a code.
+ *
+ * @author Andrea Gazzarini
+ */
+class AccessModeMapping
+{
+ private int _code;
+ private AccessMode _accessMode;
+
+ /**
+ * Sets the code for this mapping.
+ * Note that the given string must be a valid number (integer).
+ *
+ * @param codeAsString the code value as a string.
+ * @throws NumberFormatException when the given string is not a number.
+ */
+ void setCode(String codeAsString) {
+ this._code = Integer.parseInt(codeAsString);
+ }
+
+ /**
+ * Returns the access mode of this mapping.
+ *
+ * @return the access mode of this mapping.
+ */
+ AccessMode getAccessMode ()
+ {
+ return _accessMode;
+ }
+
+ /**
+ * Sets the access mode for this mapping.
+ * Note that the given string must correspond to a valid access mode value (RW,RC, RO).
+ *
+ * @param accessModeAsString acces mode as a string.
+ * @throws IllegalArgumentException when the given string is not a valid access code.
+ */
+ void setAccessMode (String accessModeAsString)
+ {
+ this._accessMode = AccessMode.valueOf(accessModeAsString);
+ }
+
+ /**
+ * Returns the code of this mapping.
+ *
+ * @return the code of this mapping.
+ */
+ int getCode ()
+ {
+ return _code;
+ }
+
+ /**
+ * Returns a string representation of this mapping.
+ * The returned string is indicating the code and the corresponding access mode.
+ *
+ * @return a string representation of this mapping.
+ */
+ @Override
+ public String toString ()
+ {
+ return new StringBuilder()
+ .append("AccessMode mapping (")
+ .append(_code)
+ .append(',')
+ .append(_accessMode)
+ .append(')').toString();
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMappingParser.java b/java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMappingParser.java
new file mode 100644
index 0000000000..d9dcbd12d3
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/AccessModeMappingParser.java
@@ -0,0 +1,74 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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;
+
+/**
+ * Parser used for building access mode mappings.
+ * For each access-mode-mappings/mapping element found in the configuration file, a new access mode mapping
+ * is built and injected into the configuration.
+ *
+ *<mapping>
+ <code>1</code>
+ <value>RC</value>
+ </mapping>
+ *
+ * @author Andrea Gazzarini
+ */
+class AccessModeMappingParser implements IParser
+{
+ private AccessModeMapping _mapping = new AccessModeMapping();
+ 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.
+ */
+ public void setCurrentAttributeName (String name)
+ {
+ switch (Tag.get(name))
+ {
+ case CODE:
+ {
+ _mapping.setCode(_currentValue);
+ break;
+ }
+ case VALUE :
+ {
+ _mapping.setAccessMode(_currentValue);
+ break;
+ }
+ case MAPPING:
+ {
+ Configuration.getInstance().addAccessModeMapping(_mapping);
+ _mapping = new AccessModeMapping();
+ break;
+ }
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java b/java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java
new file mode 100644
index 0000000000..74e89ef19d
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionData.java
@@ -0,0 +1,211 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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 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;
+ }
+
+ public void setInitialPoolCapacity (String value)
+ {
+ _initialPoolCapacity = Integer.parseInt(value);
+ }
+
+ public int getInitialPoolCapacity ()
+ {
+ return _initialPoolCapacity;
+ }
+
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java b/java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java
new file mode 100644
index 0000000000..d76baed07f
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/BrokerConnectionDataParser.java
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.transport.util.Logger;
+
+/**
+ * Parser used for building access mode mappings.
+ * For each access-mode-mappings/mapping element found in the configuration file, a new access mode mapping
+ * is built and injected into the bridge configuration.
+ *
+ * <broker>
+ <host>192.168.61.130</host>
+ <port>5673</port>
+ <virtual-host>test</virtual-host>
+ <user>andrea</user>
+ <password>andrea</password>
+ </broker>
+ *
+ * @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.
+ * <broker>
+ <host>192.168.61.130</host>
+ <port>5673</port>
+ <virtual-host>test</virtual-host>
+ <user>andrea</user>
+ <password>andrea</password>
+ </broker>
+ */
+ 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, "Unable to connect with broker located on %s and. Hence this broker will be ignored.", _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/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java b/java/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java
new file mode 100644
index 0000000000..cd39d330bb
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/Configuration.java
@@ -0,0 +1,343 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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.Type;
+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.
+ *
+ * @author Andrea Gazzarini
+ */
+public final class Configuration
+{
+ private final static Logger LOGGER = Logger.get(Configuration.class);
+ private static Configuration INSTANCE = new Configuration();
+
+ Map<Integer, Type> _typeMappings = new HashMap<Integer,Type>();
+ Map<Integer,AccessMode> _accessModes = new HashMap<Integer, AccessMode>();
+ Map<Type,String> _validators = new HashMap<Type, String>();
+
+ Map<UUID,BrokerConnectionData> _brokerConnectionInfos = new HashMap<UUID, BrokerConnectionData>();
+
+ Map<Character, String> _managementQueueHandlers = new HashMap<Character, String>();
+ Map<Character, String> _methodReplyQueueHandlers = new HashMap<Character, String>();
+
+ private String _managementQueueName;
+ private String _methodReplyQueueName;
+
+ private Header _headerForCommandMessages;
+
+ // Private constructor.
+ private Configuration()
+ {
+ defineQueueNames();
+ createHeaderForCommandMessages();
+ }
+
+ /**
+ * Returns the singleton instance.
+ *
+ * @return the singleton instance.
+ */
+ public static Configuration getInstance ()
+ {
+ return INSTANCE;
+ }
+
+ /**
+ * 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<Entry<UUID, BrokerConnectionData>> 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<Character, IMessageHandler> getManagementQueueHandlers()
+ {
+ Map<Character, IMessageHandler> result = new HashMap<Character, IMessageHandler>();
+
+ for (Entry<Character, String> entry : _managementQueueHandlers.entrySet())
+ {
+ Character opcode = entry.getKey();
+ String className = entry.getValue();
+ try
+ {
+ result.put(opcode, (IMessageHandler)Class.forName(className).newInstance());
+ } catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ "<QMAN-100020> : Management Message Handler configured for opcode %s is not available and therefore will be discarded.",
+ opcode);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 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<Character, IMessageHandler> getMethodReplyQueueHandlers()
+ {
+ Map<Character, IMessageHandler> result = new HashMap<Character, IMessageHandler>();
+
+ for (Entry<Character, String> entry : _methodReplyQueueHandlers.entrySet())
+ {
+ Character opcode = entry.getKey();
+ String className = entry.getValue();
+ try
+ {
+ result.put(opcode, (IMessageHandler)Class.forName(className).newInstance());
+ } catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ "<QMAN-100021> :Method-Reply Message Handler configured for opcode %s is not available and therefore will be discarded.",
+ opcode);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Adds a new type mapping to this configuration.
+ *
+ * @param mapping the type mapping that will be added.
+ */
+ void addTypeMapping(TypeMapping mapping) {
+ int code = mapping.getCode();
+ Type type = mapping.getType();
+ String validatorClassName = mapping.getValidatorClassName();
+ _typeMappings.put(code, type);
+ _validators.put(type, validatorClassName);
+
+ LOGGER.info("<QMAN-000020> : Type mapping : code = %s associated to %s (validator class is %s)", code,type,validatorClassName);
+ }
+
+ /**
+ * Adds a new access mode mapping to this configuration.
+ *
+ * @param mapping the mapping that will be added.
+ */
+ void addAccessModeMapping(AccessModeMapping mapping){
+ int code = mapping.getCode();
+ AccessMode accessMode = mapping.getAccessMode();
+ _accessModes.put(code, accessMode);
+
+ LOGGER.info("<QMAN-000021> : Access Mode mapping : code = %s associated to %s", 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();
+ String handlerClass = mapping.getMessageHandlerClass();
+ _managementQueueHandlers.put(opcode, handlerClass);
+
+ LOGGER.info("<QMAN-000022> : Management Queue Message Handler Mapping : opcode = %s associated with %s", opcode,handlerClass);
+ }
+
+ /**
+ * 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();
+ String handlerClass = mapping.getMessageHandlerClass();
+ _methodReplyQueueHandlers.put(opcode, handlerClass);
+
+ LOGGER.info("<QMAN-000023> : Method-Reply Queue Message Handler Mapping : opcode = %s associated with %s", opcode,handlerClass);
+ }
+
+ /**
+ * Adds to this configuration a new broker connection data.
+ *
+ * @param brokerId the broker identifier.
+ * @param connectionData the connection data.
+ * @throws Exception
+ */
+ void addBrokerConnectionData (UUID brokerId, BrokerConnectionData connectionData) throws Exception
+ {
+ QpidDatasource.getInstance().addConnectionPool(brokerId, connectionData);
+ _brokerConnectionInfos.put(brokerId,connectionData);
+ LOGGER.info("<QMAN-000024> : Broker Configuration %s: %s",brokerId,connectionData);
+ }
+
+ /**
+ * Header for command messages is created once because it only contains static values.
+ */
+ private void createHeaderForCommandMessages ()
+ {
+ MessageProperties messageProperties = new MessageProperties();
+
+ ReplyTo replyTo=new ReplyTo();
+ replyTo.setRoutingKey(_methodReplyQueueName);
+ messageProperties.setReplyTo(replyTo);
+
+ DeliveryProperties deliveryProperties = new DeliveryProperties();
+ 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("<QMAN-200021> : Management queue name : %s",_managementQueueName);
+ LOGGER.debug("<QMAN-000022> : Method-reply queue name : %s",_methodReplyQueueName);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java b/java/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.java
new file mode 100644
index 0000000000..0ddbb3e1d8
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/ConfigurationException.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.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;
+
+ /**
+ * Builds a new ConfigurationException with the given cause.
+ *
+ * @param exception the exception cause.
+ */
+ public ConfigurationException(Exception exception)
+ {
+ super(exception);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java b/java/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java
new file mode 100644
index 0000000000..fb33622f4d
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java
@@ -0,0 +1,145 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.InputStreamReader;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.qpid.management.Names;
+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.
+ *
+ * @author Andrea Gazzarini
+ */
+public class Configurator extends DefaultHandler
+{
+ /**
+ * 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 _typeMappingParser = new TypeMappingParser();
+ IParser _accessModeMappingParser = new AccessModeMappingParser();
+ IParser _brokerConfigurationParser = new BrokerConnectionDataParser();
+ IParser _managementQueueHandlerParser = new ManagementQueueMessageListenerParser();
+ IParser _methodReplyQueueHandlerParser = new MethodReplyQueueMessageListenerParser();
+
+ 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 TYPE_MAPPINGS : {
+ _currentParser = _typeMappingParser;
+ break;
+ }
+ case ACCESS_MODE_MAPPINGS:
+ {
+ _currentParser = _accessModeMappingParser;
+ break;
+ }
+ case BROKERS:
+ {
+ _currentParser = _brokerConfigurationParser;
+ break;
+ }
+ case MANAGEMENT_QUEUE:
+ {
+ _currentParser = _managementQueueHandlerParser;
+ break;
+ }
+ case METHOD_REPLY_QUEUE:
+ {
+ _currentParser = _methodReplyQueueHandlerParser;
+ 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
+ {
+ try
+ {
+ SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(getConfigurationFileName()),"UTF8"));
+ InputSource source = new InputSource(reader);
+ parser.parse(source, this);
+ } catch (Exception exception)
+ {
+ throw new ConfigurationException(exception);
+ }
+ }
+
+ /**
+ * Returns the name of the configuration file.
+ *
+ * @return the name of the configuration file.
+ */
+ String getConfigurationFileName()
+ {
+ return Names.CONFIGURATION_FILE_NAME;
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/IParser.java b/java/client/src/main/java/org/apache/qpid/management/configuration/IParser.java
new file mode 100644
index 0000000000..a221686765
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/configuration/ManagementQueueMessageListenerParser.java b/java/client/src/main/java/org/apache/qpid/management/configuration/ManagementQueueMessageListenerParser.java
new file mode 100644
index 0000000000..f31cd832cc
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/ManagementQueueMessageListenerParser.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.configuration;
+
+/**
+ * Parser used for building mapping between a management queue message listeners and an opcode.
+ *
+ * <handler>
+ <opcode>i</opcode>
+ <class-name>org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler</class-name>
+ </handler>
+
+ * @author Andrea Gazzarini
+ */
+class ManagementQueueMessageListenerParser implements IParser
+{
+ private MessageHandlerMapping _mapping = new MessageHandlerMapping();
+ 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.
+ */
+ public void setCurrentAttributeName (String name)
+ {
+ switch (Tag.get(name))
+ {
+ case OPCODE:
+ {
+ _mapping.setOpcode(_currentValue);
+ break;
+ }
+ case CLASS_NAME:
+ {
+ _mapping.setMessageHandlerClass(_currentValue);
+ break;
+ }
+ case HANDLER:
+ {
+ Configuration.getInstance().addManagementMessageHandlerMapping(_mapping);
+ _mapping = new MessageHandlerMapping();
+ break;
+ }
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java b/java/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.java
new file mode 100644
index 0000000000..7ce3baae49
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/MessageHandlerMapping.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.configuration;
+
+/**
+ * Message Handler mapping used for associating an opcode with a message handler.
+ *
+ * @author Andrea Gazzarini
+ */
+class MessageHandlerMapping
+{
+ private Character _opcode;
+ private String _handlerClass;
+
+ /**
+ * Returns the opcode of this mapping.
+ *
+ * @return the code of this mapping.
+ */
+ Character getOpcode ()
+ {
+ return _opcode;
+ }
+
+ /**
+ * Sets the opcode for this mapping.
+ *
+ * @param codeAsString the opcode as a string.
+ */
+ void setOpcode (String codeAsString)
+ {
+ this._opcode = codeAsString.charAt(0);
+ }
+
+ /**
+ * Returns the message handler for this mapping.
+ *
+ * @return the message handler for this mapping.
+ */
+ String getMessageHandlerClass()
+ {
+ return _handlerClass;
+ }
+
+ /**
+ * Sets the message handler of this mapping.
+ *
+ * @param handlerClass the handler class as a string.
+ */
+ void setMessageHandlerClass(String handlerClass)
+ {
+ this._handlerClass = handlerClass;
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/MethodReplyQueueMessageListenerParser.java b/java/client/src/main/java/org/apache/qpid/management/configuration/MethodReplyQueueMessageListenerParser.java
new file mode 100644
index 0000000000..a466b50658
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/MethodReplyQueueMessageListenerParser.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.configuration;
+
+/**
+ * Parser used for building mappings between method-reply queue message listeners and an opcode.
+ *
+ * <handler>
+ <opcode>i</opcode>
+ <class-name>org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler</class-name>
+ </handler>
+ *
+ * @author Andrea Gazzarini
+ */
+class MethodReplyQueueMessageListenerParser implements IParser
+{
+ private MessageHandlerMapping _mapping = new MessageHandlerMapping();
+ 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.
+ */
+ public void setCurrentAttributeName (String name)
+ {
+ switch (Tag.get(name))
+ {
+ case OPCODE:
+ {
+ _mapping.setOpcode(_currentValue);
+ break;
+ }
+ case CLASS_NAME:
+ {
+ _mapping.setMessageHandlerClass(_currentValue);
+ break;
+ }
+ case HANDLER:
+ {
+ Configuration.getInstance().addMethodReplyMessageHandlerMapping(_mapping);
+ _mapping = new MessageHandlerMapping();
+ break;
+ }
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java b/java/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java
new file mode 100644
index 0000000000..f4428cb1e2
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/QpidDatasource.java
@@ -0,0 +1,276 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ErrorCode;
+import org.apache.qpid.QpidException;
+import org.apache.qpid.nclient.Client;
+import org.apache.qpid.nclient.ClosedListener;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.DtxSession;
+import org.apache.qpid.nclient.Session;
+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
+ */
+ public class ConnectionDecorator implements Connection,ClosedListener
+ {
+ private final Connection _decoratee;
+ private final UUID _brokerId;
+ private boolean _valid;
+
+ /**
+ * Builds a new decorator with the given connection.
+ *
+ * @param brokerId the broker identifier.
+ * @param decoratee the underlying connection.
+ */
+ private ConnectionDecorator(UUID brokerId, Connection decoratee)
+ {
+ this._decoratee = decoratee;
+ this._brokerId = brokerId;
+ _decoratee.setClosedListener(this);
+ _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;
+ }
+
+ /**
+ * 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 () throws QpidException
+ {
+ try
+ {
+ pools.get(_brokerId).returnObject(this);
+ LOGGER.debug("<QMAN-200012> : Connection %s returned to the pool.", this);
+ } catch (Exception exception)
+ {
+ throw new QpidException("Error while closing connection.",ErrorCode.CONNECTION_ERROR,exception);
+ }
+ }
+
+ /**
+ * Do nothing : underlying connection is already connected.
+ */
+ public void connect (String host, int port, String virtualHost, String username, String password)
+ throws QpidException
+ {
+ // DO NOTHING : DECORATEE CONNECTION IS ALREADY CONNECTED.
+ }
+
+ /**
+ * Do nothing : underlying connection is already connected.
+ */
+ public void connect (String url) throws QpidException
+ {
+ // DO NOTHING : DECORATEE CONNECTION IS ALREADY CONNECTED.
+ }
+
+ /**
+ * @see Connection#createDTXSession(int)
+ */
+ public DtxSession createDTXSession (int expiryInSeconds)
+ {
+ return _decoratee.createDTXSession(expiryInSeconds);
+ }
+
+ /**
+ * @see Connection#createSession(long)
+ */
+ public Session createSession (long expiryInSeconds)
+ {
+ return _decoratee.createSession(expiryInSeconds);
+ }
+
+ /**
+ * Do nothing : closed listener has been already injected.
+ */
+ public void setClosedListener (ClosedListener exceptionListner)
+ {
+ }
+
+ /**
+ * Callback method used for error notifications while underlying connection is closing.
+ */
+ public void onClosed (ErrorCode errorCode, String reason, Throwable t)
+ {
+ _valid = false;
+ LOGGER.error(t,"<QMAN-100012> : Error on closing connection. Reason is : %s, error code is %s",reason,errorCode.getCode());
+ }
+ };
+
+ /**
+ * 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
+ {
+ Connection connection = Client.createConnection();
+ connection.connect(
+ _connectionData.getHost(),
+ _connectionData.getPort(),
+ _connectionData.getVirtualHost(),
+ _connectionData.getUsername(),
+ _connectionData.getPassword());
+ return new ConnectionDecorator(_brokerId,connection);
+ }
+
+ /**
+ * Validates the underlying connection.
+ */
+ @Override
+ public boolean validateObject (Object obj)
+ {
+ ConnectionDecorator connection = (ConnectionDecorator) obj;
+ boolean isValid = connection.isValid();
+ LOGGER.debug("<QMAN-200013> : Test connection on reserve. Is valid? %s",isValid);
+ return isValid;
+ }
+
+ /**
+ * Closes the underlying connection.
+ */
+ @Override
+ public void destroyObject (Object obj) throws Exception
+ {
+ try
+ {
+ ConnectionDecorator connection = (ConnectionDecorator) obj;
+ connection._decoratee.close();
+ LOGGER.debug("<QMAN-200014> : Connection has been destroyed.");
+ } catch (Exception e)
+ {
+ LOGGER.debug(e, "<QMAN-200015> : Unable to destroy a connection object");
+ }
+ }
+ }
+
+ // Singleton instance.
+ private static QpidDatasource instance = new QpidDatasource();
+
+ // Each entry contains a connection pool for a specific broker.
+ private Map<UUID, ObjectPool> pools = new HashMap<UUID, ObjectPool>();
+
+ // 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();
+
+ for (int i = 0; i < connectionData.getInitialPoolCapacity(); i++)
+ {
+ pool.returnObject(pool.borrowObject());
+ }
+
+ pools.put(brokerId,pool);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/Tag.java b/java/client/src/main/java/org/apache/qpid/management/configuration/Tag.java
new file mode 100644
index 0000000000..9b3a4a3f6f
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/Tag.java
@@ -0,0 +1,42 @@
+package org.apache.qpid.management.configuration;
+
+/**
+ * Configuration Tag catalogue.
+ *
+ * @author Andrea Gazzarini
+ */
+public enum Tag {
+ HANDLER { @Override public String toString() { return "handler"; }},
+ MAPPING { @Override public String toString() { return "mapping"; }},
+ CODE { @Override public String toString() { return "code"; }},
+ CLASS_NAME { @Override public String toString() { return "class-name"; }},
+ TYPE_MAPPINGS { @Override public String toString() { return "type-mappings"; }},
+ ACCESS_MODE_MAPPINGS { @Override public String toString() { return "access-mode-mappings"; }},
+ VALUE { @Override public String toString() { return "value"; }},
+ CONFIGURATION { @Override public String toString() { return "configuration"; }},
+ MESSAGE_HANDLERS { @Override public String toString() { return "message-handlers"; }},
+ OPCODE { @Override public String toString() { return "opcode"; }},
+ VALIDATOR_CLASS_NAME { @Override public String toString() { return "validator-class-name"; }},
+ 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"; }},
+ MANAGEMENT_QUEUE { @Override public String toString() { return "management-queue"; }},
+ METHOD_REPLY_QUEUE { @Override public String toString() { return "method-reply-queue"; }};
+
+ /**
+ * 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());
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/TypeMapping.java b/java/client/src/main/java/org/apache/qpid/management/configuration/TypeMapping.java
new file mode 100644
index 0000000000..714c8eb6f5
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/TypeMapping.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.model.type.Type;
+/**
+ * Type Mapping used for associating a code with a management type.
+ *
+ * @author Andrea Gazzarini
+ */
+class TypeMapping
+{
+ private int _code;
+ private Type _type;
+ private String _validatorClass;
+
+ /**
+ * Returns the code of this mapping.
+ *
+ * @return the code of this mapping.
+ */
+ int getCode ()
+ {
+ return _code;
+ }
+
+ /**
+ * Sets the code for this mapping.
+ * Note that the given string must be a valid number (integer).
+ *
+ * @param codeAsString the code as a string.
+ * @throws NumberFormatException when the given string is not a valid number.
+ */
+ void setCode (String codeAsString)
+ {
+ this._code = Integer.parseInt(codeAsString);
+ }
+
+ /**
+ * Returns the type for this mapping.
+ *
+ * @return the type for this mapping.
+ */
+ Type getType ()
+ {
+ return _type;
+ }
+
+ /**
+ * Sets the type of this mapping.
+ *
+ * @param typeClass the type class as a string.
+ * @throw IllegalArgumentException when it's not possible to load the given class.
+ */
+ void setType (String typeClass)
+ {
+ try
+ {
+ this._type = (Type) Class.forName(typeClass).newInstance();
+ } catch (Exception exception)
+ {
+ throw new IllegalArgumentException(exception);
+ }
+ }
+
+ /**
+ * Sets the validator class that will be used for validation.
+ *
+ * @param className the fully qualified name of the validation class.
+ */
+ public void setValidatorClassName (String className)
+ {
+ this._validatorClass = className;
+ }
+
+ /**
+ * Returns the validator class of this mapping.
+ *
+ * @return the validator class (as a string) of this mapping.
+ */
+ public String getValidatorClassName()
+ {
+ return _validatorClass;
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/TypeMappingParser.java b/java/client/src/main/java/org/apache/qpid/management/configuration/TypeMappingParser.java
new file mode 100644
index 0000000000..40b9cf84ca
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/configuration/TypeMappingParser.java
@@ -0,0 +1,77 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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;
+
+/**
+ * Parser used for building type mappings.
+ * For each type-mappings/mapping element found in the configuration file, a new type mapping is built and injected into
+ * the bridge configuration.
+ *
+ * <mapping>
+ <code>1</code>
+ <class-name>org.apache.qpid.management.domain.model.type.Uint8</class-name>
+ <validator-class-name>org.apache.qpid.management.domain.model.QpidProperty$NumberValidator</validator-class-name>
+ </mapping>
+ *
+ * @author Andrea Gazzarini
+ */
+class TypeMappingParser implements IParser
+{
+ private TypeMapping _mapping = new TypeMapping();
+ 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.
+ */
+ public void setCurrentAttributeName (String name)
+ {
+ switch (Tag.get(name))
+ {
+ case CODE:
+ {
+ _mapping.setCode(_currentValue);
+ break;
+ }
+ case CLASS_NAME : {
+ _mapping.setType(_currentValue);
+ break;
+ }
+ case VALIDATOR_CLASS_NAME : {
+ _mapping.setValidatorClassName(_currentValue);
+ break;
+ }
+ case MAPPING : {
+ Configuration.getInstance().addTypeMapping(_mapping);
+ _mapping = new TypeMapping();
+ break;
+ }
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java b/java/client/src/main/java/org/apache/qpid/management/configuration/UnknownAccessCodeException.java
new file mode 100644
index 0000000000..b7f1c0a7ec
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java b/java/client/src/main/java/org/apache/qpid/management/configuration/UnknownBrokerException.java
new file mode 100644
index 0000000000..5b08e09c24
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java b/java/client/src/main/java/org/apache/qpid/management/configuration/UnknownTypeCodeException.java
new file mode 100644
index 0000000000..57005d21e5
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/base/BaseMessageHandler.java
new file mode 100644
index 0000000000..798e835ff4
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java
new file mode 100644
index 0000000000..21a3281fa9
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/handler/base/ContentIndicationMessageHandler.java
@@ -0,0 +1,116 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ManagementDecoder;
+
+/**
+ * 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 (ManagementDecoder 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/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/base/IMessageHandler.java
new file mode 100644
index 0000000000..b945a29117
--- /dev/null
+++ b/java/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.ManagementDecoder;
+
+/**
+ * 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 (ManagementDecoder 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/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.java
new file mode 100644
index 0000000000..a5f8c238a7
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/ConfigurationMessageHandler.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.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)
+ {
+ // TODO : deal with timestamps, too
+ _domainModel.addConfigurationRawData(packageName,className,classHash,objectId,contentData);
+ }
+ } \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.java
new file mode 100644
index 0000000000..ee6d1f0092
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InstrumentationMessageHandler.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.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)
+ {
+ // TODO : deal with timestamps, too
+ _domainModel.addInstrumentationRawData(packageName,className,classHash,objectId,contentData);
+ }
+ } \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodOrEventDataTransferObject.java
new file mode 100644
index 0000000000..bc6a77d804
--- /dev/null
+++ b/java/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<String, Object> _definition;
+ private List<Map<String, Object>> _argumentDefinitions;
+
+ /**
+ * Builds a new trasfer object with the given parameters.
+ *
+ * @param definition the method definition.
+ * @param argumentDefinitions the arguments definitions.
+ */
+ public MethodOrEventDataTransferObject(
+ Map<String, Object> definition,
+ List<Map<String, Object>> argumentDefinitions)
+ {
+ this._definition = definition;
+ this._argumentDefinitions = argumentDefinitions;
+ }
+
+ /**
+ * Returns the method definition.
+ *
+ * @return the method definition.
+ */
+ public Map<String, Object> getDefinition() {
+ return _definition;
+ }
+
+ /**
+ * Returns the arguemnts definitions.
+ *
+ * @return the arguemnts definitions.
+ */
+ public List<Map<String, Object>> getArgumentsDefinitions()
+ {
+ return _argumentDefinitions;
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.java
new file mode 100644
index 0000000000..24db2e963d
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/MethodResponseMessageHandler.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 org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.transport.codec.ManagementDecoder;
+import org.apache.qpid.transport.util.Logger;
+
+public class MethodResponseMessageHandler extends BaseMessageHandler
+{
+ private final static Logger LOGGER = Logger.get(MethodResponseMessageHandler.class);
+
+ public void process (ManagementDecoder decoder, int sequenceNumber)
+ {
+ LOGGER.debug("<QMAN-200009> : Incoming method response message.");
+
+ long statusCode = decoder.readUint32();
+ String statusText = decoder.readStr8();
+
+ LOGGER.debug("<QMAN-200010> : Status code : %s", statusCode);
+ LOGGER.debug("<QMAN-200011> : Status text : %s", statusText);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java
new file mode 100644
index 0000000000..7a0ee556d2
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.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.domain.handler.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.codec.ManagementDecoder;
+
+/**
+ * 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
+{
+ /**
+ * 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 (ManagementDecoder decoder, int sequenceNumber)
+ {
+ 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();
+ int howManyEvents = decoder.readUint16();
+
+ // FIXME : Divide between schema error and raw data conversion error!!!!
+ _domainModel.addSchema(
+ packageName,
+ className,
+ schemaHash,
+ getProperties(decoder, howManyProperties),
+ getStatistics(decoder, howManyStatistics),
+ getMethods(decoder, howManyMethods),
+ getEvents(decoder, howManyEvents));
+ } catch(Exception exception)
+ {
+ _logger.error(exception,"<QMAN-100007> : Q-Man was unable to process the schema response message.");
+ }
+ }
+
+ /**
+ * 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<Map<String, Object>> getProperties(ManagementDecoder decoder,int howManyProperties)
+ {
+ List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(howManyProperties);
+ for (int i = 0; i < howManyProperties; i++ )
+ {
+ result.add(decoder.readMap());
+ }
+ return result;
+ }
+
+ /**
+ * Reads the statistics definitions from the incoming message stream.
+ *
+ * @param decoder the decoder used for decode incoming data.
+ * @param howManyProperties the number of statistics to read.
+ * @return a list of maps. Each map contains a statistic definition.
+ */
+ List<Map<String, Object>> getStatistics(ManagementDecoder decoder,int howManyStatistics)
+ {
+ List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(howManyStatistics);
+ for (int i = 0; i < howManyStatistics; 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<MethodOrEventDataTransferObject> getMethods(ManagementDecoder decoder, int howManyMethods)
+ {
+ List<MethodOrEventDataTransferObject> result = new ArrayList<MethodOrEventDataTransferObject>(howManyMethods);
+ for (int i = 0; i < howManyMethods; i++)
+ {
+ Map<String,Object> method = decoder.readMap();
+ int howManyArguments = (Integer) method.get(Names.ARG_COUNT_PARAM_NAME);
+
+ List<Map<String,Object>> arguments = new ArrayList<Map<String,Object>>(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<MethodOrEventDataTransferObject> getEvents(ManagementDecoder decoder, int howManyEvents)
+ {
+ List<MethodOrEventDataTransferObject> result = new ArrayList<MethodOrEventDataTransferObject>(howManyEvents);
+ for (int i = 0; i < howManyEvents; i++)
+ {
+ Map<String,Object> method = decoder.readMap();
+ int howManyArguments = (Integer) method.get(Names.ARG_COUNT_PARAM_NAME);
+
+ List<Map<String,Object>> arguments = new ArrayList<Map<String,Object>>(howManyArguments);
+ for (int argIndex = 0; argIndex < howManyArguments; argIndex++){
+ arguments.add(decoder.readMap());
+ }
+ result.add(new MethodOrEventDataTransferObject(method,arguments));
+ }
+ return result;
+ }
+ } \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/AccessMode.java
new file mode 100644
index 0000000000..6d1426c122
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/Direction.java
new file mode 100644
index 0000000000..8166c35eb6
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java
new file mode 100644
index 0000000000..b24228d122
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java
@@ -0,0 +1,174 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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<String,QpidPackage> _packages = new HashMap<String, QpidPackage>();
+
+ /**
+ * 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.
+ * @param events the class events.
+ * @throws UnableToBuildFeatureException
+ */
+ public void addSchema(
+ String packageName,
+ String className,
+ Binary classHash,
+ List<Map<String, Object>> properties,
+ List<Map<String, Object>> statistics,
+ List<MethodOrEventDataTransferObject> methods,
+ List<MethodOrEventDataTransferObject> events) throws UnableToBuildFeatureException
+ {
+ QpidPackage qpidPackage = getPackageByName(packageName);
+ qpidPackage.addClassDefinition(className,classHash,properties,statistics,methods, events);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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();
+ }
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/IValidator.java
new file mode 100644
index 0000000000..1ede559145
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java
new file mode 100644
index 0000000000..9ca6ba0e7c
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.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.domain.model;
+
+import java.lang.management.ManagementFactory;
+import java.util.UUID;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.domain.model.QpidClass.QpidManagedObject;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * A simple facade used to perform operations on Mbean server.
+ *
+ * @author Andrea Gazzarini
+ */
+class JmxService
+{
+ private final static Logger LOGGER = Logger.get(JmxService.class);
+ private MBeanServer _mxServer = ManagementFactory.getPlatformMBeanServer();
+
+
+ /**
+ * 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.
+ */
+ void registerObjectInstance(
+ QpidManagedObject 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(
+ "<QMAN-200026> : Object instance %s::%s::%s:%s successfully registered with MBean Server with name %s",
+ brokerId,
+ packageName,
+ className,
+ objectId,
+ name);
+ } catch (Exception exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ }
+ }
+
+ /**
+ * 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.
+ */
+ void 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(
+ "<QMAN-200012> : Object instance %s::%s::%s:%s successfully unregistered from MBean Server. " +
+ "Name was %s",
+ brokerId,
+ packageName,
+ className,
+ objectId,
+ name);
+ } catch (Exception exception)
+ {
+ LOGGER.error(exception,"<QMAN-100010> : Unable to unregister object instance %s.",name);
+ }
+ }
+ }
+
+ /**
+ * 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(',')
+ .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);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/MissingFeatureAttributesException.java
new file mode 100644
index 0000000000..160054059b
--- /dev/null
+++ b/java/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<Attribute> missingAttributeList)
+ {
+ super(String.valueOf(missingAttributeList));
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java
new file mode 100644
index 0000000000..e38ad4cee0
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidArgument.java
@@ -0,0 +1,77 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.transport.codec.ManagementEncoder;
+import org.apache.qpid.transport.util.Logger;
+
+class QpidArgument extends QpidProperty
+{
+ private final static Logger LOGGER = Logger.get(QpidArgument.class);
+
+ private Object _defaultValue;
+
+ private Direction _direction;
+
+ public void setDirection(String code)
+ {
+ this._direction = Direction.valueOf(code);
+ }
+
+ public Direction getDirection()
+ {
+ return _direction;
+ }
+
+ public void setDefaultValue(Object defaultValue)
+ {
+ this._defaultValue = defaultValue;
+ }
+
+ public Object getDefaultValue()
+ {
+ return _defaultValue;
+ }
+
+ 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();
+ }
+
+ public void validateAndEncode (Object value,ManagementEncoder encoder) throws ValidationException
+ {
+ validate(value);
+ _type.encode(value, encoder);
+ LOGGER.debug("Encoded value %S for argument %s. Type is %s",value,_name,_type);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.java
new file mode 100644
index 0000000000..d0bc470de9
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidAttribute.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.domain.model;
+
+import org.apache.qpid.management.domain.model.type.Type;
+import org.apache.qpid.transport.codec.ManagementDecoder;
+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;
+ LOGGER.debug("Unit : %s", 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(ManagementDecoder decoder)
+ {
+ try {
+ return _type.decode(decoder);
+ } catch(RuntimeException exception) {
+ LOGGER.error(exception,"Unable to decode value for attribute %s",this);
+ throw exception;
+ }
+ }
+
+ @Override
+ public String toString ()
+ {
+ return super.toString()+",type="+_type;
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java
new file mode 100644
index 0000000000..262e17db9a
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java
@@ -0,0 +1,855 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Map.Entry;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+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.Protocol;
+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.QpidService;
+import org.apache.qpid.transport.codec.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+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 2 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);
+ * 2) second state is when schema is injected. In this case 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).
+ *
+ * @author Andrea Gazzarini
+ */
+class QpidClass
+{
+ /**
+ * State interface for this class definition.
+ * Each state is responsible to handle the injection of the object data.
+ *
+ * @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
+ * @param eventDefinitions
+ * @throws UnableToBuildFeatureException when it's not possibile to parse schema and build the class definition.
+ */
+ public void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions,
+ List<MethodOrEventDataTransferObject> eventDefinitions) 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)
+ {
+ schemaRequest();
+ QpidManagedObject instance = getObjectInstance(objectId,false);
+ instance._rawConfigurationData.add(rawData);
+ _state = _schemaRequestedButNotYetInjected;
+ }
+
+ /**
+ * 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)
+ {
+ schemaRequest();
+ QpidManagedObject instance = getObjectInstance(objectId,false);
+ instance._rawConfigurationData.add(rawData);
+ _state = _schemaRequestedButNotYetInjected;
+ }
+
+ /**
+ * This method only throws an illegal state exception because when a schema arrives
+ * this state is no longer valid.
+ */
+ public void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions,
+ List<MethodOrEventDataTransferObject> eventDefinitions) 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)
+ {
+ QpidManagedObject 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)
+ {
+ QpidManagedObject 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<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions,
+ List<MethodOrEventDataTransferObject> eventDefinitions) throws UnableToBuildFeatureException
+ {
+
+ MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[propertyDefinitions.size()+statisticDefinitions.size()];
+ MBeanOperationInfo [] operationsMetadata = new MBeanOperationInfo[methodDefinitions.size()];
+
+ buildAttributes(propertyDefinitions,statisticDefinitions,attributesMetadata);
+ buildMethods(methodDefinitions,operationsMetadata);
+ buildEvents(eventDefinitions);
+
+ _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,operationsMetadata,null);
+
+ // Converting stored object instances into JMX MBean and removing raw instance data.
+ for (Entry<Binary, QpidManagedObject> instanceEntry : _objectInstances.entrySet())
+ {
+ Binary objectId = instanceEntry.getKey();
+ QpidManagedObject instance = instanceEntry.getValue();
+
+ for (Iterator<byte[]> iterator = instance._rawInstrumentationData.iterator(); iterator.hasNext();)
+ {
+ updateInstanceWithInstrumentationData(instance,iterator.next());
+ iterator.remove();
+ }
+
+ for (Iterator<byte[]> iterator = instance._rawConfigurationData.iterator(); iterator.hasNext();)
+ {
+ updateInstanceWithConfigurationData(instance, iterator.next());
+ iterator.remove();
+ }
+
+ JMX_SERVICE.registerObjectInstance(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)
+ {
+ QpidManagedObject 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)
+ {
+ QpidManagedObject instance = getObjectInstance(objectId,true);
+ updateInstanceWithInstrumentationData(instance, rawData);
+ }
+
+ /**
+ * Never called when the class definition has this state.
+ */
+ public void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions,
+ List<MethodOrEventDataTransferObject> eventDefinitions) 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
+ *
+ * @author Andrea Gazzarini
+ */
+ class QpidManagedObject implements DynamicMBean,MBeanRegistration
+ {
+ // After this mbean is registered with the MBean server this collection holds the mbean attributes
+ private Map<String,Object> _attributes = new HashMap<String, Object>();
+ private Binary _objectId;
+
+ // Arrays used for storing raw data before this mbean is registered to mbean server.
+ List<byte[]> _rawInstrumentationData = new ArrayList<byte[]>();
+ List<byte[]> _rawConfigurationData = new ArrayList<byte[]>();
+
+ /**
+ * Builds a new managed object with the given object identifier.
+ *
+ * @param objectId the object identifier.
+ */
+ QpidManagedObject(Binary objectId)
+ {
+ this._objectId = objectId;
+ }
+
+ /**
+ * 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.
+ *
+ * @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);
+ }
+
+ /**
+ * 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);
+ }
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * 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
+ {
+ // TODO : Overloaded methods
+ QpidMethod method = _methods.get(actionName);
+ if (method != null)
+ {
+ try
+ {
+ methodRequest(_objectId, method, params);
+ return null;
+ } catch (ValidationException exception)
+ {
+ throw new MBeanException(exception);
+ }
+ } else {
+ 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
+ {
+ 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;
+ }
+ }
+
+ private final static Logger LOGGER = Logger.get(QpidClass.class);
+ private final static JmxService JMX_SERVICE = new JmxService();
+
+ private final String _name;
+ private final Binary _hash;
+
+ private final QpidPackage _parent;
+
+ Map<String, QpidProperty> _properties = new HashMap<String, QpidProperty>();
+ Map<String, QpidStatistic> _statistics = new HashMap<String, QpidStatistic>();
+ private Map<String, QpidMethod> _methods = new HashMap<String, QpidMethod>();
+
+ private List<QpidProperty> _schemaOrderedProperties = new ArrayList<QpidProperty>();
+ private List<QpidStatistic> _schemaOrderedStatistics= new ArrayList<QpidStatistic>();
+ private MBeanInfo _metadata;
+
+ private final QpidService _service;
+
+ private int _howManyPresenceBitMasks;
+
+ Map<Binary, QpidManagedObject> _objectInstances = new HashMap<Binary, QpidManagedObject>();
+ 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.
+ */
+ QpidClass(String className, Binary hash, QpidPackage parentPackage)
+ {
+ this._name = className;
+ this._parent = parentPackage;
+ this._hash = hash;
+ this._service = new QpidService(_parent.getOwnerId());
+ LOGGER.debug(
+ "<QMAN-200017> : Class definition has been built (without schema) for %s::%s.%s",
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name);
+ }
+
+ /**
+ * 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("<QMAN-200015> : Incoming instrumentation data for %s::%s.%s.%s",
+ _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("<QMAN-200016> : Incoming configuration data for %s::%s.%s.%s",
+ _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.
+ * @param eventDefinitions events metadata.
+ * @throws UnableToBuildFeatureException when some error occurs while parsing the incoming schema.
+ */
+ void setSchema (
+ List<Map<String, Object>> propertyDefinitions,
+ List<Map<String, Object>> statisticDefinitions,
+ List<MethodOrEventDataTransferObject> methodDefinitions,
+ List<MethodOrEventDataTransferObject> eventDefinitions) throws UnableToBuildFeatureException
+ {
+ LOGGER.info("<QMAN-000012> : Incoming schema for %s::%s.%s",_parent.getOwnerId(),_parent.getName(),_name);
+ _state.setSchema(propertyDefinitions, statisticDefinitions, methodDefinitions, eventDefinitions);
+ }
+
+ /**
+ * 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<Map<String, Object>> props,
+ List<Map<String, Object>> stats,
+ MBeanAttributeInfo[] attributes) throws UnableToBuildFeatureException
+ {
+ int index = 0;
+ int howManyOptionalProperties = 0;
+
+ for (Map<String, Object> 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(
+ "<QMAN-200017> : Property definition for %s::%s.%s has been built.",
+ _parent.getName(),
+ _name,
+ property);
+ }
+
+ _howManyPresenceBitMasks = (int)Math.ceil((double)howManyOptionalProperties / 8);
+
+ LOGGER.debug(
+ "<QMAN-200018> : Class %s::%s.%s has %s optional properties.",
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name,
+ _howManyPresenceBitMasks);
+
+ for (Map<String, Object> 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(
+ "<QMAN-200019> : Statistic definition for %s::%s.%s 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.
+ */
+ QpidManagedObject getObjectInstance(Binary objectId, boolean registration)
+ {
+ QpidManagedObject objectInstance = _objectInstances.get(objectId);
+ if (objectInstance == null)
+ {
+ objectInstance = new QpidManagedObject(objectId);
+ _objectInstances.put(objectId, objectInstance);
+ if (registration)
+ {
+ JMX_SERVICE.registerObjectInstance(objectInstance,_parent.getOwnerId(),_parent.getName(),_name,objectId);
+ }
+ }
+ return objectInstance;
+ }
+
+ /**
+ * Internal method used for building event statistics defintions.
+ *
+ * @param definitions the properties map contained in the incoming schema.
+ * @throws UnableToBuildFeatureException when it's not possibile to build one or more definitions.
+ */
+ void buildEvents (List<MethodOrEventDataTransferObject> eventDefinitions)
+ {
+ // TODO
+ }
+
+ /**
+ * 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<MethodOrEventDataTransferObject> 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);
+ }
+ }
+
+ private void schemaRequest()
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(100);
+ ManagementEncoder encoder = new ManagementEncoder(buffer);
+ buffer.put(Protocol.SCHEMA_REQUEST_FIRST_FOUR_BYTES);
+
+ // TODO
+ encoder.writeSequenceNo(1000);
+ encoder.writeStr8(_parent.getName());
+ encoder.writeStr8(_name);
+ _hash.encode(encoder);
+ buffer.rewind();
+ try
+ {
+ _service.connect();
+ _service.sendCommandMessage(buffer);
+ _service.sync();
+ } catch (Exception exception)
+ {
+ exception.printStackTrace();
+ // TODO
+ // Log.logSchemaRequestNotSent(exception,
+ // _parent.getOwnerId(),_parent.getName(), _name);
+ } finally
+ {
+ _service.close();
+ }
+ }
+
+ /**
+ * 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 ValidationException
+ */
+ private void methodRequest(Binary objectId,QpidMethod method,Object [] parameters) throws ValidationException
+ {
+ ByteBuffer buffer = ByteBuffer.allocate(1000);
+ ManagementEncoder encoder = new ManagementEncoder(buffer);
+ buffer.put(Protocol.METHOD_REQUEST_FIRST_FOUR_BYTES);
+ encoder.writeSequenceNo(0);
+ objectId.encode(encoder);
+ encoder.writeStr8(_parent.getName());
+ encoder.writeStr8(_name);
+ _hash.encode(encoder);
+ encoder.writeStr8(method.getName());
+ method.encodeParameters(parameters,encoder);
+
+ buffer.rewind();
+ try
+ {
+ _service.connect();
+ _service.sendCommandMessage(buffer);
+ //_service.sync();
+ } catch (Exception exception)
+ {
+ exception.printStackTrace();
+ // TODO
+ // Log.logSchemaRequestNotSent(exception,
+ // _parent.getOwnerId(),_parent.getName(), _name);
+ } 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.
+ */
+ private void updateInstanceWithConfigurationData(QpidManagedObject instance,byte [] rawData)
+ {
+ ManagementDecoder decoder = new ManagementDecoder();
+ 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("Unable to decode value for %s::%s::%s", _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.
+ */
+ private void updateInstanceWithInstrumentationData(QpidManagedObject instance,byte [] rawData)
+ {
+ ManagementDecoder decoder = new ManagementDecoder();
+ 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("Unable to decode value for %s::%s::%s", _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)
+ {
+ QpidManagedObject toBeRemoved = _objectInstances.remove(objectId);
+ if (toBeRemoved != null)
+ {
+ JMX_SERVICE.unregisterObjectInstance(_parent.getOwnerId(),_parent.getName(),_name,toBeRemoved._objectId);
+ }
+ }
+
+ /**
+ * Deregisters all the object instances and release all previously acquired resources.
+ */
+ void releaseResources ()
+ {
+ for (Iterator<Binary> iterator = _objectInstances.keySet().iterator(); iterator.hasNext();)
+ {
+ Binary objectId = iterator.next();
+ JMX_SERVICE.unregisterObjectInstance(_parent.getOwnerId(),_parent.getName(),_name,objectId);
+ iterator.remove();
+ LOGGER.debug(
+ "%s.%s.%s object instance has been removed from broker %s",
+ _parent.getName(),
+ _name,objectId,
+ _parent.getOwnerId());
+ }
+ _service.close();
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java
new file mode 100644
index 0000000000..200791bb93
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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;
+
+class QpidEvent extends QpidFeature
+{
+ // NOT YET IMPLEMENTED
+}
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java
new file mode 100644
index 0000000000..5fccb0a858
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeature.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model;
+
+/**
+ * Layer Supertype for all qpid management features.
+ *
+ * @author Andrea Gazzarini
+ */
+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.
+ */
+ 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/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java
new file mode 100644
index 0000000000..4bac16452c
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java
@@ -0,0 +1,444 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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;
+
+/**
+ * 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 :
+ *
+ * <br>- QpidFeatureBuilder builder = QpidFeature.createPropertyBuilder(...);
+ * <br>- builder.build();
+ * <br>- QpidProperty property = (QpidProperty) builder.getQpidFeature();
+ * <br>- MBeanAttributeInfo managementAttributeInfo = (MBeanAttributeInfo)builder.getManagementFeature();
+ *
+ * <br>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<Attribute> _mandatoryAttributes = new ArrayList<Attribute>();
+
+ /**
+ * 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<String, Object> 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<String, Object> 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<String, Object> argumentAttribute : _featureDefinition.entrySet())
+ {
+ String key = argumentAttribute.getKey();
+ if ("default".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<String,Object> 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("name"),(String) definition.get("desc"));
+
+ List<Map<String,Object>> args = _methodOrEventDefinition.getArgumentsDefinitions();
+
+ List<MBeanParameterInfo> signature = new LinkedList<MBeanParameterInfo>();
+
+ for (Map<String,Object> 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 <String, Object> _featureDefinition;
+ private final MethodOrEventDataTransferObject _methodOrEventDefinition;
+ private State _state;
+
+ static QpidFeatureBuilder createPropertyBuilder(Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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
+ {
+ _state.build();
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java
new file mode 100644
index 0000000000..4d4918e45f
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidMethod.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.LinkedList;
+import java.util.List;
+
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+/**
+ * Qpid method definition.
+ * An entity describing an invocation that can be made on a managed object instance.
+ *
+ * @author Andrea Gazzarini
+ */
+class QpidMethod extends QpidFeature
+{
+ /** Argument list */
+ List<QpidArgument> arguments = new LinkedList<QpidArgument>();
+
+ /**
+ * 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 <method name>(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.
+ * Also provide a validation of the given values according to the invariants defined for each argument.
+ * Note that only Input/Output and Output parameters are encoded.
+ *
+ * @param parameters the parameters values.
+ * @param encoder the encoder used for encoding.
+ * @throws ValidationException when one of the given values is violating an argument invariant.
+ */
+ void encodeParameters (Object[] parameters, ManagementEncoder encoder) throws ValidationException
+ {
+ int index = 0;
+ for (QpidArgument argument : arguments)
+ {
+ if (argument.getDirection() != Direction.O)
+ {
+ argument.validateAndEncode(parameters[index++],encoder);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java
new file mode 100644
index 0000000000..524121afe5
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java
@@ -0,0 +1,227 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.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)
+ {
+ QpidClassIdentity identity = (QpidClassIdentity) obj;
+ return name.equals(identity.name) && hash.equals(identity.hash);
+ }
+ }
+
+ private String _name;
+ private DomainModel _parent;
+ private Map<QpidClassIdentity, QpidClass> _classes = new HashMap<QpidClassIdentity, QpidClass>();
+
+ /**
+ * 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<Map<String, Object>> properties,
+ List<Map<String, Object>> statistics,
+ List<MethodOrEventDataTransferObject> methods,
+ List<MethodOrEventDataTransferObject> events) throws UnableToBuildFeatureException
+ {
+ getQpidClass(className,classHash,true).setSchema(properties,statistics,methods, events);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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 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();
+ }
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidProperty.java
new file mode 100644
index 0000000000..8b2544af1c
--- /dev/null
+++ b/java/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.configuration.Configuration;
+import org.apache.qpid.management.domain.model.type.Type;
+import org.apache.qpid.transport.codec.ManagementDecoder;
+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(ManagementDecoder decoder,byte [] presenceBitMasks);
+ }
+
+ /**
+ * Decoder used for decoding incoming values for this optional property.
+ */
+ final Decoder _optionalPropertyDecoder = new Decoder() {
+
+ public Object decodeValue (ManagementDecoder 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 (ManagementDecoder 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("Validator %s for type %s successfully installed." ,validatorClass.getName(), type);
+ } catch(Exception exception) {
+ _validator = EMPTY_VALIDATOR;
+ LOGGER.debug("No validator was found for type %s. The default (empty) validator will be used." , 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(ManagementDecoder 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;
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/QpidStatistic.java
new file mode 100644
index 0000000000..37a652c098
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java
new file mode 100644
index 0000000000..59721240d0
--- /dev/null
+++ b/java/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 : "Not available" ,exception);
+ }
+
+ /**
+ * Builds a new UnableToBuildFeatureException with the specified message.
+ *
+ * @param message the detail message.
+ */
+ UnableToBuildFeatureException(String message)
+ {
+ super(message);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/ValidationException.java
new file mode 100644
index 0000000000..3b117e5b9d
--- /dev/null
+++ b/java/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/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/AbsTime.java
new file mode 100644
index 0000000000..27bfa62e2b
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class AbsTime extends Type
+{
+ public AbsTime()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readUint64();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint64((Long)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java
new file mode 100644
index 0000000000..d6d25534d8
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.ManagementEncoder;
+
+/**
+ * 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;
+
+ // instance identifider.
+ private final UUID uuid;
+
+ // 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 byte [] bytes;
+ 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;
+ uuid = UUID.randomUUID();
+ }
+
+ @Override
+ public int hashCode ()
+ {
+ return state.hashCode();
+ }
+
+ @Override
+ public boolean equals (Object obj)
+ {
+ try
+ {
+ Binary binary = (Binary)obj;
+ return Arrays.equals(bytes, binary.bytes);
+ } catch (Exception exception)
+ {
+ 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(ManagementEncoder encoder)
+ {
+ encoder.writeBin128(bytes);
+ }
+
+ // TODO
+ @Override
+ public String toString ()
+ {
+ return uuid.toString();
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Boolean.java
new file mode 100644
index 0000000000..89867bd4c4
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Boolean extends Type
+{
+ public Boolean()
+ {
+ super(java.lang.Boolean.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return (decoder.readUint8() == 1);
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint8( ((java.lang.Boolean)value) ? (short)1 : (short)0);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/DeltaTime.java
new file mode 100644
index 0000000000..85724f34c8
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class DeltaTime extends Type
+{
+ public DeltaTime()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readUint64();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint64((Long)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.java
new file mode 100644
index 0000000000..f7d6101d3f
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Map.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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Map extends Type
+{
+ public Map()
+ {
+ super(java.util.Map.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readMap();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeMap((java.util.Map<String, Object>)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/ObjectReference.java
new file mode 100644
index 0000000000..784571e0c0
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class ObjectReference extends Type
+{
+ public ObjectReference()
+ {
+ super(byte[].class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readBin128();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ ((Binary)value).encode(encoder);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Str16.java
new file mode 100644
index 0000000000..7ab1c667f0
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Str16 extends Type
+{
+ public Str16()
+ {
+ super(String.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readStr16();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeStr16((String)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Str8.java
new file mode 100644
index 0000000000..f8f48bc8ec
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Str8 extends Type
+{
+ public Str8()
+ {
+ super(String.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readStr8();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeStr8((String)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.java
new file mode 100644
index 0000000000..786f8d9957
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Type.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.domain.model.type;
+
+import org.apache.qpid.transport.codec.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+/**
+ * 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(ManagementDecoder 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 getClass() == obj.getClass();
+ }
+
+ @Override
+ public int hashCode ()
+ {
+ return getClass().hashCode();
+ }
+
+ public abstract void encode (Object value, ManagementEncoder encoder);
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint16.java
new file mode 100644
index 0000000000..31aeab954d
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Uint16 extends Type
+{
+ public Uint16()
+ {
+ super(Integer.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return new Integer(decoder.readUint16());
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint16((Integer)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint32.java
new file mode 100644
index 0000000000..deb9772953
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Uint32 extends Type
+{
+ public Uint32()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return new Long(decoder.readUint32());
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint32((Integer)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint64.java
new file mode 100644
index 0000000000..9d414cf225
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Uint64 extends Type
+{
+ public Uint64()
+ {
+ super(Long.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return new Long(decoder.readUint64());
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint64((Integer)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uint8.java
new file mode 100644
index 0000000000..681537c48f
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Uint8 extends Type
+{
+ public Uint8()
+ {
+ super(Short.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return new Short(decoder.readUint8());
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUint8((Short)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java b/java/client/src/main/java/org/apache/qpid/management/domain/model/type/Uuid.java
new file mode 100644
index 0000000000..74e0337173
--- /dev/null
+++ b/java/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.ManagementDecoder;
+import org.apache.qpid.transport.codec.ManagementEncoder;
+
+public class Uuid extends Type
+{
+ public Uuid()
+ {
+ super(UUID.class);
+ }
+
+ @Override
+ public Object decode (ManagementDecoder decoder)
+ {
+ return decoder.readUuid();
+ }
+
+ @Override
+ public void encode (Object value, ManagementEncoder encoder)
+ {
+ encoder.writeUuid((UUID)value);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java b/java/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java
new file mode 100644
index 0000000000..d5fdce09fc
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/services/BrokerMessageListener.java
@@ -0,0 +1,181 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.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.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.ManagementDecoder;
+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(
+ "<QMAN-200006> : New incoming message has been received. Message content : %s",
+ Arrays.toString(message.array()));
+ }
+ }
+
+ // Debugs all the configured handlers.
+ static void debugConfiguredHandlers (Map<Character, IMessageHandler> _handlers)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ for (Entry<Character, IMessageHandler> entry : _handlers.entrySet())
+ {
+ LOGGER.debug("<QMAN-200007> : \"%s\" opcode is associated to handler %s",entry.getKey(),entry.getValue());
+ }
+ }
+ }
+ }
+
+ Map<Character, IMessageHandler> _handlers = new HashMap<Character, IMessageHandler>();
+ 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 message)
+ {
+ try
+ {
+ ByteBuffer buffer = message.readData();
+
+ // TODO : Should be better...!
+ String magicNumber = new String(new byte[] {buffer.get(),buffer.get(),buffer.get()});
+ if (!Protocol.MAGIC_NUMBER.equals(magicNumber))
+ {
+ LOGGER.error(
+ "<QMAN-100003> : Message processing failure : incoming message contains a bad magic number (%s) " +
+ "and therefore will be discaded.",
+ magicNumber);
+ return;
+ }
+
+ char opcode = (char)buffer.get();
+
+ IMessageHandler handler = _handlers.get(opcode);
+ if (handler != null)
+ {
+ ManagementDecoder decoder = new ManagementDecoder();
+ decoder.init(buffer);
+
+ LOGGER.debug(
+ "<QMAN-200008> : Incoming message with \"%s\" as opcode will be forwarded to %s for processing.",
+ opcode,
+ handler);
+
+ handler.process(decoder,decoder.readSequenceNo());
+ } else
+ {
+ LOGGER.warn(
+ "<QMAN-300001> : No handler has been configured for processing messages with \"%s\" as opcode. " +
+ "This message will be discarded.",
+ opcode);
+
+ Log.debugConfiguredHandlers(_handlers);
+ }
+ } catch(IOException exception)
+ {
+ LOGGER.error(
+ exception,
+ "<QMAN-100004> : Message I/O failure : unable to read byte message content and therefore it will be discarded.");
+ } catch(Exception exception)
+ {
+ LOGGER.error(
+ exception,
+ "<QMAN-100005> : Message processing failure : unknown exception; see logs for more details.");
+ }
+ }
+
+ /**
+ * 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<Character, IMessageHandler> handlers)
+ {
+ for (Entry<Character, IMessageHandler> 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,
+ "<QMAN-100006> : Message handler configured for opcode %s thrown an exception in initialization and therefore will be discarded.",
+ opcode);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java b/java/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java
new file mode 100644
index 0000000000..b2f1b19a6c
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/services/ManagementClient.java
@@ -0,0 +1,256 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.QpidException;
+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
+ */
+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;
+
+ /**
+ * Builds a new <code>ManagementClient</code> 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)
+ {
+ _service = new QpidService(brokerId);
+ _domainModel = new DomainModel(brokerId);
+ _managementQueueName = Configuration.getInstance().getManagementQueueName();
+ _methodReplyQueueName = Configuration.getInstance().getMethodReplyQueueName();
+ }
+
+ /**
+ * 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(
+ "<QMAN-000033> : The shutdown sequence has been initiated for management client connected with broker %s",
+ _domainModel.getBrokerId());
+
+ removeMethodReplyConsumer();
+ destroyAndUnbingMethodReplyQueue();
+
+ removeManagementConsumer();
+ destroyAndUnbingManagementQueue();
+
+ _domainModel.releaseResources();
+
+ _service.close();
+
+ LOGGER.info(
+ "<QMAN-000034> : Management client connected with broker %s shut down successfully.",
+ _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(
+ "<QMAN-000039> : Method-reply queue consumer has been successfully installed and bound on broker %s.",
+ _domainModel.getBrokerId());
+ }
+
+ /**
+ * Registers a consumer (listener) on the management queue.
+ */
+ private void registerConsumerOnManagementQueue () throws QpidException
+ {
+ BrokerMessageListener managementChannelListener = new BrokerMessageListener(_domainModel);
+ managementChannelListener.setHandlers(Configuration.getInstance().getManagementQueueHandlers());
+ _service.createSubscription(_managementQueueName, _managementQueueName, managementChannelListener);
+
+ LOGGER.info(
+ "<QMAN-000038> : Management queue consumer has been successfully installed and bound on broker %s.",
+ _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(
+ "<QMAN-000037> : Management queue with name %s has been successfully declared and bound on broker %s.",
+ _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(
+ "<QMAN-000037> : Method-reply queue with name %s has been successfully declared and bound on broker %s.",
+ _methodReplyQueueName,
+ _domainModel.getBrokerId());
+ }
+
+ /**
+ * Removes the method-reply queue consumer.
+ */
+ private void removeMethodReplyConsumer()
+ {
+ _service.removeSubscription(_methodReplyQueueName);
+
+ LOGGER.info(
+ "<QMAN-000034> : Consumer %s has been removed from broker %s.",
+ _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(
+ "<QMAN-000035> : Queue %s has been removed from broker %s.",
+ _methodReplyQueueName,
+ _domainModel.getBrokerId());
+ }
+
+ /**
+ * Removes the management queue consumer.
+ */
+ private void removeManagementConsumer()
+ {
+ _service.removeSubscription(_managementQueueName);
+
+ LOGGER.info(
+ "<QMAN-000036> : Consumer %s has been removed from broker %s.",
+ _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(
+ "<QMAN-000037> : Queue %s has been removed from broker %s.",
+ _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();
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java b/java/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java
new file mode 100644
index 0000000000..00dbec261d
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.Map.Entry;
+
+import org.apache.qpid.management.configuration.BrokerConnectionData;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.configuration.ConfigurationException;
+import org.apache.qpid.management.configuration.Configurator;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Main entry point for starting Q-Man application.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QMan
+{
+ private final static Logger LOGGER = Logger.get(QMan.class);
+ private final static List<ManagementClient> managementClients = new ArrayList<ManagementClient>();
+
+ /**
+ * Main method used for starting Q-Man.
+ *
+ * @param args the command line arguments.
+ */
+ public static void main (String[] args) throws IOException
+ {
+ // SHUTDOWN HOOK
+ Runtime.getRuntime().addShutdownHook(new Thread(){
+ @Override
+ public void run ()
+ {
+ LOGGER.info("<QMAN-000006> : Shutting down Q-Man...");
+ for (ManagementClient client : managementClients)
+ {
+ client.shutdown();
+ }
+ LOGGER.info("<QMAN-000007> : Q-Man shut down.");
+ }
+ });
+
+ LOGGER.info("<QMAN-000001> : Starting Q-Man...");
+ LOGGER.info("<QMAN-000002> : Reading Q-Man configuration...");
+
+ Configurator configurator = new Configurator();
+ try
+ {
+ configurator.configure();
+ LOGGER.info("<QMAN-000003> : Creating management client(s)...");
+ for (Entry<UUID, BrokerConnectionData> entry : Configuration.getInstance().getConnectionInfos())
+ {
+ UUID brokerId = entry.getKey();
+ BrokerConnectionData data = entry.getValue();
+ try
+ {
+ ManagementClient client = new ManagementClient(brokerId,data);
+ managementClients.add(client);
+ client.estabilishFirstConnectionWithBroker();
+
+ LOGGER.info("<QMAN-000004> : Management client for broker %s successfully connected.",brokerId);
+ } catch(StartupFailureException exception) {
+ LOGGER.error(exception, "<QMAN-100001>: Cannot connect to broker %s on %s:%s",brokerId,data.getHost(),data.getPort());
+ }
+ }
+ LOGGER.info("<QMAN-000004> : Q-Man open for e-business.");
+
+ // TODO : console enhancement (i.e. : connect another broker)
+ System.out.println("Type \"q\" to quit.");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ while ( !"q".equals(reader.readLine()) ){
+ }
+ } catch(ConfigurationException exception) {
+ LOGGER.error(exception, "<QMAN-100002> : Q-Man was unable to startup correctly : a configuration error occurred.");
+ System.exit(1);
+ }
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java b/java/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java
new file mode 100644
index 0000000000..92689eba52
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/management/domain/services/QpidService.java
@@ -0,0 +1,270 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * 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.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+import org.apache.qpid.QpidException;
+import org.apache.qpid.management.Constants;
+import org.apache.qpid.management.Names;
+import org.apache.qpid.management.configuration.Configuration;
+import org.apache.qpid.management.configuration.QpidDatasource;
+import org.apache.qpid.nclient.Connection;
+import org.apache.qpid.nclient.Session;
+import org.apache.qpid.nclient.util.MessageListener;
+import org.apache.qpid.nclient.util.MessagePartListenerAdapter;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageCreditUnit;
+import org.apache.qpid.transport.Option;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Qpid Broker facade.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidService
+{
+ private final static Logger LOGGER = Logger.get(QpidService.class);
+
+ // Inner static class used for logging and avoid conditional logic (isDebugEnabled()) duplication.
+ private static class Log
+ {
+ /**
+ * Logs the content f the message.
+ * This will be written on log only if DEBUG level is enabled.
+ *
+ * @param messageContent the raw content of the message.
+ */
+ static void logMessageContent(byte [] messageContent)
+ {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(
+ "<QMAN-200001> : Message has been sent to management exchange. Message content : %s",
+ Arrays.toString(messageContent));
+ }
+ }
+
+ /**
+ * Logs the content f the message.
+ * This will be written on log only if DEBUG level is enabled.
+ *
+ * @param messageContent the raw content of the message.
+ */
+ static void logMessageContent(ByteBuffer messageContent)
+ {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(
+ "<QMAN-200002> : Message has been sent to management exchange.");
+ }
+ }
+ }
+
+ private UUID _brokerId;
+ private Connection _connection;
+ private Session _session;
+
+ /**
+ * 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);
+ _session = _connection.createSession(Constants.NO_EXPIRATION);
+ }
+
+ /**
+ * 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;
+ } 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)
+ {
+ _session.messageSubscribe(
+ queueName,
+ destinationName,
+ Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED,
+ Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE,
+ new MessagePartListenerAdapter(listener), null);
+
+ _session.messageFlow(destinationName, MessageCreditUnit.BYTE, Session.MESSAGE_FLOW_MAX_BYTES);
+ _session.messageFlow(destinationName, MessageCreditUnit.MESSAGE, Integer.MAX_VALUE);
+
+ LOGGER.debug(
+ "<QMAN-200003> : New subscription between queue %s and destination %s has been 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(
+ "<QMAN-200026> : Subscription named %s has been removed from remote broker.",
+ 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("<QMAN-200004> : New queue with name %s has been 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("<QMAN-2000025> : Queue with name %s has been 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(
+ "<QMAN-200005> : New binding with %s as routing key has been declared between queue %s and exchange %s.",
+ 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(
+ "<QMAN-200005> : Binding with %s as routing key has been removed between queue %s and exchange %s.",
+ routingKey,queueName,
+ exchangeName);
+ }
+
+ /**
+ * Sends a command message with the given data on the management queue.
+ *
+ * @param messageData the command message content.
+ */
+ public void sendCommandMessage(byte [] messageData)
+ {
+ _session.messageTransfer(
+ Names.MANAGEMENT_EXCHANGE,
+ MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ Configuration.getInstance().getCommandMessageHeader(),
+ messageData);
+
+ Log.logMessageContent (messageData);
+ }
+
+ /**
+ * Sends a command message with the given data on the management queue.
+ *
+ * @param messageData the command message content.
+ */
+ public void sendCommandMessage(ByteBuffer messageData)
+ {
+ _session.messageTransfer(
+ Names.MANAGEMENT_EXCHANGE,
+ MessageAcceptMode.EXPLICIT,
+ MessageAcquireMode.PRE_ACQUIRED,
+ Configuration.getInstance().getCommandMessageHeader(),
+ messageData);
+
+ Log.logMessageContent (messageData);
+ }
+} \ No newline at end of file
diff --git a/java/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java b/java/client/src/main/java/org/apache/qpid/management/domain/services/StartupFailureException.java
new file mode 100644
index 0000000000..9da8832624
--- /dev/null
+++ b/java/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