diff options
author | Arnaud Simon <arnaudsimon@apache.org> | 2008-10-22 10:19:50 +0000 |
---|---|---|
committer | Arnaud Simon <arnaudsimon@apache.org> | 2008-10-22 10:19:50 +0000 |
commit | c62e7915339bf8800eeb06db3c9a3409293467f6 (patch) | |
tree | d2b981f6ebddbfe09287b8a389c4554b115b1f08 /qpid/java/management | |
parent | 6c13adb0ac208e0b61fb9c3f9d21bd0658c6a2f3 (diff) | |
download | qpid-python-c62e7915339bf8800eeb06db3c9a3409293467f6.tar.gz |
QPID-1357: applied qman_22102008_events_handling.patch
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk@707016 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/management')
21 files changed, 1688 insertions, 345 deletions
diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/Names.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/Names.java index 8ab9e13d4f..dde7715509 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/Names.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/Names.java @@ -29,13 +29,13 @@ public interface Names { /** Name of the qpid management exchange. */ String MANAGEMENT_EXCHANGE = "qpid.management"; - String MANAGEMENT_ROUTING_KEY = "mgmt.#"; + String MANAGEMENT_ROUTING_KEY = "console.#"; String MANAGEMENT_QUEUE_PREFIX = "management."; String METHOD_REPLY_QUEUE_PREFIX = "reply."; String AMQ_DIRECT_QUEUE = "amq.direct"; - String AGENT_ROUTING_KEY = "agent.0"; + String AGENT_ROUTING_KEY = "agent.1.0"; String BROKER_ROUTING_KEY = "broker"; @@ -49,4 +49,4 @@ public interface Names 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/qpid/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java index 169e28e26e..222b5d8aa6 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/Protocol.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.management; +import com.sun.org.apache.xerces.internal.jaxp.validation.ErrorHandlerAdaptor; + /** * Protocol defined constants. * @@ -27,7 +29,7 @@ package org.apache.qpid.management; */ public interface Protocol { - String MAGIC_NUMBER = "AM1"; + String MAGIC_NUMBER = "AM2"; char SCHEMA_REQUEST_OPCODE = 'S'; char SCHEMA_RESPONSE_OPCODE = Character.toLowerCase(SCHEMA_REQUEST_OPCODE); @@ -37,5 +39,9 @@ public interface Protocol char INSTRUMENTATION_CONTENT_RESPONSE_OPCODE = 'i'; char CONFIGURATION_CONTENT_RESPONSE_OPCDE = 'c'; + char EVENT_CONTENT_RESPONSE_OPCDE = 'e'; char INSTR_AND_CONFIG_CONTENT_RESPONSE_OPCODE = 'g'; -}
\ No newline at end of file + + int CLASS = 1; + int EVENT = 2; +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java index 3cd76c06e9..defedf0a8d 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/configuration/Configurator.java @@ -29,6 +29,7 @@ import javax.xml.parsers.SAXParserFactory; import org.apache.qpid.management.Names; import org.apache.qpid.management.Protocol; import org.apache.qpid.management.domain.handler.impl.ConfigurationMessageHandler; +import org.apache.qpid.management.domain.handler.impl.EventContentMessageHandler; import org.apache.qpid.management.domain.handler.impl.InstrumentationMessageHandler; import org.apache.qpid.management.domain.handler.impl.MethodResponseMessageHandler; import org.apache.qpid.management.domain.handler.impl.SchemaResponseMessageHandler; @@ -160,6 +161,11 @@ public class Configurator extends DefaultHandler new MessageHandlerMapping( Protocol.CONFIGURATION_CONTENT_RESPONSE_OPCDE, ConfigurationMessageHandler.class.getName())); + + Configuration.getInstance().addManagementMessageHandlerMapping( + new MessageHandlerMapping( + Protocol.EVENT_CONTENT_RESPONSE_OPCDE, + EventContentMessageHandler.class.getName())); } /** @@ -171,4 +177,4 @@ public class Configurator extends DefaultHandler { return Names.CONFIGURATION_FILE_NAME; } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java new file mode 100644 index 0000000000..0a9e8138da --- /dev/null +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/EventContentMessageHandler.java @@ -0,0 +1,51 @@ +/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.handler.impl;
+
+import org.apache.qpid.management.domain.handler.base.BaseMessageHandler;
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.transport.codec.ManagementDecoder;
+
+/**
+ * Base class for content indication message handlers.
+ *
+ * @author Andrea Gazzarini
+ */
+public class EventContentMessageHandler extends BaseMessageHandler
+{
+ /**
+ * Processes the income message.
+ *
+ * @param decoder the decoder used to parse the message.
+ * @param sequenceNumber the sequence number of the message.
+ */
+ public final void process (ManagementDecoder decoder, int sequenceNumber)
+ {
+ String packageName = decoder.readStr8();
+ String eventName = decoder.readStr8();
+ Binary eventHash = new Binary(decoder.readBin128());
+ long timeStampOfCurrentSample = decoder.readDatetime();
+ int severity = decoder.readUint8();
+ byte[] argumentsData = decoder.readReaminingBytes();
+
+ _domainModel.addEventRawData(packageName, eventName, eventHash, argumentsData,timeStampOfCurrentSample,severity);
+ }
+}
diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java index 7a0ee556d2..fdee2f2f2d 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/SchemaResponseMessageHandler.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import org.apache.qpid.management.Names; +import org.apache.qpid.management.Protocol; import org.apache.qpid.management.domain.handler.base.BaseMessageHandler; import org.apache.qpid.management.domain.model.type.Binary; import org.apache.qpid.transport.codec.ManagementDecoder; @@ -38,6 +39,66 @@ import org.apache.qpid.transport.codec.ManagementDecoder; */ public class SchemaResponseMessageHandler extends BaseMessageHandler { + interface IProcessor + { + void process(ManagementDecoder decoder); + } + + final IProcessor classDefinitionProcessor = new IProcessor() + { + @Override + public void process(ManagementDecoder decoder) + { + try + { + String packageName = decoder.readStr8(); + String className = decoder.readStr8(); + + Binary schemaHash = new Binary(decoder.readBin128()); + + int howManyProperties = decoder.readUint16(); + int howManyStatistics = decoder.readUint16(); + int howManyMethods = decoder.readUint16(); + + _domainModel.addSchema( + packageName, + className, + schemaHash, + getAttributes(decoder, howManyProperties), + getAttributes(decoder, howManyStatistics), + getMethods(decoder, howManyMethods)); + } catch(Exception exception) + { + _logger.error(exception,"<QMAN-100007> : Q-Man was unable to process the schema response message."); + } + + } + }; + + final IProcessor eventDefinitionProcessor = new IProcessor() + { + @Override + public void process(ManagementDecoder decoder) + { + try + { + String packageName = decoder.readStr8(); + String className = decoder.readStr8(); + Binary hash = new Binary(decoder.readBin128()); + int howManyArguments = decoder.readUint16(); + + _domainModel.addEventSchema( + packageName, + className, + hash, + getAttributes(decoder, howManyArguments)); + } catch(Exception exception) + { + _logger.error(exception,"<QMAN-100007> : Q-Man was unable to process the schema response message."); + } + } + }; + /** * Processes an incoming schema response. * This will be used for building the corresponding class definition. @@ -49,29 +110,28 @@ public class SchemaResponseMessageHandler extends BaseMessageHandler { 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)); + int classKind = decoder.readUint8(); + switch(classKind) + { + case Protocol.CLASS : + { + classDefinitionProcessor.process(decoder); + break; + } + case Protocol.EVENT : + { + eventDefinitionProcessor.process(decoder); + break; + } + default : + { + _logger.error("<QMAN-100035> : Q-Man was unable to process the schema response message (reason : unknown class kind %s).",classKind); + } + } } catch(Exception exception) { _logger.error(exception,"<QMAN-100007> : Q-Man was unable to process the schema response message."); - } + } } /** @@ -81,10 +141,10 @@ public class SchemaResponseMessageHandler extends BaseMessageHandler * @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>> getAttributes(ManagementDecoder decoder,int howMany) { - List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(howManyProperties); - for (int i = 0; i < howManyProperties; i++ ) + List<Map<String, Object>> result = new ArrayList<Map<String, Object>>(howMany); + for (int i = 0; i < howMany; i++ ) { result.add(decoder.readMap()); } @@ -92,23 +152,6 @@ public class SchemaResponseMessageHandler extends BaseMessageHandler } /** - * 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. @@ -155,4 +198,4 @@ public class SchemaResponseMessageHandler extends BaseMessageHandler } return result; } - }
\ No newline at end of file + } diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java index 8ebd667893..6bd9d22014 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/DomainModel.java @@ -73,7 +73,6 @@ public class DomainModel * @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( @@ -82,11 +81,31 @@ public class DomainModel Binary classHash, List<Map<String, Object>> properties, List<Map<String, Object>> statistics, - List<MethodOrEventDataTransferObject> methods, - List<MethodOrEventDataTransferObject> events) throws UnableToBuildFeatureException + List<MethodOrEventDataTransferObject> methods) throws UnableToBuildFeatureException { QpidPackage qpidPackage = getPackageByName(packageName); - qpidPackage.addClassDefinition(className,classHash,properties,statistics,methods, events); + qpidPackage.addClassDefinition(className,classHash,properties,statistics,methods); + } + + /** + * Adds the specified schema to this domain model. + * + * @param packageName the package name. + * @param className the class name. + * @param classHash the class schema hash. + * @param properties the class properties. + * @param statistics the class statistics. + * @param methods the class methods. + * @throws UnableToBuildFeatureException + */ + public void addEventSchema( + String packageName, + String className, + Binary classHash, + List<Map<String, Object>> arguments) throws UnableToBuildFeatureException + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.addEventDefinition(className,classHash,arguments); } /** @@ -134,6 +153,18 @@ public class DomainModel qpidPackage.setObjectInstanceInstrumentationRawData(className,classHash,objectId,rawData); } + public void addEventRawData ( + String packageName, + String eventName, + Binary eventHash, + byte[] rawData, + long currentTimestamp, + int severity) + { + QpidPackage qpidPackage = getPackageByName(packageName); + qpidPackage.setEventInstanceRawData(eventName,eventHash,rawData,currentTimestamp,severity); + } + /** * Adds the given configuration data (raw format) to this domain model. * Note that this data is belonging to a specific object instance. @@ -184,4 +215,4 @@ public class DomainModel { return _methodInvocationListener; } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java index 9ca6ba0e7c..09003fac9e 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/JmxService.java @@ -21,6 +21,7 @@ package org.apache.qpid.management.domain.model; import java.lang.management.ManagementFactory; +import java.util.Set; import java.util.UUID; import javax.management.MBeanServer; @@ -29,6 +30,7 @@ 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.QpidEvent.QpidManagedEvent; import org.apache.qpid.management.domain.model.type.Binary; import org.apache.qpid.transport.util.Logger; @@ -40,8 +42,33 @@ import org.apache.qpid.transport.util.Logger; class JmxService { private final static Logger LOGGER = Logger.get(JmxService.class); - private MBeanServer _mxServer = ManagementFactory.getPlatformMBeanServer(); + MBeanServer _mxServer = ManagementFactory.getPlatformMBeanServer(); + void registerEventInstance( + QpidManagedEvent eventInstance, + UUID brokerId, + String packageName, + String eventClassName) + { + ObjectName name = createEventName(brokerId, packageName, eventClassName); + if (!_mxServer.isRegistered(name)) + { + try + { + _mxServer.registerMBean(eventInstance, name); + + LOGGER.debug( + "<QMAN-200026> : Event instance %s::%s::%s successfully registered with MBean Server with name %s", + brokerId, + packageName, + eventClassName, + name); + } catch (Exception exception) + { + throw new RuntimeException(exception); + } + } +} /** * Registers a pre-existing object instance as an MBean with the MBean @@ -118,6 +145,44 @@ class JmxService } /** + * Removes (unregister) all events from MBean Server. + */ + void unregisterEvents() + { + for (ObjectName name : getEventMBeans()) + { + try + { + _mxServer.unregisterMBean(name); + } catch(Exception ignore) + { + } + } + } + + Set<ObjectName> getEventMBeans() + { + return _mxServer.queryNames(createEventSearchName(),null); + } + + /** + * Removes (unregister) all object instances from MBean Server. + */ + void unregisterObjectInstances() + { + Set<ObjectName> names = _mxServer.queryNames(createObjectInstanceSearchName(),null); + for (ObjectName name : names) + { + try + { + _mxServer.unregisterMBean(name); + } catch(Exception ignore) + { + } + } + } + + /** * Factory method for ObjectNames. * * @param brokerId the broker identifier. @@ -134,7 +199,7 @@ class JmxService .append(Names.BROKER_ID) .append('=') .append(brokerId) - .append(',') + .append(",type=Object,") .append(Names.PACKAGE) .append('=') .append(packageName) @@ -155,4 +220,86 @@ class JmxService throw new RuntimeException(exception); } } -}
\ No newline at end of file + + /** + * Factory method for ObjectNames. + * + * @param brokerId the broker identifier. + * @param packageName the name of the package containing this instance. + * @param className the name of the owner class of this instance. + * @return the object name built according to the given parameters. + */ + private ObjectName createEventName(UUID brokerId, String packageName, String className) + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append(Names.BROKER_ID) + .append('=') + .append(brokerId) + .append(",type=Event,") + .append(Names.PACKAGE) + .append('=') + .append(packageName) + .append(',') + .append(Names.CLASS) + .append('=') + .append(className) + .append(',') + .append(Names.OBJECT_ID) + .append('=') + .append(UUID.randomUUID()) + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Creates an object name that will be used for searching all registered events. + * + * @return the object name that will be used for searching all registered events. + */ + ObjectName createEventSearchName() + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append('*') + .append(",type=Event") + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } + + /** + * Creates an object name that will be used for searching all registered object instances. + * + * @return the object name that will be used for searching all registered object instances. + */ + private ObjectName createObjectInstanceSearchName() + { + String asString = new StringBuilder() + .append(Names.DOMAIN_NAME) + .append(':') + .append('*') + .append(",type=Object") + .toString(); + try + { + return new ObjectName(asString); + } catch (MalformedObjectNameException exception) + { + throw new RuntimeException(exception); + } + } +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java index 4ad5f7086f..a119b6c2b1 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidClass.java @@ -34,7 +34,6 @@ import java.util.concurrent.TimeUnit; 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; @@ -50,7 +49,6 @@ import org.apache.qpid.management.domain.handler.impl.IMethodInvocationListener; import org.apache.qpid.management.domain.handler.impl.InvocationResult; import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; import org.apache.qpid.management.domain.model.type.Binary; -import org.apache.qpid.management.domain.services.QpidService; import org.apache.qpid.management.domain.services.SequenceNumberGenerator; import org.apache.qpid.transport.codec.ManagementDecoder; import org.apache.qpid.transport.util.Logger; @@ -68,11 +66,11 @@ import org.apache.qpid.transport.util.Logger; * * @author Andrea Gazzarini */ -class QpidClass +class QpidClass extends QpidEntity { /** * State interface for this class definition. - * Each state is responsible to handle the injection of the object data. + * Each state is responsible to handle the injection of the data and / or schema. * * @author Andrea Gazzarini */ @@ -100,14 +98,12 @@ class QpidClass * @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; + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException; }; /** @@ -134,7 +130,7 @@ class QpidClass _state = _schemaRequestedButNotYetInjected; } catch (Exception e) { - LOGGER.error( + _logger.error( "<QMAN-100012> : Unable to send a schema request schema for %s.%s", _parent.getName(), _name); @@ -159,14 +155,13 @@ class QpidClass _state = _schemaRequestedButNotYetInjected; } catch (Exception e) { - LOGGER.error( + _logger.error( "<QMAN-100012> : Unable to send a schema request schema for %s.%s", _parent.getName(), _name); } finally { QpidManagedObject instance = getObjectInstance(objectId,false); instance._rawConfigurationData.add(rawData); - _state = _schemaRequestedButNotYetInjected; } } @@ -177,8 +172,7 @@ class QpidClass public void setSchema ( List<Map<String, Object>> propertyDefinitions, List<Map<String, Object>> statisticDefinitions, - List<MethodOrEventDataTransferObject> methodDefinitions, - List<MethodOrEventDataTransferObject> eventDefinitions) throws UnableToBuildFeatureException + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException { throw new IllegalStateException("When a schema arrives it's not possible for this class to be in this state."); } @@ -225,8 +219,7 @@ class QpidClass public synchronized void setSchema ( List<Map<String, Object>> propertyDefinitions, List<Map<String, Object>> statisticDefinitions, - List<MethodOrEventDataTransferObject> methodDefinitions, - List<MethodOrEventDataTransferObject> eventDefinitions) throws UnableToBuildFeatureException + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException { MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[propertyDefinitions.size()+statisticDefinitions.size()]; @@ -234,7 +227,6 @@ class QpidClass buildAttributes(propertyDefinitions,statisticDefinitions,attributesMetadata); buildMethods(methodDefinitions,operationsMetadata); - buildEvents(eventDefinitions); _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,operationsMetadata,null); @@ -248,7 +240,7 @@ class QpidClass { updateInstanceWithInstrumentationData(instance,iterator.next()); iterator.remove(); - } + } for (Iterator<byte[]> iterator = instance._rawConfigurationData.iterator(); iterator.hasNext();) { @@ -297,8 +289,7 @@ class QpidClass public void setSchema ( List<Map<String, Object>> propertyDefinitions, List<Map<String, Object>> statisticDefinitions, - List<MethodOrEventDataTransferObject> methodDefinitions, - List<MethodOrEventDataTransferObject> eventDefinitions) throws UnableToBuildFeatureException + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException { throw new IllegalStateException("When a schema arrives it's not possible for this class to be in this state."); } @@ -310,10 +301,8 @@ class QpidClass * * @author Andrea Gazzarini */ - class QpidManagedObject implements DynamicMBean,MBeanRegistration + class QpidManagedObject extends QpidManagedEntity implements 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. @@ -329,20 +318,6 @@ class QpidClass { 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 @@ -365,45 +340,6 @@ class QpidClass } } - /** - * 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. * @@ -500,14 +436,6 @@ class QpidClass 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>(); @@ -515,9 +443,6 @@ class QpidClass private List<QpidProperty> _schemaOrderedProperties = new ArrayList<QpidProperty>(); private List<QpidStatistic> _schemaOrderedStatistics= new ArrayList<QpidStatistic>(); - private MBeanInfo _metadata; - - private final QpidService _service; private int _howManyPresenceBitMasks; private BlockingQueue<InvocationResult> _exchangeChannelForMethodInvocations; @@ -528,6 +453,7 @@ class QpidClass private final static class Log { + private final static Logger LOGGER = Logger.get(QpidClass.class); final static void logMethodInvocationResult(InvocationResult result) { if (LOGGER.isDebugEnabled()) @@ -546,18 +472,9 @@ class QpidClass */ QpidClass(String className, Binary hash, QpidPackage parentPackage) { - this._name = className; - this._parent = parentPackage; - this._hash = hash; - this._service = new QpidService(_parent.getOwnerId()); + super(className,hash, parentPackage); this._methodInvocationListener = _parent.getMethodInvocationListener(); this._exchangeChannelForMethodInvocations = new SynchronousQueue<InvocationResult>(); - - LOGGER.debug( - "<QMAN-200017> : Class definition has been built (without schema) for %s::%s.%s", - _parent.getOwnerId(), - _parent.getName(), - _name); } /** @@ -568,7 +485,7 @@ class QpidClass */ void addInstrumentationData (Binary objectId, byte[] rawData) { - LOGGER.debug("<QMAN-200015> : Incoming instrumentation data for %s::%s.%s.%s", + _logger.debug("<QMAN-200015> : Incoming instrumentation data for %s::%s.%s.%s", _parent.getOwnerId(), _parent.getName(), _name, @@ -584,7 +501,7 @@ class QpidClass */ void addConfigurationData (Binary objectId, byte[] rawData) { - LOGGER.debug("<QMAN-200016> : Incoming configuration data for %s::%s.%s.%s", + _logger.debug("<QMAN-200016> : Incoming configuration data for %s::%s.%s.%s", _parent.getOwnerId(), _parent.getName(), _name, @@ -599,17 +516,15 @@ class QpidClass * @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 + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException { - LOGGER.info("<QMAN-000012> : Incoming schema for %s::%s.%s",_parent.getOwnerId(),_parent.getName(),_name); - _state.setSchema(propertyDefinitions, statisticDefinitions, methodDefinitions, eventDefinitions); + _logger.info("<QMAN-000012> : Incoming schema for %s::%s.%s",_parent.getOwnerId(),_parent.getName(),_name); + _state.setSchema(propertyDefinitions, statisticDefinitions, methodDefinitions); } /** @@ -641,7 +556,7 @@ class QpidClass _schemaOrderedProperties.add(property); attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature(); - LOGGER.debug( + _logger.debug( "<QMAN-200017> : Property definition for %s::%s.%s has been built.", _parent.getName(), _name, @@ -650,7 +565,7 @@ class QpidClass _howManyPresenceBitMasks = (int)Math.ceil((double)howManyOptionalProperties / 8); - LOGGER.debug( + _logger.debug( "<QMAN-200018> : Class %s::%s.%s has %s optional properties.", _parent.getOwnerId(), _parent.getName(), @@ -667,7 +582,7 @@ class QpidClass _schemaOrderedStatistics.add(statistic); attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature(); - LOGGER.debug( + _logger.debug( "<QMAN-200019> : Statistic definition for %s::%s.%s has been built.", _parent.getName(), _name, @@ -699,17 +614,6 @@ class QpidClass } /** - * 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. @@ -730,24 +634,6 @@ class QpidClass } /** - * Internal method used to send a schema request for this class. - * - * @throws Exception when the request cannot be sent. - */ - private void requestSchema() throws Exception - { - try - { - _service.connect(); - _service.requestSchema(_parent.getName(), _name, _hash); - _service.sync(); - } finally - { - _service.close(); - } - } - - /** * Header (opcode='M') * ObjectId of target object (128 bits) * Package name (str8) @@ -796,7 +682,7 @@ class QpidClass * @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) + void updateInstanceWithConfigurationData(QpidManagedObject instance,byte [] rawData) { ManagementDecoder decoder = new ManagementDecoder(); decoder.init(ByteBuffer.wrap(rawData)); @@ -808,7 +694,7 @@ class QpidClass 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()); + _logger.error("Unable to decode value for %s::%s::%s", _parent.getName(),_name,property.getName()); } } } @@ -819,7 +705,7 @@ class QpidClass * @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) + void updateInstanceWithInstrumentationData(QpidManagedObject instance,byte [] rawData) { ManagementDecoder decoder = new ManagementDecoder(); decoder.init(ByteBuffer.wrap(rawData)); @@ -830,7 +716,7 @@ class QpidClass 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()); + _logger.error("Unable to decode value for %s::%s::%s", _parent.getName(),_name,statistic.getName()); } } } @@ -842,7 +728,7 @@ class QpidClass .append(_parent.getOwnerId()) .append("::") .append(_parent.getName()) - .append("::") + .append('.') .append(_name) .toString(); } @@ -866,17 +752,9 @@ class QpidClass */ 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()); - } + // Chiamlo entityInstances<QpidManagedEntity> e mettilo nella superclasse? + _objectInstances.clear(); + JMX_SERVICE.unregisterObjectInstances(); _service.close(); } } diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java new file mode 100644 index 0000000000..62f469e53c --- /dev/null +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEntity.java @@ -0,0 +1,136 @@ +package org.apache.qpid.management.domain.model;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.DynamicMBean;
+import javax.management.MBeanInfo;
+import javax.management.RuntimeOperationsException;
+
+import org.apache.qpid.management.domain.model.type.Binary;
+import org.apache.qpid.management.domain.services.QpidService;
+import org.apache.qpid.transport.util.Logger;
+
+/**
+ * Layer supertype for QMan entities.
+ *
+ * @author Andrea Gazzarini
+ */
+public abstract class QpidEntity
+{
+ /**
+ * Layer supertype for QMan managed bean entities.
+ *
+ * @author Andrea Gazzarini
+ */
+ abstract class QpidManagedEntity implements DynamicMBean
+ {
+ // After mbean is registered with the MBean server this collection holds the mbean attribute values.
+ Map<String,Object> _attributes = new HashMap<String, Object>();
+
+ /**
+ * Creates or replace the given attribute.
+ * Note that this is not part of the management interface of this object instance and therefore will be accessible only
+ * from within this class.
+ * It is used to update directly the object attributes bypassing jmx interface.
+ *
+ * @param attributeName the name of the attribute.
+ * @param property newValue the new value of the attribute.
+ */
+ void createOrReplaceAttributeValue(String attributeName, Object newValue)
+ {
+ _attributes.put(attributeName, newValue);
+ }
+
+ /**
+ * Get the values of several attributes of the Dynamic MBean.
+ *
+ * @param attributes A list of the attributes to be retrieved.
+ *
+ * @return The list of attributes retrieved.
+ */
+ public AttributeList getAttributes (String[] attributes)
+ {
+ if (attributes == null)
+ {
+ throw new RuntimeOperationsException(new IllegalArgumentException("Attributes array must not be null"));
+ }
+
+ AttributeList result = new AttributeList(attributes.length);
+ for (int i = 0; i < attributes.length; i++)
+ {
+ String attributeName = attributes[i];
+ try
+ {
+ result.add(new Attribute(attributeName,getAttribute(attributeName)));
+ } catch(Exception exception)
+ {
+ // Already logged.
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns metadata for this object instance.
+ */
+ // Developer Note : note that this metadata is a member of the outer class definition : in that way we create
+ // that metadata only once and then it will be shared between all object instances (it's a readonly object)
+ public MBeanInfo getMBeanInfo ()
+ {
+ return _metadata;
+ }
+ };
+
+ final Logger _logger = Logger.get(getClass());
+ final static JmxService JMX_SERVICE = new JmxService();
+
+ final String _name;
+ final Binary _hash;
+
+ final QpidPackage _parent;
+ MBeanInfo _metadata;
+
+ final QpidService _service;
+
+ /**
+ * Builds a new class with the given name and package as parent.
+ *
+ * @param className the name of the class.
+ * @param hash the class schema hash.
+ * @param parentPackage the parent of this class.
+ */
+ QpidEntity(String className, Binary hash, QpidPackage parentPackage)
+ {
+ this._name = className;
+ this._parent = parentPackage;
+ this._hash = hash;
+ this._service = new QpidService(_parent.getOwnerId());
+
+ _logger.debug(
+ "<QMAN-200017> : Entity definition has been built (without schema) for %s::%s.%s",
+ _parent.getOwnerId(),
+ _parent.getName(),
+ _name);
+ }
+
+ /**
+ * Internal method used to send a schema request for this entity.
+ *
+ * @throws Exception when the request cannot be sent.
+ */
+ void requestSchema() throws Exception
+ {
+ try
+ {
+ _service.connect();
+ _service.requestSchema(_parent.getName(), _name, _hash);
+ _service.sync();
+ } finally
+ {
+ _service.close();
+ }
+ }
+}
diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java index 200791bb93..98a05bf931 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidEvent.java @@ -20,7 +20,435 @@ */ package org.apache.qpid.management.domain.model; -class QpidEvent extends QpidFeature -{ - // NOT YET IMPLEMENTED +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.InvalidAttributeValueException; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.ReflectionException; +import javax.management.RuntimeOperationsException; + +import org.apache.qpid.management.domain.model.type.Binary; +import org.apache.qpid.transport.codec.ManagementDecoder; + +/** + * Qpid event definition. + * + * @author Andrea Gazzarini + */ +class QpidEvent extends QpidEntity +{ + + /** + * State interface for this event definition. + * Each state is responsible to handle the injection of the data and / or schema. + * + * @author Andrea Gazzarini + */ + interface State + { + /** + * Adds the given data for the object instance associated to the given object identifier. + * + * @param rawData the raw configuration data. + */ + void addNewEventData (byte[] rawData, long currentTimestamp, int severity); + + /** + * Inject the schema into this class definition. + * + * @param propertyDefinitions + * @param statisticDefinitions + * @param methodDefinitions + * @throws UnableToBuildFeatureException when it's not possibile to parse schema and build the class definition. + */ + public void setSchema (List<Map<String, Object>> agumentDefinitions) throws UnableToBuildFeatureException; + }; + + + /** + * This is the initial state of every qpid class. + * The class definition instance is created but its schema has not been injected. + * Incoming configuration & instrumentation data will be stored in raw format because we don't know how to + * parse it until the schema arrives. + * In addition, this state is responsible (when data arrives) to request its schema. + */ + final State _schemaNotRequested = new State() { + + /** + * Stores the incoming data in raw format and request the schema for this class. + * After that a transition to the next state is made. + * + * @param objectId the object instance identifier. + * @param rawData incoming configuration data. + */ + public synchronized void addNewEventData (byte[] rawData, long currentTimestamp, int severity) + { + try + { + requestSchema(); + _state = _schemaRequestedButNotYetInjected; + } catch (Exception e) + { + _logger.error( + "<QMAN-100012> : Unable to send a schema request schema for %s.%s", + _parent.getName(), + _name); + } finally { + createEventInstance(rawData,currentTimestamp,severity); + } + } + + /** + * This method only throws an illegal state exception because when a schema arrives + * this state is no longer valid. + */ + public void setSchema (List<Map<String, Object>> agumentDefinitions) 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 and request the schema for this class. + * After that a transition to the next state is made. + * + * @param objectId the object instance identifier. + * @param rawData incoming configuration data. + */ + public synchronized void addNewEventData (byte[] rawData,long currentTimestamp, int severity) + { + createEventInstance(rawData,currentTimestamp, severity); + } + + /** + * When a schema is injected into this defintiion the following should happen : + * 1) the incoming schema is parsed and the class definition is built; + * 2) the retained raw data is converted into object instance(s) + * 3) the internal state of this class changes; + * + * If someting is wrong during that process the schema is not built and the state don't change. + */ + public synchronized void setSchema (List<Map<String, Object>> argumentDefinitions) throws UnableToBuildFeatureException + { + MBeanAttributeInfo [] attributesMetadata = new MBeanAttributeInfo[argumentDefinitions.size()+2]; + + buildArguments(argumentDefinitions, attributesMetadata); + + _metadata = new MBeanInfo(_name,_name,attributesMetadata,null,null,null); + + // Converting stored object instances into JMX MBean and removing raw instance data. + for (QpidManagedEvent instance : _eventInstances) + { + updateEventInstanceWithData(instance); + JMX_SERVICE.registerEventInstance(instance,_parent.getOwnerId(),_parent.getName(),_name); + } + _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 addNewEventData (byte[] rawData,long currentTimestamp, int severity) + { + QpidManagedEvent instance = createEventInstance(rawData,currentTimestamp, severity); + updateEventInstanceWithData(instance); + JMX_SERVICE.registerEventInstance(instance,_parent.getOwnerId(),_parent.getName(),_name); + } + + /** + * Never called when the class definition has this state. + */ + public void setSchema (List<Map<String, Object>> agumentDefinitions) throws UnableToBuildFeatureException + { + // N.A. : Schema is already injected. + } + }; + + /** + * MBean used for representing remote broker object instances. + * This is the core component of the QMan domain model + * + * @author Andrea Gazzarini + */ + class QpidManagedEvent extends QpidManagedEntity + { + + + // Arrays used for storing raw data before this mbean is registered to mbean server. + final byte[] _rawEventData; + final long _timestamp; + final int _severity; + + /** + * Builds a new managed object with the given object identifier. + * + * @param objectId the object identifier. + */ + private QpidManagedEvent(byte [] data, long timestamp, int severity) + { + this._rawEventData = data; + this._timestamp = timestamp; + this._severity = severity; + _attributes.put(SEVERITY_ATTR_NAME, _severity); + _attributes.put(TIMESTAMP_ATTR_NAME, new Date(_timestamp)); + } + + /** + * Returns the value of the given attribute.s + * + * @throws AttributeNotFoundException when no attribute is found with the given name. + */ + public Object getAttribute (String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException + { + if (attributeName == null) + { + throw new RuntimeOperationsException(new IllegalArgumentException("Attribute name must not be null.")); + } + + if (_arguments.containsKey(attributeName) || SEVERITY_ATTR_NAME.equals(attributeName) || TIMESTAMP_ATTR_NAME.equals(attributeName)) + { + return _attributes.get(attributeName); + } else + { + throw new AttributeNotFoundException(attributeName); + } + } + + /** + * Executes an operation on this object instance. + * + * @param actionName the name of the method. + * @param params the method parameters + * @param signature the method signature. + */ + public Object invoke (String actionName, Object[] params, String[] signature) throws MBeanException,ReflectionException + { + throw new ReflectionException(new NoSuchMethodException(actionName)); + } + + /** + * Sets the value of the given attribute on this object instance. + * + * @param attribute contains the new value of the attribute. + * @throws AttributeNotFoundException when the given attribute is not found on this object instance. + * @throws InvalidAttributeValueException when the given value is violating one attribute invariant. + */ + public void setAttribute (Attribute attribute) throws AttributeNotFoundException, + InvalidAttributeValueException, MBeanException, ReflectionException + { + throw new ReflectionException(new NoSuchMethodException()); + } + + /** + * Sets the values of several attributes of this MBean. + * + * @param attributes a list of attributes: The identification of the attributes to be set and the values they are to be set to. + * @return The list of attributes that were set, with their new values. + */ + public AttributeList setAttributes (AttributeList attributes) + { + throw new RuntimeException(); + } + } + + final static String SEVERITY_ATTR_NAME = "Severity"; + final static String TIMESTAMP_ATTR_NAME = "Date"; + + private List<QpidProperty> _schemaOrderedArguments = new ArrayList<QpidProperty>(); + + Map<String, QpidProperty> _arguments = new HashMap<String, QpidProperty>(); + List<QpidManagedEvent> _eventInstances = new LinkedList<QpidManagedEvent>(); + State _state = _schemaNotRequested;; + + /** + * Builds a new class with the given name and package as parent. + * + * @param className the name of the class. + * @param hash the class schema hash. + * @param parentPackage the parent of this class. + */ + QpidEvent(String eventClassName, Binary hash, QpidPackage parentPackage) + { + super(eventClassName,hash,parentPackage); + } + + /** + * Adds the configuration data for the object instance associated to the given object identifier. + * + * @param objectId the object identifier. + * @param rawData the raw configuration data. + */ + void addEventData (byte[] rawData, long currentTimestamp, int severity) + { + _logger.debug("<QMAN-200015> : Incoming data for event %s::%s.%s", + _parent.getOwnerId(), + _parent.getName(), + _name); + _state.addNewEventData(rawData, currentTimestamp, severity); + } + + /** + * Sets the schema for this class definition. + * A schema is basically a metadata description of all properties, statistics, methods and events of this class. + * + * @param propertyDefinitions properties metadata. + * @param statisticDefinitions statistics metadata. + * @param methodDefinitions methods metadata. + * @throws UnableToBuildFeatureException when some error occurs while parsing the incoming schema. + */ + void setSchema (List<Map<String, Object>> argumentDefinitions) throws UnableToBuildFeatureException + { + _logger.info("<QMAN-000012> : Incoming schema for %s::%s.%s",_parent.getOwnerId(),_parent.getName(),_name); + _state.setSchema(argumentDefinitions); + } + + /** + * Internal method used for building attributes definitions. + * + * @param props the map contained in the properties schema. + * @param stats the map contained in the statistics schema. + * @param attributes the management metadata for attributes. + * @throws UnableToBuildFeatureException when it's not possibile to build one attribute definition. + */ + void buildArguments ( + List<Map<String, Object>> arguments,MBeanAttributeInfo[] attributes) throws UnableToBuildFeatureException + { + int index = 0; + + for (Map<String, Object> argumentDefinition : arguments) + { + // Force metadata attributes. It is needed because arguments are "similar" to properties but they + // aren't properties and then they haven't optional, index and access metadata attributes + // (mandatory for build a property definition). + argumentDefinition.put(QpidFeatureBuilder.Attribute.optional.name(),0); + argumentDefinition.put(QpidFeatureBuilder.Attribute.index.name(),1); + argumentDefinition.put(QpidFeatureBuilder.Attribute.access.name(),3); + + QpidFeatureBuilder builder = QpidFeatureBuilder.createPropertyBuilder(argumentDefinition); + builder.build(); + + QpidProperty argument = (QpidProperty) builder.getQpidFeature(); + + _arguments.put(argument.getName(),argument); + _schemaOrderedArguments.add(argument); + attributes[index++]=(MBeanAttributeInfo) builder.getManagementFeature(); + + _logger.debug( + "<QMAN-200017> : Event argument definition for %s::%s.%s has been built.", + _parent.getName(), + _name, + argument); + } + + attributes[index++] = new MBeanAttributeInfo( + SEVERITY_ATTR_NAME, + Integer.class.getName(), + "Severity level for this event.", + true, + false, + false); + + attributes[index++] = new MBeanAttributeInfo( + TIMESTAMP_ATTR_NAME, + Date.class.getName(), + "Current timestamp of this event.", + true, + false, + false); + + } + + /** + * Returns the object instance associated to the given identifier. + * Note that if the identifier is not associated to any obejct instance, a new one will be created. + * + * @param objectId the object identifier. + * @param registration a flag indicating whenever the (new ) instance must be registered with MBean server. + * @return the object instance associated to the given identifier. + */ + QpidManagedEvent createEventInstance(byte [] data, long timestamp, int severity) + { + QpidManagedEvent eventInstance = new QpidManagedEvent(data, timestamp, severity); + _eventInstances.add(eventInstance); + return eventInstance; + } + + /** + * Updates the given obejct instance with the given incoming configuration data. + * + * @param instance the managed object instance. + * @param rawData the incoming configuration data which contains new values for instance properties. + */ + void updateEventInstanceWithData(QpidManagedEvent instance) + { + ManagementDecoder decoder = new ManagementDecoder(); + decoder.init(ByteBuffer.wrap(instance._rawEventData)); + + for (QpidProperty property : _schemaOrderedArguments) + { + try { + Object value = property.decodeValue(decoder); + instance.createOrReplaceAttributeValue(property.getName(),value); + } catch(Exception ignore) { + _logger.error("Unable to decode value for %s::%s::%s", _parent.getName(),_name,property.getName()); + } + } + } + + @Override + public String toString () + { + return new StringBuilder() + .append(_parent.getOwnerId()) + .append("::") + .append(_parent.getName()) + .append(".") + .append(_name) + .toString(); + } + + /** + * Deregisters all the object instances and release all previously acquired resources. + */ + void releaseResources () + { + _eventInstances.clear(); + JMX_SERVICE.unregisterEvents(); + _service.close(); + } + + /** + * Checks if this event definition contains event instance(s). + * + * @return true if there is one or more managed instances. + */ + boolean hasNoInstances() { + return _eventInstances.isEmpty(); + } } diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java index 4bac16452c..23353bf37e 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidFeatureBuilder.java @@ -439,6 +439,15 @@ class QpidFeatureBuilder void build() throws UnableToBuildFeatureException { - _state.build(); + try + { + _state.build(); + } catch(UnableToBuildFeatureException exception) + { + throw exception; + } catch(Exception exception) + { + throw new UnableToBuildFeatureException(exception,"Feature name is not available for debugging."); + } } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java index 1bc3d63129..e9799cb147 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/QpidPackage.java @@ -79,6 +79,7 @@ final class QpidPackage private String _name; private DomainModel _parent; private Map<QpidClassIdentity, QpidClass> _classes = new HashMap<QpidClassIdentity, QpidClass>(); + private Map<QpidClassIdentity, QpidEvent> _events = new HashMap<QpidClassIdentity, QpidEvent>(); /** * Builds a new package with the supplied name. @@ -128,12 +129,19 @@ final class QpidPackage Binary classHash, List<Map<String, Object>> properties, List<Map<String, Object>> statistics, - List<MethodOrEventDataTransferObject> methods, - List<MethodOrEventDataTransferObject> events) throws UnableToBuildFeatureException + List<MethodOrEventDataTransferObject> methods) throws UnableToBuildFeatureException { - getQpidClass(className,classHash,true).setSchema(properties,statistics,methods, events); + getQpidClass(className,classHash,true).setSchema(properties,statistics,methods); } + void addEventDefinition ( + String eventClassName, + Binary classHash, + List<Map<String, Object>> arguments) throws UnableToBuildFeatureException + { + getQpidEvent(eventClassName,classHash,true).setSchema(arguments); + } + /** * Returns true if this package contains the given class definition. * @@ -168,6 +176,11 @@ final class QpidPackage { getQpidClass(className,classHash,true).addConfigurationData(objectId,rawData); } + + void setEventInstanceRawData (String eventName,Binary eventHash, byte[] rawData,long currentTimestamp,int severity) + { + getQpidEvent(eventName,eventHash,true).addEventData(rawData, currentTimestamp, severity); + } /** * Returns the definition of the class with given name. @@ -193,6 +206,29 @@ final class QpidPackage } /** + * Returns the definition of the class with given name. + * + * @param className the name of the class. + * @param hash the class hash. + * @param store a flag indicating if a just created class must be stored or not. + * @return the definition of the class with given name. + */ + QpidEvent getQpidEvent(String className, Binary hash, boolean store) + { + QpidClassIdentity identity = new QpidClassIdentity(className,hash); + QpidEvent eventDefinition = _events.get(identity); + if (eventDefinition == null) + { + eventDefinition = new QpidEvent(className, hash,this); + if (store) + { + _events.put(identity,eventDefinition); + } + } + return eventDefinition; + } + + /** * Returns a string representation of this class. * That is, this method returns the simple name (not FQN) of this class. */ @@ -224,6 +260,11 @@ final class QpidPackage { qpidClass.releaseResources(); } + + for (QpidEvent qpidEvent: _events.values()) + { + qpidEvent.releaseResources(); + } } /** @@ -235,4 +276,4 @@ final class QpidPackage { return _parent.getMethodInvocationListener(); } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java index 59721240d0..fc4506779b 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/UnableToBuildFeatureException.java @@ -36,7 +36,7 @@ public class UnableToBuildFeatureException extends Exception */ UnableToBuildFeatureException(Exception exception, String featureName) { - super( (featureName != null) ? featureName : "Not available" ,exception); + super( (featureName != null) ? featureName : "Feature name is not available for debugging purposes." ,exception); } /** @@ -48,4 +48,4 @@ public class UnableToBuildFeatureException extends Exception { super(message); } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java index 3fe134ebe7..4c0dd926d0 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/model/type/Binary.java @@ -26,7 +26,6 @@ import java.util.UUID; import org.apache.qpid.management.messages.AmqpCoDec; - /** * 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. @@ -121,10 +120,9 @@ public final class Binary implements Serializable encoder.pack(bytes); } - // TODO @Override public String toString () { return uuid.toString(); } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java index e2808213f1..ce700aa283 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/domain/services/QMan.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.UUID; import java.util.Map.Entry; +import org.apache.log4j.xml.DOMConfigurator; import org.apache.qpid.management.configuration.BrokerConnectionData; import org.apache.qpid.management.configuration.Configuration; import org.apache.qpid.management.configuration.ConfigurationException; @@ -42,38 +43,19 @@ import org.apache.qpid.transport.util.Logger; public class QMan { private final static Logger LOGGER = Logger.get(QMan.class); - private final static List<ManagementClient> managementClients = new ArrayList<ManagementClient>(); - + private final List<ManagementClient> managementClients = new ArrayList<ManagementClient>(); + /** - * Main method used for starting Q-Man. - * - * @param args the command line arguments. + * Starts QMan. + * @throws StartupFailureException when it's not possible to proceed with startup. */ - 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..."); - try - { - for (ManagementClient client : managementClients) - { - client.shutdown(); - } - } catch(Exception exception) - { - - } - LOGGER.info("<QMAN-000007> : Q-Man shut down."); - } - }); - + void start() throws StartupFailureException + { LOGGER.info("<QMAN-000001> : Starting Q-Man..."); LOGGER.info("<QMAN-000002> : Reading Q-Man configuration..."); - + + addShutDownHook(); + Configurator configurator = new Configurator(); try { @@ -107,5 +89,63 @@ public class QMan "<QMAN-100002> : Q-Man was unable to startup correctly : a configuration error occurred."); System.exit(1); } + catch(IOException exception) + { + throw new StartupFailureException(exception); + } + } + + /** + * Compose method used for adding a "graceful" shutdown hook. + */ + private void addShutDownHook() + { + // SHUTDOWN HOOK + Runtime.getRuntime().addShutdownHook(new Thread(){ + @Override + public void run () + { + LOGGER.info("<QMAN-000006> : Shutting down Q-Man..."); + try + { + for (ManagementClient client : managementClients) + { + client.shutdown(); + } + } catch(Exception exception) + { + + } + LOGGER.info("<QMAN-000007> : Q-Man shut down."); + } + }); + } + + /** + * Main method used for starting Q-Man. + * + * @param args the command line arguments. + */ + public static void main (String[] args) + { + if (args.length == 1) + { + String logFileName = args[0]; + DOMConfigurator.configureAndWatch(logFileName,5000); + } + + new Thread() + { + public void run() + { + QMan qman = new QMan(); + try + { + qman.start(); + } catch (StartupFailureException exception) { + exception.printStackTrace(); + } + } + }.start(); } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/main/java/org/apache/qpid/management/messages/AmqpCoDec.java b/qpid/java/management/client/src/main/java/org/apache/qpid/management/messages/AmqpCoDec.java index 51a0189873..c7ab9b7fd2 100644 --- a/qpid/java/management/client/src/main/java/org/apache/qpid/management/messages/AmqpCoDec.java +++ b/qpid/java/management/client/src/main/java/org/apache/qpid/management/messages/AmqpCoDec.java @@ -13,7 +13,7 @@ public class AmqpCoDec _buffer = new byte [1000]; _buffer[0] = 'A'; _buffer[1] = 'M'; - _buffer[2] = '1'; + _buffer[2] = '2'; _position = 3; } @@ -133,4 +133,4 @@ public class AmqpCoDec { return ByteBuffer.wrap(_buffer,0,_position); } -}
\ No newline at end of file +} diff --git a/qpid/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java b/qpid/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java index 1ed938d9fd..5855a3e60b 100644 --- a/qpid/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java +++ b/qpid/java/management/client/src/test/java/org/apache/qpid/management/TestConstants.java @@ -25,24 +25,40 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; import org.apache.qpid.management.domain.model.DomainModel; import org.apache.qpid.management.domain.model.type.Binary; public interface TestConstants { - String QPID_PACKAGE_NAME = "qpid"; - String EXCHANGE_CLASS_NAME = "exchange"; - Binary HASH = new Binary(new byte []{1,2,3,4,5,6,7,8,9}); - int VALID_CODE = 1; - - UUID BROKER_ID = UUID.randomUUID(); Binary OBJECT_ID = new Binary(new byte []{1,2,3,2,1,1,2,3}); - DomainModel DOMAIN_MODEL = new DomainModel(BROKER_ID); + DomainModel DOMAIN_MODEL = new DomainModel(BROKER_ID); + + String AGE_ATTRIBUTE_NAME = "age"; + String AGE_ATTRIBUTE_DESCRIPTION = "The age of a person."; + String SURNAME_ATTRIBUTE_NAME = "surname"; + String SURNAME_ATTRIBUTE_DESCRIPTION = "The surname of a person."; + Integer _1 = new Integer(1); + byte [] TEST_RAW_DATA= new byte []{1,4,5,7,8,9,4,44}; + long NOW = System.currentTimeMillis(); + int SEVERITY = _1; + + String QPID_PACKAGE_NAME = "qpid"; + String EXCHANGE_CLASS_NAME = "exchange"; + String BIND_EVENT_NAME = "bind"; + Binary HASH = new Binary(new byte []{1,2,3,4,5,6,7,8,9}); + int VALID_CODE = _1; + List<Map<String, Object>> EMPTY_PROPERTIES_SCHEMA = new LinkedList<Map<String,Object>>(); List<Map<String, Object>> EMPTY_STATISTICS_SCHEMA = new LinkedList<Map<String,Object>>(); - List<Map<String, Object>> EMPTY_METHODS_SCHEMA = new LinkedList<Map<String,Object>>(); - List<Map<String, Object>> EMPTY_EVENTS_SCHEMA = new LinkedList<Map<String,Object>>(); -}
\ No newline at end of file + List<MethodOrEventDataTransferObject> EMPTY_METHODS_SCHEMA = new LinkedList<MethodOrEventDataTransferObject>(); + List<Map<String, Object>> EMPTY_ARGUMENTS_SCHEMA = new LinkedList<Map<String,Object>>(); + int _0 = 0; + int SAMPLE_ACCESS_CODE = 1; + String YEARS = "years"; + int SAMPLE_MIN_VALUE = 1; + int SAMPLE_MAX_VALUE = 120; +} diff --git a/qpid/java/management/client/src/test/java/org/apache/qpid/management/configuration/StubConfigurator.java b/qpid/java/management/client/src/test/java/org/apache/qpid/management/configuration/StubConfigurator.java index 426a1a29f1..8bb4985a89 100644 --- a/qpid/java/management/client/src/test/java/org/apache/qpid/management/configuration/StubConfigurator.java +++ b/qpid/java/management/client/src/test/java/org/apache/qpid/management/configuration/StubConfigurator.java @@ -31,9 +31,9 @@ public class StubConfigurator extends Configurator */ public void configure() throws ConfigurationException { - addAccessModeMapping("1", "RW"); - addAccessModeMapping("2", "RO"); - addAccessModeMapping("3", "RC"); + addAccessModeMapping("1", "RC"); + addAccessModeMapping("2", "RW"); + addAccessModeMapping("3", "RO"); addTypeMapping("1", Str8.class.getName()); } diff --git a/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java b/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java index 66287016aa..837810ea0d 100644 --- a/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java +++ b/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidClassTest.java @@ -1,47 +1,36 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ package org.apache.qpid.management.domain.model; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; + +import junit.framework.TestCase; import org.apache.qpid.management.TestConstants; import org.apache.qpid.management.configuration.ConfigurationException; import org.apache.qpid.management.configuration.StubConfigurator; +import org.apache.qpid.management.domain.handler.impl.MethodOrEventDataTransferObject; import org.apache.qpid.management.domain.model.QpidClass.QpidManagedObject; -public class QpidClassTest extends BaseDomainModelTestCase +public class QpidClassTest extends TestCase { - private QpidClass _qpidClass; + private QpidClass _class; + private QpidPackage _package; @Override - protected void setUp () throws Exception + protected void setUp () throws ConfigurationException { - QpidPackage qpidPackage = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL); - _qpidClass = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,qpidPackage); + StubConfigurator configurator = new StubConfigurator(); + configurator.configure(); + _package = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL); + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package); } /** @@ -55,13 +44,15 @@ public class QpidClassTest extends BaseDomainModelTestCase { assertFalse ( "Nobody set instance #"+TestConstants.OBJECT_ID+" into this class so why is it there?", - _qpidClass._objectInstances.containsKey(TestConstants.OBJECT_ID)); + _class._objectInstances.containsKey(TestConstants.OBJECT_ID)); - _qpidClass.getObjectInstance(TestConstants.OBJECT_ID, false); + QpidManagedObject instance = _class.getObjectInstance(TestConstants.OBJECT_ID, false); assertTrue ( "Now the instance #"+TestConstants.OBJECT_ID+" should be there...", - _qpidClass._objectInstances.containsKey(TestConstants.OBJECT_ID)); + _class._objectInstances.containsKey(TestConstants.OBJECT_ID)); + + assertEquals(instance,_class.getObjectInstance(TestConstants.OBJECT_ID, false)); } /** @@ -73,8 +64,8 @@ public class QpidClassTest extends BaseDomainModelTestCase */ public void testAddInstrumentationAndConfigurationDataBeforeSchemaInstallation() { - _qpidClass._state = _qpidClass._schemaRequestedButNotYetInjected; - QpidManagedObject objectInstance = _qpidClass.getObjectInstance(TestConstants.OBJECT_ID,false); + _class._state = _class._schemaRequestedButNotYetInjected; + QpidManagedObject objectInstance = _class.getObjectInstance(TestConstants.OBJECT_ID,false); assertTrue( "This object instance is a new one so how is it possible that it has already instrumentation data? ", @@ -86,8 +77,8 @@ public class QpidClassTest extends BaseDomainModelTestCase byte [] dummyConfigurationData = {1,2,3,4,5,6,7,8}; byte [] dummyInstrumentationData = {11,21,31,41,51,61,71,81}; - _qpidClass.addConfigurationData(TestConstants.OBJECT_ID, dummyConfigurationData); - _qpidClass.addInstrumentationData(TestConstants.OBJECT_ID, dummyInstrumentationData); + _class.addConfigurationData(TestConstants.OBJECT_ID, dummyConfigurationData); + _class.addInstrumentationData(TestConstants.OBJECT_ID, dummyInstrumentationData); assertEquals("Now configuration data should be there...",1,objectInstance._rawConfigurationData.size()); assertEquals("Now instrumentation data should be there...",1,objectInstance._rawInstrumentationData.size()); @@ -103,63 +94,292 @@ public class QpidClassTest extends BaseDomainModelTestCase dummyInstrumentationData)); } - public void testBuildAttributesOK() throws UnableToBuildFeatureException, ConfigurationException + /** + * Tests the internal state change of a class definition. + */ + public void testStateChange() throws UnableToBuildFeatureException { - StubConfigurator configurator = new StubConfigurator(); - configurator.configure(); + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception { + _state = _schemaRequestedButNotYetInjected; + } + + @Override + void setSchema(List<Map<String, Object>> propertyDefinitions, + List<Map<String, Object>> statisticDefinitions, + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException { + _state = _schemaInjected; + } + }; + + assertSame( + "Initial state doesn't match.", + _class._schemaNotRequested, + _class._state); + + _class.addConfigurationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); - List<Map<String,Object>> properties = new ArrayList<Map<String, Object>>(); - List<Map<String,Object>> statistics = new ArrayList<Map<String, Object>>(); - - Map <String,Object> age = new HashMap<String, Object>(); - - age.put("name","age"); - age.put("access", new Integer(1)); - age.put("unit","years"); - age.put("min", new Integer(0)); - age.put("max",new Integer(120)); - age.put("desc", "The age of a person."); - age.put("type", new Integer(1)); - age.put("optional",0); - age.put("index", new Integer(1)); + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + + _class.setSchema( + TestConstants.EMPTY_PROPERTIES_SCHEMA, + TestConstants.EMPTY_STATISTICS_SCHEMA, + new LinkedList<MethodOrEventDataTransferObject>()); + + assertSame( + "Request schema has been injected. The current state is not indicating that!", + _class._schemaInjected, + _class._state); + } + + /** + * Tests the injection of a valid schema on a QpidClass. + * + * <br>precondition : a valid arguments is injected on the qpid class. + * <br>postcondition : class definition is built successfully. + */ + public void testSchemaInjectionOk() throws UnableToBuildFeatureException + { + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception + { + // DO NOTHING : QMan is not running and therefore the schema will be manually injected. + } + + @Override + void updateInstanceWithConfigurationData(QpidManagedObject instance, byte[] rawData) + { + // DO NOTHING Given raw data is not valid so it cannot be converted. + } + }; + + // Incoming configuration data : that will fire the schema request and a state change + // from schema-not-requested to schema-requested-but-not-injected + _class.addConfigurationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + // I must be sure that what is obvious for me it's obvious for QMan... :) + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + + List<Map<String,Object>> propertyDefinitions = new ArrayList<Map<String,Object>>(2); + propertyDefinitions.add( + createProperty( + TestConstants.AGE_ATTRIBUTE_NAME, + 1, + TestConstants.YEARS, + TestConstants.SAMPLE_MIN_VALUE, + TestConstants.SAMPLE_MAX_VALUE, + null, + TestConstants.AGE_ATTRIBUTE_DESCRIPTION, + TestConstants._1, + false, + TestConstants._0)); + + propertyDefinitions.add( + createProperty( + TestConstants.SURNAME_ATTRIBUTE_NAME, + TestConstants.SAMPLE_ACCESS_CODE, + null, + null, + null, + TestConstants.SAMPLE_MAX_VALUE, + TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION, + TestConstants._1, + true, + TestConstants._1)); - Map <String,Object> surname = new HashMap<String, Object>(); - surname.put("name","surname"); - surname.put("access", new Integer(1)); - surname.put("desc", "The surname of a person."); - surname.put("type", new Integer(1)); - surname.put("optional",1); - surname.put("index", new Integer(1)); - properties.add(age); - properties.add(surname); - - MBeanAttributeInfo [] info = new MBeanAttributeInfo[properties.size()+statistics.size()]; - _qpidClass.buildAttributes(properties, statistics, info); - - assertEquals(2,_qpidClass._properties.size()); - - QpidProperty property = _qpidClass._properties.get("age"); - - assertEquals("age",property.getName()); - assertEquals(AccessMode.RW,property.getAccessMode()); - assertEquals("years",property.getUnit()); - assertEquals(0,property.getMinValue()); - assertEquals(120,property.getMaxValue()); + List<Map<String,Object>> statisticDefinitions = new ArrayList<Map<String,Object>>(2); + + _class.setSchema(propertyDefinitions, TestConstants.EMPTY_STATISTICS_SCHEMA, TestConstants.EMPTY_METHODS_SCHEMA); + + assertEquals(2,_class._properties.size()); + + QpidProperty property = _class._properties.get(TestConstants.AGE_ATTRIBUTE_NAME); + assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,property.getName()); + assertEquals(AccessMode.RC,property.getAccessMode()); + assertEquals(TestConstants.YEARS,property.getUnit()); + assertEquals(TestConstants.SAMPLE_MIN_VALUE,property.getMinValue()); + assertEquals(TestConstants.SAMPLE_MAX_VALUE,property.getMaxValue()); assertEquals(Integer.MIN_VALUE,property.getMaxLength()); - assertEquals("The age of a person.",property.getDescription()); + assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,property.getDescription()); assertEquals(String.class,property.getJavaType()); assertFalse(property.isOptional()); - property = _qpidClass._properties.get("surname"); - - assertEquals("surname",property.getName()); - assertEquals(AccessMode.RW,property.getAccessMode()); + property = _class._properties.get(TestConstants.SURNAME_ATTRIBUTE_NAME); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,property.getName()); + assertEquals(AccessMode.RC,property.getAccessMode()); assertNull(property.getUnit()); assertEquals(Integer.MIN_VALUE,property.getMinValue()); assertEquals(Integer.MIN_VALUE,property.getMaxValue()); - assertEquals(Integer.MIN_VALUE,property.getMaxLength()); - assertEquals("The surname of a person.",property.getDescription()); + assertEquals(TestConstants.SAMPLE_MAX_VALUE,property.getMaxLength()); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,property.getDescription()); assertEquals(String.class,property.getJavaType()); assertTrue(property.isOptional()); - } -}
\ No newline at end of file + + MBeanInfo mbeanInfo = _class._metadata; + assertEquals(TestConstants.EXCHANGE_CLASS_NAME,mbeanInfo.getClassName()); + + MBeanAttributeInfo [] attributes = mbeanInfo.getAttributes(); + assertEquals(2,attributes.length); + + MBeanAttributeInfo attribute = attributes[0]; + assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,attribute.getName()); + assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,attribute.getDescription()); + assertFalse(attribute.isWritable()); + assertTrue(attribute.isReadable()); + assertEquals(String.class.getName(),attribute.getType()); + + attribute = attributes[1]; + assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,attribute.getName()); + assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,attribute.getDescription()); + assertFalse(attribute.isWritable()); + assertTrue(attribute.isReadable()); + assertEquals(String.class.getName(),attribute.getType()); + } + + /** + * Tests the behaviour of the class when a schema request can't be made. + * + * <br>precondition : class must be in "schema-not-requested" state when incoming data arrives. + * <br>postcondition : no exception is thrown and no state transition happens. + */ + public void testStateChange_withRequestSchemaFailure() + { + _class= new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception { + throw new Exception(); + } + + @Override + void setSchema( + List<Map<String, Object>> propertyDefinitions, + List<Map<String, Object>> statisticDefinitions, + List<MethodOrEventDataTransferObject> methodDefinitions) throws UnableToBuildFeatureException + { + } + }; + + assertSame( + "Initial state must be schema-not-requested.", + _class._schemaNotRequested, + _class._state); + + _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + assertSame( + "Current state must be still schema-not-requested.", + _class._schemaNotRequested, + _class._state); + } + + /** + * Tests the behaviour of the class when a schema injection fails. + * + * <br>precondition : class must be in "schema-not-requested" state when incoming data arrives. + * <br>postcondition : an exception is thrown and no state transition happens. + */ + public void testStateChange_withSchemaInjectionFailure() + { + _class = new QpidClass(TestConstants.EXCHANGE_CLASS_NAME,TestConstants.HASH,_package) + { + @Override + void requestSchema() throws Exception + { + // DO NOTHING. + } + + @Override + void setSchema(List<Map<String, Object>> propertyDefinitions, + List<Map<String, Object>> statisticDefinitions, + List<MethodOrEventDataTransferObject> methodDefinitions) + throws UnableToBuildFeatureException + { + throw new UnableToBuildFeatureException(""); + } + }; + + assertSame( + "Initial state must be schema-not-requested.", + _class._schemaNotRequested, + _class._state); + + _class.addInstrumentationData(TestConstants.OBJECT_ID, TestConstants.TEST_RAW_DATA); + + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + + try { + _class.setSchema( + TestConstants.EMPTY_PROPERTIES_SCHEMA, + TestConstants.EMPTY_STATISTICS_SCHEMA, + TestConstants.EMPTY_METHODS_SCHEMA); + fail("If we are here something was wrong becuase the setSchema() of this event is throwing an exception..."); + } catch (UnableToBuildFeatureException expected) { + assertSame( + "Request schema has been requested but not yet injected. The current state is not indicating that!", + _class._schemaRequestedButNotYetInjected, + _class._state); + } + } + + private Map<String,Object> createProperty( + String name, + Integer accessCode, + String unit, + Integer min, + Integer max, + Integer maxLength, + String description, + Integer type, + boolean optional, + Integer index) + { + Map <String,Object> result = new HashMap<String, Object>(); + result.put(QpidFeatureBuilder.Attribute.name.name(),name); + result.put(QpidFeatureBuilder.Attribute.access.name(), accessCode); + + if (unit != null) + { + result.put(QpidFeatureBuilder.Attribute.unit.name(),unit); + } + + if (min != null) + { + result.put(QpidFeatureBuilder.Attribute.min.name(), min); + } + + if (max != null) + { + result.put(QpidFeatureBuilder.Attribute.max.name(),max); + } + + if (maxLength != null) + { + result.put(QpidFeatureBuilder.Attribute.maxlen.name(),maxLength); + } + + result.put(QpidFeatureBuilder.Attribute.desc.name(), description); + result.put(QpidFeatureBuilder.Attribute.type.name(), type); + result.put(QpidFeatureBuilder.Attribute.optional.name(),optional ? 1 : 0); + + if (index != null) + { + result.put(QpidFeatureBuilder.Attribute.index.name(), index); + } + return result; + } +} diff --git a/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java b/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java new file mode 100644 index 0000000000..8a8adee294 --- /dev/null +++ b/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/model/QpidEventTest.java @@ -0,0 +1,293 @@ +/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.management.domain.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import junit.framework.TestCase;
+
+import org.apache.qpid.management.TestConstants;
+import org.apache.qpid.management.configuration.ConfigurationException;
+import org.apache.qpid.management.configuration.StubConfigurator;
+import org.apache.qpid.management.domain.model.QpidEvent.QpidManagedEvent;
+
+/**
+ * Test case for qpid class entity.
+ *
+ * @author Andrea Gazzarini
+ */
+public class QpidEventTest extends TestCase
+{
+ private QpidEvent _event;
+ private QpidPackage _qpidPackage;
+
+ @Override
+ protected void setUp () throws Exception
+ {
+ _qpidPackage = new QpidPackage(TestConstants.QPID_PACKAGE_NAME,TestConstants.DOMAIN_MODEL);
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage);
+ }
+
+ /**
+ * Tests the execution of the createEventInstance() method.
+ * Basically it tests the addition of a new event instance.
+ *
+ * <br>precondition: event deifinition has no object instances.
+ * <br>precondition : event definition contains the new object instance.
+ */
+ public void testCreateEventInstance()
+ {
+ assertTrue(
+ "A just created event should be empty. I mean there shouldn't be event instances inside.",
+ _event.hasNoInstances());
+
+ QpidManagedEvent instance = createEventInstance();
+
+ assertFalse (
+ "Now a new instance should be there...",
+ _event.hasNoInstances());
+
+ assertEquals(TestConstants.TEST_RAW_DATA,instance._rawEventData);
+ assertEquals(TestConstants.NOW,instance._timestamp);
+ assertEquals(TestConstants.SEVERITY, instance._severity);
+ }
+
+ /**
+ * Tests the internal state change of an event definition.
+ */
+ public void testStateChange() throws UnableToBuildFeatureException
+ {
+ // Let's override this class because this is not an online tests and therefore
+ // QMan is not supposed to be up.
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ // Do Nothing.
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> argumentDefinitions)throws UnableToBuildFeatureException {
+ _state = _schemaInjected;
+ }
+ };
+
+ assertSame(
+ "Initial state doesn't match.",
+ _event._schemaNotRequested,
+ _event._state);
+
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+
+ _event.setSchema(TestConstants.EMPTY_ARGUMENTS_SCHEMA);
+
+ assertSame(
+ "Request schema has been injected. The current state is not indicating that!",
+ _event._schemaInjected,
+ _event._state);
+ }
+
+ /**
+ * Tests the injection of a valid schema on a QpidEvent.
+ *
+ * <br>precondition : a valid arguments is injected on the qpid event.
+ * <br>postcondition : event definition is built successfully.
+ */
+ public void testSchemaInjectionOK() throws UnableToBuildFeatureException, ConfigurationException, InstanceNotFoundException, MBeanException, ReflectionException
+ {
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception
+ {
+ // DO NOTHING : QMan is not running and therefore the schema will be manually injected.
+ }
+
+ @Override
+ void updateEventInstanceWithData(QpidManagedEvent instance)
+ {
+ // DO NOTHING : otherwise we should supply a valid raw data to be converted. ;-)
+ }
+ };
+
+ StubConfigurator configurator = new StubConfigurator();
+ configurator.configure();
+
+ List<Map<String,Object>> arguments = new ArrayList<Map<String, Object>>();
+ arguments.add(createArgument(TestConstants.AGE_ATTRIBUTE_NAME, TestConstants.AGE_ATTRIBUTE_DESCRIPTION));
+ arguments.add(createArgument(TestConstants.SURNAME_ATTRIBUTE_NAME, TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION));
+
+ // Incoming data : that will fire the schema request and a state change from schema-not-requested to schema-requested-but-not-injected
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ // I must be sure that what is obvious for me it's obvious for QMan... :)
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+
+ // Inject schema
+ _event.setSchema(arguments);
+
+ // Arguments must be 2 + 2 (severity)
+ assertEquals(2,_event._arguments.size());
+
+ QpidProperty argument = _event._arguments.get(TestConstants.AGE_ATTRIBUTE_NAME);
+ assertEquals(TestConstants.AGE_ATTRIBUTE_NAME,argument.getName());
+ assertEquals(AccessMode.RO,argument.getAccessMode());
+ assertEquals(TestConstants.AGE_ATTRIBUTE_DESCRIPTION,argument.getDescription());
+ assertEquals(String.class,argument.getJavaType());
+ assertFalse(argument.isOptional());
+
+ argument = _event._arguments.get(TestConstants.SURNAME_ATTRIBUTE_NAME);
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_NAME,argument.getName());
+ assertEquals(AccessMode.RO,argument.getAccessMode());
+ assertEquals(TestConstants.SURNAME_ATTRIBUTE_DESCRIPTION,argument.getDescription());
+ assertEquals(String.class,argument.getJavaType());
+ assertFalse(argument.isOptional());
+
+ assertEquals(1,_event._eventInstances.size());
+
+ JmxService service = new JmxService();
+ Set<ObjectName> objectNames = service.getEventMBeans();
+
+ assertEquals(1,objectNames.size());
+ }
+
+ /**
+ * Tests the behaviour of the event class when a schema request can't be made.
+ *
+ * <br>precondition : event must be in "schema-not-requested" state when incoming data arrives.
+ * <br>postcondition : no exception is thrown and no state transition happens.
+ */
+ public void testStateChange_withRequestSchemaFailure()
+ {
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ throw new Exception();
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> argumentDefinitions)throws UnableToBuildFeatureException {
+ _state = _schemaInjected;
+ }
+ };
+
+ assertSame(
+ "Initial state must be schema-not-requested.",
+ _event._schemaNotRequested,
+ _event._state);
+
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ assertSame(
+ "Current state must be still schema-not-requested.",
+ _event._schemaNotRequested,
+ _event._state);
+ }
+
+ /**
+ * Tests the behaviour of the event class when a schema injection fails.
+ *
+ * <br>precondition : event must be in "schema-not-requested" state when incoming data arrives.
+ * <br>postcondition : an exception is thrown and no state transition happens.
+ */
+ public void testStateChange_withSchemaInjectionFailure()
+ {
+ _event = new QpidEvent(TestConstants.BIND_EVENT_NAME,TestConstants.HASH,_qpidPackage)
+ {
+ @Override
+ void requestSchema() throws Exception {
+ // DO NOTHING.
+ }
+
+ @Override
+ void setSchema(List<Map<String, Object>> argumentDefinitions)throws UnableToBuildFeatureException {
+ throw new UnableToBuildFeatureException("");
+ }
+ };
+
+ assertSame(
+ "Initial state must be schema-not-requested.",
+ _event._schemaNotRequested,
+ _event._state);
+
+ _event.addEventData(TestConstants.TEST_RAW_DATA, TestConstants.NOW, TestConstants.SEVERITY);
+
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+
+ try {
+ _event.setSchema(TestConstants.EMPTY_ARGUMENTS_SCHEMA);
+ fail("If we are here something was wrong becuase the setSchema() of this event is throwing an exception...");
+ } catch (UnableToBuildFeatureException expected) {
+ assertSame(
+ "Request schema has been requested but not yet injected. The current state is not indicating that!",
+ _event._schemaRequestedButNotYetInjected,
+ _event._state);
+ }
+ }
+
+ /**
+ * Factory method for qpid managed event instances.
+ *
+ * @return a new QpidManagedEvent with test data inside.
+ */
+ private QpidManagedEvent createEventInstance()
+ {
+ return _event.createEventInstance(
+ TestConstants.TEST_RAW_DATA,
+ TestConstants.NOW,
+ TestConstants.SEVERITY);
+ }
+
+ /**
+ * Factory method for event argument.
+ *
+ * @return a new argument metadata.
+ */
+ private Map<String,Object> createArgument(String name,String desc)
+ {
+ Map <String,Object> argument = new HashMap<String, Object>();
+ argument.put(QpidFeatureBuilder.Attribute.name.name(),name);
+ argument.put(QpidFeatureBuilder.Attribute.desc.name(), desc);
+ argument.put(QpidFeatureBuilder.Attribute.type.name(), TestConstants._1);
+ return argument;
+ }
+}
diff --git a/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java b/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java index 1561314d2f..533c98c973 100644 --- a/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java +++ b/qpid/java/management/client/src/test/java/org/apache/qpid/management/domain/services/BrokerMessageListenerTest.java @@ -127,7 +127,7 @@ public class BrokerMessageListenerTest extends TestCase _listener._handlers.isEmpty()); _handlers.put(opcodeForWrongHandler,wrongMessageHandler); - + _listener.setHandlers(_handlers); assertEquals("Now we should have two handlers configured.",2,_listener._handlers.size()); @@ -167,4 +167,4 @@ public class BrokerMessageListenerTest extends TestCase _listener.onMessage(message); } -}
\ No newline at end of file +} |