diff options
| author | Arnaud Simon <arnaudsimon@apache.org> | 2008-09-29 12:02:54 +0000 |
|---|---|---|
| committer | Arnaud Simon <arnaudsimon@apache.org> | 2008-09-29 12:02:54 +0000 |
| commit | 32c96c8a723712b74a3b7b2331cc3b1b75d6cc3e (patch) | |
| tree | 8a85f9d9ea3b0a0ac617d89e884077708b8983b4 /java/client/src | |
| parent | 5d140890605743357347a0c0326ed4cf78117d8d (diff) | |
| download | qpid-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')
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 |
