From cd99f2b8454e6be2f1d05f9808096c280e843218 Mon Sep 17 00:00:00 2001 From: Andrea Gazzarini Date: Tue, 20 Jan 2009 15:20:57 +0000 Subject: QPID-1585 : WS-DM Method invocation feature. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@736031 13f79535-47bb-0310-9956-ffa450edef68 --- java/management/client/src/main/java/muse.xml | 6 +- .../java/org/apache/qpid/management/Messages.java | 10 +- .../java/org/apache/qpid/management/Names.java | 16 +- .../domain/handler/impl/InvocationResult.java | 4 +- .../qpid/management/servlet/WSDMAdapter.java | 1 - .../ArtifactsNotAvailableException.java | 7 + .../wsdm/capabilities/MBeanCapability.java | 65 ++- .../wsdm/capabilities/MBeanCapabilityBuilder.java | 356 ++++++++++++++--- .../wsdm/capabilities/QManAdapterCapability.java | 33 ++ .../QManMetadataExchangeCapability.java | 5 + .../qpid/management/wsdm/capabilities/Result.java | 111 ++++++ .../wsdm/capabilities/WSDMArtifactsDirector.java | 2 +- .../management/wsdm/capabilities/WsdlBuilder.java | 438 +++++++++++++++++---- .../wsdm/common/EntityInstanceNotFoundFault.java | 15 +- .../wsdm/common/MethodInvocationFault.java | 79 ++++ .../wsdm/common/NoSuchAttributeFault.java | 36 +- .../wsdm/muse/resources/QManWsResource.java | 2 +- .../wsdm/muse/serializer/ByteArraySerializer.java | 8 +- .../serializer/InvocationResultSerializer.java | 112 ++++++ .../wsdm/muse/serializer/MapSerializer.java | 19 +- .../client/src/main/java/wsdl/QManWsResource.wsdl | 9 +- 21 files changed, 1110 insertions(+), 224 deletions(-) create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java create mode 100644 java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java (limited to 'java') diff --git a/java/management/client/src/main/java/muse.xml b/java/management/client/src/main/java/muse.xml index 4ebcff445b..aa1ece3404 100644 --- a/java/management/client/src/main/java/muse.xml +++ b/java/management/client/src/main/java/muse.xml @@ -16,11 +16,15 @@ java.util.UUID org.apache.qpid.management.wsdm.muse.serializer.UUIDSerializer + + org.apache.qpid.management.wsdm.capabilities.Result + org.apache.qpid.management.wsdm.muse.serializer.InvocationResultSerializer + org.apache.muse.core.routing.SimpleResourceRouter log/muse.log - SEVERE + FINE org.apache.muse.core.routing.RouterFilePersistence diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Messages.java b/java/management/client/src/main/java/org/apache/qpid/management/Messages.java index 75e46afdfd..6acc83cd1a 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/Messages.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/Messages.java @@ -114,7 +114,6 @@ public interface Messages String QMAN_300002_UNKNOWN_SEQUENCE_NUMBER = " : Unable to deal with incoming message because it contains a unknown sequence number (%s)."; String QMAN_300003_BROKER_ALREADY_CONNECTED = " : Unable to enlist given broker connection data : QMan is already connected with broker %s"; String QMAN_300004_INVALID_CONFIGURATION_FILE = " : The given configuration file (%s) is not valid (it doesn't exist or cannot be read)"; - String QMAN_300005_QEMU_INITIALIZATION_FAILURE = " : Unable to initialize QEmu module and therefore emulation won't be enabled..."; // ERROR @@ -125,6 +124,8 @@ public interface Messages String QMAN_100005_CLASS_SCHEMA_PROCESSING_FAILURE = " : Q-Man was unable to process the schema response message."; String QMAN_100006_EVENT_SCHEMA_PROCESSING_FAILURE = " : Q-Man was unable to process the schema response message."; String QMAN_100007_UNABLE_TO_CONNECT_WITH_BROKER = " : Unable to connect with broker located on %s. This broker will be ignored."; + + String QMAN_100010_METHOD_INVOCATION_RESULT_FAILURE = " : an exception occurred while storing the result of a method invocation. Sequence number was %s"; String QMAN_100011_UNKNOWN_CLASS_KIND = " : Unknwon class kind : %s)."; String QMAN_100012_SCHEMA_MESSAGE_PROCESSING_FAILURE = " : Q-Man was unable to process the schema response message."; @@ -137,17 +138,16 @@ public interface Messages String QMAN_100019_REQ_OR_RES_MALFORMED = " : Unexpected exception occurred on WSDM adapter layer : probably request or response was malformed."; String QMAN_100020_ACTION_NOT_SUPPORTED = " : "+ACTION_NOT_SUPPORTED; String QMAN_100021_RMD_BUID_FAILURE = " : Unable to build RDM for resource %s."; - String QMAN_100022_ISOLATION_LAYER_SHUTDOWN_FAILURE = " : Unable to shutdown Isolation Layer."; + String QMAN_100023_BUILD_WS_ARTIFACTS_FAILURE = " : Unable to build WS artifacts."; String QMAN_100024_CAPABILITY_INSTANTIATION_FAILURE = " : Unable to instantiate generated capability class for %s."; String QMAN_100025_WSRF_FAILURE = " : Resource manager raised an exception while creating capability for %s."; String QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE = " : Exception occurred while replacing the placeholder soap address with resource actual location."; - - //// NEW String QMAN_100027_RESOURCE_SHUTDOWN_FAILURE = " : Shutdown failure while destroying resource %s."; String QMAN_100029_MALFORMED_RESOURCE_URI_FAILURE = " : Unable to define URI for QMan resources using \"%s\". It violates RFC 2396"; String QMAN_100030_JMX_CORE_STARTUP_FAILURE = " : QMan JMX core Unexpected failure while starting up."; - String QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED = " : Bad request has been received on this WS-Resource : Initialization is not possible because the resource has already been initialized."; + String QMAN_100031_WS_RESOURCE_ALREADY_INITIALIZED = " : Bad request has been received on this WS-Resource : Initialization is not possible because the resource has already been initialized."; String QMAN_100032_WS_RESOURCE_NOT_YET_INITIALIZED = " : Bad request has been received on this WS-Resource : Shutdown is not possible because the resource hasn't yet been initialized."; String QMAN_100033_WS_RESOURCE_ALREADY_SHUTDOWN = " : Bad request has been received on this WS-Resource : Shutdown is not possible because the resource has already been shutdown."; + String QMAN_100034_WSDL_SCHEMA_SECTION_NOT_FOUND = " : Unable to get via XPath the schema section in WSDL."; } \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/Names.java b/java/management/client/src/main/java/org/apache/qpid/management/Names.java index da533c6f59..db3cdf7abe 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/Names.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/Names.java @@ -28,7 +28,6 @@ import javax.xml.namespace.QName; */ public abstract class Names { - /** Name of the qpid management exchange. */ public static String MANAGEMENT_EXCHANGE = "qpid.management"; public static String MANAGEMENT_ROUTING_KEY = "console.#"; @@ -114,6 +113,21 @@ public abstract class Names "QManWsResourcePortType", Names.PREFIX); + public final static QName QMAN_STATUS_TEXT_NAME = new QName( + Names.NAMESPACE_URI, + "Message", + Names.PREFIX); + + public final static QName QMAN_STATUS_CODE_NAME = new QName( + Names.NAMESPACE_URI, + "ReturnCode", + Names.PREFIX); + + public final static QName QMAN_STATUS_ATTRIBUTE_NAME= new QName( + Names.NAMESPACE_URI, + "AttributeName", + Names.PREFIX); + public final static String NAME_ATTRIBUTE = "name"; public final static String MODIFIABILITY = "modifiability"; public final static String READ_WRITE = "read-write"; diff --git a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java index d188d20976..6dd213aa8c 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/domain/handler/impl/InvocationResult.java @@ -36,7 +36,7 @@ import org.apache.qpid.management.domain.services.MethodInvocationException; public class InvocationResult implements Serializable { private static final long serialVersionUID = 2062662997326399693L; - + private final long _returnCode; private final String _statusText; private final byte [] _outputAndBidirectionalArgumentValues; @@ -54,7 +54,7 @@ public class InvocationResult implements Serializable this._statusText = statusText; this._outputAndBidirectionalArgumentValues = outputAndBidirectionalArgumentValues; } - + /** * Checks if this result contains an error return code. * diff --git a/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java b/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java index 58f839bb33..10fcaeec0f 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/servlet/WSDMAdapter.java @@ -53,7 +53,6 @@ public class WSDMAdapter extends HttpServlet public void init() throws ServletException { LOGGER.debug(Messages.QMAN_000026_WSDM_ADAPTER_STARTS); - _isolationLayer = new WSDMAdapterIsolationLayer(getServletContext()); _isolationLayer.initialize(); diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java index 01463bc6d8..3f1188e5af 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/ArtifactsNotAvailableException.java @@ -34,6 +34,13 @@ public class ArtifactsNotAvailableException extends Exception private final WsArtifacts _artifacts; private final ObjectName _objectName; + /** + * Builds a new exception with the given arguments. + * + * @param artifacts the artifacts built. + * @param cause the exception cause. + * @param objectName the object name of the corresponding JMX entity. + */ public ArtifactsNotAvailableException(WsArtifacts artifacts,Throwable cause, ObjectName objectName) { super(cause); diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java index 76edf878a0..1942e8809e 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapability.java @@ -26,6 +26,7 @@ import java.lang.reflect.Array; import javax.management.Attribute; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; +import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.xml.namespace.QName; @@ -39,7 +40,10 @@ import org.apache.muse.ws.resource.basefaults.BaseFault; import org.apache.muse.ws.resource.basefaults.WsbfUtils; import org.apache.muse.ws.resource.impl.AbstractWsResourceCapability; import org.apache.muse.ws.resource.properties.ResourcePropertyCollection; +import org.apache.qpid.management.domain.handler.impl.InvocationResult; +import org.apache.qpid.management.domain.services.MethodInvocationException; import org.apache.qpid.management.wsdm.common.EntityInstanceNotFoundFault; +import org.apache.qpid.management.wsdm.common.MethodInvocationFault; import org.apache.qpid.management.wsdm.common.NoSuchAttributeFault; import org.apache.qpid.management.wsdm.common.QManFault; import org.apache.qpid.management.wsdm.muse.serializer.ByteArraySerializer; @@ -73,7 +77,7 @@ public abstract class MBeanCapability extends AbstractWsResourceCapability * * @param objectName the object name of the target mbean. */ - public void setResourceObjectName(ObjectName objectName) + void setResourceObjectName(ObjectName objectName) { this._objectName = objectName; } @@ -89,7 +93,7 @@ public abstract class MBeanCapability extends AbstractWsResourceCapability * be found. * @throws QManFault in case of internal system failure. */ - protected Object getAttribute(String attributeName) throws QManFault + Object getAttribute(String attributeName) throws QManFault { try { @@ -98,7 +102,6 @@ public abstract class MBeanCapability extends AbstractWsResourceCapability { throw new NoSuchAttributeFault( getWsResource().getEndpointReference(), - _objectName, attributeName); } catch (InstanceNotFoundException exception) { @@ -131,17 +134,15 @@ public abstract class MBeanCapability extends AbstractWsResourceCapability * @throws QManFault * in case of internal system failure. */ - protected void setAttribute(String attributeName, Object value) throws QManFault + void setAttribute(String attributeName, Object value) throws QManFault { try { - _mxServer.setAttribute(_objectName, new Attribute(attributeName, - value)); + _mxServer.setAttribute(_objectName, new Attribute(attributeName,value)); } catch (AttributeNotFoundException exception) { throw new NoSuchAttributeFault( getWsResource().getEndpointReference(), - _objectName, attributeName); } catch (InstanceNotFoundException exception) { @@ -156,6 +157,49 @@ public abstract class MBeanCapability extends AbstractWsResourceCapability } } + /** + * Invokes the requested operation on target JMX resource. + * + * @param operationName the name of the operation to be invoked. + * @param params parameters used for operation invocation. + * @param signature the operation / method signature. + * @throws QManFault when invocation fails. + */ + Result invoke(String operationName, Object [] params, String [] signature) throws QManFault + { + try + { + InvocationResult output = (InvocationResult) _mxServer.invoke(_objectName, operationName, params, signature); + Result result = new Result(output.getReturnCode(),output.getStatusText(),output.getOutputSection()); + return result; + } catch (InstanceNotFoundException e) + { + throw new EntityInstanceNotFoundFault( + getWsResource().getEndpointReference(), + _objectName); + } catch (MBeanException exception) + { + if (exception.getTargetException() instanceof MethodInvocationException) + { + MethodInvocationException failure = (MethodInvocationException) exception.getTargetException(); + throw new MethodInvocationFault( + getWsResource().getEndpointReference(), + operationName, + failure.getStatusText(), + failure.getReturnCode()); + } else { + throw new QManFault( + getWsResource().getEndpointReference(), + exception); + } + }catch(Exception exception) + { + throw new QManFault( + getWsResource().getEndpointReference(), + exception); + } + } + /** * * @param name @@ -192,13 +236,8 @@ public abstract class MBeanCapability extends AbstractWsResourceCapability // Object valuesArray = null; Class type = null; - + // TODO if (value.getClass().isArray()) { - // TODO : 'sta porcheria non va bene. L'ho inserita perché se il - // value è un array non vivne - // utilizzato il mio ByteArraySerializer ma array serializer che fa - // il serial degli elementi uno a uno : quindi - // cercava un serializer per "byte" if (value.getClass() == byte[].class) { Serializer serializer = new ByteArraySerializer(); try { diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java index df2a963d50..01d8c07e55 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/MBeanCapabilityBuilder.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.management.wsdm.capabilities; +import javassist.CannotCompileException; import javassist.ClassClassPath; import javassist.ClassPool; import javassist.CtClass; @@ -29,6 +30,7 @@ import javassist.CtNewMethod; import javax.management.MBeanAttributeInfo; import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.xml.namespace.QName; @@ -38,77 +40,138 @@ import org.apache.qpid.management.wsdm.common.QManFault; public class MBeanCapabilityBuilder implements IArtifactBuilder{ + private final static String GET_PROPERTY_NAMES_METHOD_COMMON_PART = "public QName[] getPropertyNames() { return "; + private final static String GET_PROPERTY_NAMES_METHOD_WITH_ARRAY = GET_PROPERTY_NAMES_METHOD_COMMON_PART+" PROPERTIES;}"; + private final static String GET_PROPERTY_NAMES_METHOD_WITH_EMPTY_ARRAY = GET_PROPERTY_NAMES_METHOD_COMMON_PART+" new QName[0];}"; + + /** + * Handler interface definining operation needed to be peformed (by a concrete + * implementor) when the "endAttributes" director callback happens. + * + * @author Andrea Gazzarini + */ + interface EndAttributesHandler { + + /** + * Concrete implementor must define in this method what + * needs to be done when the corresponding director callback + * happens (@see {@link MBeanCapabilityBuilder#endAttributes()} + * + * @throws BuilderException when a failure is raised inside the concrete implementation. + */ + void endAttributes() throws BuilderException; + }; + + /** + * This is the concrete implementation of the internal interface EndAttributesHandler + * that is activated when this builder detects the presence of at least one property on the + * capability class. + */ + private final EndAttributesHandler _atLeastThereIsOneProperty = new EndAttributesHandler() { + + /** + * Creates the QName array instance member and the corresponding + * accessor getPropertyNames(). + * + * @throws BuilderException when the member above cannot be added to the capability class. + */ + public void endAttributes() throws BuilderException + { + try + { + _properties.deleteCharAt(_properties.length()-1); + _properties.append("};"); + + CtField properties = CtField.make(_properties.toString(), _capabilityClassDefinition); + + _capabilityClassDefinition.addField(properties); + + CtMethod getPropertyNames = CtNewMethod.make( + GET_PROPERTY_NAMES_METHOD_WITH_ARRAY, + _capabilityClassDefinition); + _capabilityClassDefinition.addMethod(getPropertyNames); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + }; + + /** + * This is the concrete implementation of the internal interface EndAttributesHandler + * that is activated when this builder detects that there are no properties defined for + * the capability class. + */ + private final EndAttributesHandler _noPropertyHasBeenDefined= new EndAttributesHandler() + { + /** + * Creates the getPropertyNames() that simply returns an empty QName array. + * + * @throws BuilderException when the member above cannot be added to the capability class. + */ + public void endAttributes() throws BuilderException + { + try + { + CtMethod getPropertyNames = CtNewMethod.make( + GET_PROPERTY_NAMES_METHOD_WITH_EMPTY_ARRAY, + _capabilityClassDefinition); + _capabilityClassDefinition.addMethod(getPropertyNames); + } catch(Exception exception) + { + throw new BuilderException(exception); + } + } + }; + private StringBuilder _properties = new StringBuilder("private static final QName[] PROPERTIES = new QName[]{ "); private CtClass _capabilityClassDefinition; private Class _capabilityClass; + private EndAttributesHandler _endAttributeHandler = _noPropertyHasBeenDefined; + /** + * Director callback. + * Attrbute metadata notification. With this callback the director informs this builder that the + * currently processed MBean has an attribute with the given metadata. + * This builder uses this information in order to add a property and the corresponding accessors + * to the capability class that is going to be built. + * + * @throws BuilderException bytecode manipulation / creation failure. + */ public void onAttribute(MBeanAttributeInfo attribute) throws BuilderException { - String plainName = attribute.getName(); - - _properties.append("new QName(Names.NAMESPACE_URI, \"") - .append(attribute.getName()) - .append("\", Names.PREFIX),"); - + String name = attribute.getName(); String type = attribute.getType(); type = (type.startsWith("[B")) ? " byte[] " : type; - StringBuilder buffer = new StringBuilder() - .append("private ") - .append(type) - .append(' ') - .append(attribute.getName()) - .append(';'); try { - CtField field= CtField.make(buffer.toString(),_capabilityClassDefinition); - _capabilityClassDefinition.addField(field); - - char firstLetter = Character.toUpperCase(plainName.charAt(0)); - String nameForAccessors = firstLetter + plainName.substring(1); + addPropertyMemberInstance(type, name); + + String nameForAccessors = + Character.toUpperCase(name.charAt(0)) + + name.substring(1); if (attribute.isReadable()) { - buffer = new StringBuilder() - .append("public ") - .append(type) - .append(' ') - .append("get") - .append(nameForAccessors) - .append("() throws QManFault { return (").append(type).append(") getAttribute(\"") - .append(plainName) - .append("\"); }"); - - CtMethod getter = CtNewMethod.make(buffer.toString(),_capabilityClassDefinition); - _capabilityClassDefinition.addMethod(getter); + generateGetter(type, nameForAccessors); } if (attribute.isWritable()) { - buffer = new StringBuilder() - .append("public void ") - .append("set") - .append(nameForAccessors) - .append("(") - .append(type) - .append(" newValue) throws QManFault {") - .append(" setAttribute(\"") - .append(plainName) - .append("\", newValue); }"); - - CtMethod setter = CtNewMethod.make(buffer.toString(),_capabilityClassDefinition); - _capabilityClassDefinition.addMethod(setter); + generateSetter(type, nameForAccessors); } } catch(Exception exception) { throw new BuilderException(exception); } } - + /** * First callback : this method is called at the begin of the director process. - * It contains builder initialization code. + * Contains builder initialization code. * + * @param objectName the name of the target JMX entity of this capability. * @throws BuilderException when the initialization fails. */ public void begin(ObjectName objectName) throws BuilderException @@ -120,6 +183,8 @@ public class MBeanCapabilityBuilder implements IArtifactBuilder{ pool.importPackage(ObjectName.class.getPackage().getName()); pool.importPackage(QManFault.class.getPackage().getName()); pool.importPackage(Names.class.getPackage().getName()); + pool.importPackage(Result.class.getPackage().getName()); + _capabilityClassDefinition = pool.makeClass("org.apache.qpid.management.wsdm.capabilities."+className); try { @@ -130,42 +195,116 @@ public class MBeanCapabilityBuilder implements IArtifactBuilder{ } } - public void onOperation(MBeanOperationInfo operation) + /** + * Director callback. + * Operation metadata notification. With this callback the director informs this builder that the + * currently processed MBean has an operation with the given metadata. + * This builder uses this information in order to add a method to the capability class that is + * going to be built. + * + * For example, let's suppose that an operation like that is detected on the MBean : + * + * public void purge(int request) + * + * then the capability will be enrichied with the following method : + * + * public void purge(int request) throws QManFault { + * invoke( + * "purge", + * new Object[]{request}, + * new String[]{int.class.getName()}); + * } + * + * @throws BuilderException bytecode manipulation / creation failure. + */ + public void onOperation(MBeanOperationInfo operation) throws BuilderException { - // TODO : operation on mbean capability + try + { + StringBuilder method = new StringBuilder() + .append("public Result ") + .append(operation.getName()) + .append("( "); + + for (MBeanParameterInfo parameter: operation.getSignature()) + { + method + .append(parameter.getType()) + .append(' ') + .append(parameter.getName()) + .append(','); + } + + method.deleteCharAt(method.length()-1); + method.append(") throws QManFault { return invoke(") + .append("\"").append(operation.getName()).append("\"") + .append(", new Object[]{ "); + + for (MBeanParameterInfo parameter: operation.getSignature()) + { + method.append(parameter.getName()) + .append(','); + } + + method.deleteCharAt(method.length()-1); + method.append("}, new String[]{ "); + + for (MBeanParameterInfo parameter: operation.getSignature()) + { + method + .append("\"") + .append(parameter.getType()) + .append("\","); + } + method.deleteCharAt(method.length()-1); + method.append("}); }"); + + CtMethod definition = CtNewMethod.make(method.toString(),_capabilityClassDefinition); + _capabilityClassDefinition.addMethod(definition); + } catch(Exception exception) + { + throw new BuilderException(exception); + } } - public Class getCapabilityClass() + /** + * Returns the capability class (the product of this builder). + * + * @return the capability class (the product of this builder). + */ + Class getCapabilityClass() { return _capabilityClass; } + /** + * Determines what needs to be done when all attributes + * metadata has been notified to this builder. + * Capability class must have an array member with all defined + * properties and a getter method that returns it. + * In this method those two members are declared (obviously only + * if this capability has at least one property). + * + * @throws BuilderException when something fails during this phase. + */ public void endAttributes() throws BuilderException { - try - { - _properties.deleteCharAt(_properties.length()-1); - _properties.append("};"); - - CtField properties = CtField.make(_properties.toString(), _capabilityClassDefinition); - _capabilityClassDefinition.addField(properties); - - CtMethod getPropertyNames = CtNewMethod.make( - "public QName[] getPropertyNames() { return PROPERTIES;}", - _capabilityClassDefinition); - _capabilityClassDefinition.addMethod(getPropertyNames); - } catch(Exception exception) - { - throw new BuilderException(exception); - } + _endAttributeHandler.endAttributes(); } + /** + * Director callback. + * This method is notified when all operations metadata has been + * notified to this builder. + * This is the place where the capability class is created, defined and loaded by the JVM. + * + * @throws BuilderException issues on this method are basically class loading related. + */ @SuppressWarnings("unchecked") public void endOperations() throws BuilderException { try { - // Class loader and protection domain are needed for Qpid emulation. _capabilityClass = _capabilityClassDefinition.toClass( QManAdapterCapability.class.getClassLoader(), QManAdapterCapability.class.getProtectionDomain()); @@ -175,8 +314,97 @@ public class MBeanCapabilityBuilder implements IArtifactBuilder{ } } + /** + * Injects the module environment on this builder. + * + * @param environment the module environment. + */ public void setEnvironment(Environment environment) { // N.A. } + + /** + * Generates the get accessor method for the given property. + * + * @param type the type of the property. + * @param name the name of the property. + * @throws CannotCompileException compilation failure while adding the new feature. + */ + private void generateGetter(String type, String name) throws CannotCompileException + { + StringBuilder buffer = new StringBuilder() + .append("public ") + .append(type) + .append(' ') + .append("get") + .append(name) + .append("() throws QManFault { return (").append(type).append(") getAttribute(\"") + .append(name) + .append("\"); }"); + + CtMethod getter = CtNewMethod.make(buffer.toString(),_capabilityClassDefinition); + _capabilityClassDefinition.addMethod(getter); + + appendToPropertiesArray(name); + } + + /** + * Generates the set accessor method for the given property. + * + * @param type the type of the property. + * @param name the name of the property. + * @throws CannotCompileException compilation failure while adding the new feature. + */ + private void generateSetter(String type, String name) throws CannotCompileException + { + StringBuilder buffer = new StringBuilder() + .append("public void ") + .append("set") + .append(name) + .append("(") + .append(type) + .append(" newValue) throws QManFault {") + .append(" setAttribute(\"") + .append(name) + .append("\", newValue); }"); + + CtMethod setter = CtNewMethod.make(buffer.toString(),_capabilityClassDefinition); + _capabilityClassDefinition.addMethod(setter); + } + + /** + * Appends the given attribute name to the properties array declared as an + * instance member of the capability class. + * + * @param attributeName the name of the attribute. + */ + private void appendToPropertiesArray(String attributeName) + { + _properties.append("new QName(Names.NAMESPACE_URI, \"") + .append(attributeName) + .append("\", Names.PREFIX),"); + + _endAttributeHandler = _atLeastThereIsOneProperty; + } + + /** + * Adds a new property member instance to the capability class. + * + * @param type the type of the property. + * @param name the name of the property. + * @throws CannotCompileException when the property cannot be added. + */ + private void addPropertyMemberInstance(String type, String name) throws CannotCompileException + { + StringBuilder buffer = new StringBuilder() + .append("private ") + .append(type) + .append(' ') + .append(name) + .append(';'); + + CtField field= CtField.make(buffer.toString(),_capabilityClassDefinition); + _capabilityClassDefinition.addField(field); + } } \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java index 7d111b8031..ada995d35c 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManAdapterCapability.java @@ -21,7 +21,10 @@ package org.apache.qpid.management.wsdm.capabilities; import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; @@ -29,10 +32,13 @@ import javax.management.Notification; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectName; +import javax.xml.namespace.QName; import org.apache.muse.core.AbstractCapability; import org.apache.muse.core.Resource; import org.apache.muse.core.ResourceManager; +import org.apache.muse.core.routing.MessageHandler; +import org.apache.muse.core.routing.ReflectionMessageHandler; import org.apache.muse.core.serializer.SerializerRegistry; import org.apache.muse.ws.addressing.EndpointReference; import org.apache.muse.ws.addressing.soap.SoapFault; @@ -94,6 +100,8 @@ public class QManAdapterCapability extends AbstractCapability resource.setWsdlPortType(Names.QMAN_RESOURCE_PORT_TYPE_NAME); capability.setCapabilityURI(Names.NAMESPACE_URI+"/"+capability.getClass().getSimpleName()); + capability.setMessageHandlers(createMessageHandlers(capability)); + resource.addCapability(capability); resource.initialize(); resourceManager.addResource(resource.getEndpointReference(), resource); @@ -266,4 +274,29 @@ public class QManAdapterCapability extends AbstractCapability { } + + /** + * Creates the message handlers for the given capability. + * + * @param capability the QMan capability. + * @return a collection with message handlers for the given capability. + */ + protected Collection createMessageHandlers(MBeanCapability capability) + { + Collection handlers = new ArrayList(); + + for (Method method : capability.getClass().getDeclaredMethods()) + { + String name = method.getName(); + + QName requestName = new QName(Names.NAMESPACE_URI,name,Names.PREFIX); + QName returnValueName = new QName(Names.NAMESPACE_URI,name+"Response",Names.PREFIX); + + String actionURI = Names.NAMESPACE_URI+"/"+name; + MessageHandler handler = new ReflectionMessageHandler(actionURI, requestName, returnValueName); + handler.setMethod(method); + handlers.add(handler); + } + return handlers; + } } \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java index 28ce2c1f67..7e58992540 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/QManMetadataExchangeCapability.java @@ -42,6 +42,11 @@ import org.w3c.dom.Element; */ public class QManMetadataExchangeCapability extends WsrfMetadataExchange { + /** + * Returns the WSDL associated with the owner of this capability. + * + * @return the WSDL associated with the owner of this capability. + */ @Override protected Element getWSDL() { diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java new file mode 100644 index 0000000000..b8e22b4bc7 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/Result.java @@ -0,0 +1,111 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.capabilities; + +import java.util.*; + +/** + * Data Transfer Object that encapsulates the result of a method invocation. + * This is the object that will be marshalled in XML and will contain the result of a method + * invocation (status code & text). + * + * @author Andrea Gazzarini + */ +public class Result +{ + private long _statusCode; + private String _statusText; + private Map _outputParameters; + + /** + * Builds a new result DTO with the given parameters. + * + * @param statusCode the return code. + * @param statusText the status message. + * @param outputParameters the output parameters. + */ + public Result(long statusCode, String statusText,Map outputParameters) + { + this._statusCode = statusCode; + this._statusText = statusText; + this._outputParameters = outputParameters; + } + + /** + * Returns the status code. + * + * @return the status code. + */ + public long getStatusCode() + { + return _statusCode; + } + + /** + * Sets the status code. + * + * @param statusCode the status code. + */ + void setStatusCode(long statusCode) + { + this._statusCode = statusCode; + } + + /** + * Returns the status text. + * + * @return the status text. + */ + public String getStatusText() + { + return _statusText; + } + + /** + * Sets the status text. + * + * @param statusText the status text. + */ + void setStatusText(String statusText) + { + this._statusText = statusText; + } + + /** + * Returns the output parameterss. + * + * @return the output parameterss. + */ + public Map getOutputParameters() + { + return _outputParameters; + } + + /** + * Sets the output parameters. + * + * @param outputParameters the output parameters. + */ + void setOutputParameters(Map outputParameters) + { + this._outputParameters = outputParameters; + } +} diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java index 4c19475572..c9ffd5eac0 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WSDMArtifactsDirector.java @@ -131,7 +131,7 @@ class WSDMArtifactsDirector * * @throws BuilderException when one builder raises an exception during this operation. */ - void processOperations() + void processOperations() throws BuilderException { for (MBeanOperationInfo operation : _metadata.getOperations()) { diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java index 85b5198493..a9aa845f3d 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/capabilities/WsdlBuilder.java @@ -24,6 +24,7 @@ import java.net.InetAddress; import javax.management.MBeanAttributeInfo; import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.xml.namespace.QName; @@ -56,14 +57,6 @@ class WsdlBuilder implements IArtifactBuilder { { try { - if (schema == null) - { - - schema = (Element) XPathAPI.selectSingleNode( - _document.getDocumentElement(), - "/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://amqp.apache.org/qpid/management/qman']"); - - } /* @@ -80,58 +73,7 @@ class WsdlBuilder implements IArtifactBuilder { */ - if (attributeMetadata.getType().equals("java.util.Map")) - { - Element prop = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - prop.setAttribute("name",attributeMetadata.getName()); - - Element complexType = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","complexType","xsd")); - - Element sequence = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","sequence","xsd")); - - Element entry = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - entry.setAttribute("name", "entry"); - entry.setAttribute("minOccurs", "0"); - entry.setAttribute("maxOccurs", "unbounded"); - - Element complexType2 = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","complexType","xsd")); - Element sequence2 = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","sequence","xsd")); - - Element key = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - key.setAttribute("name", "key"); - key.setAttribute("type", "xsd:string"); - - Element value = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - value.setAttribute("name", "value"); - value.setAttribute("type", "xsd:anyType"); - - sequence2.appendChild(key); - sequence2.appendChild(value); - complexType2.appendChild(sequence2); - entry.appendChild(complexType2); - sequence.appendChild(entry); - complexType.appendChild(sequence); - prop.appendChild(complexType); - schema.appendChild(prop); - } else if ("java.util.UUID".equals(attributeMetadata.getType())) - { - Element prop = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - prop.setAttribute("name", attributeMetadata.getName()); - Element complexType = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","complexType","xsd")); - Element sequence = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","sequence","xsd")); - Element uuid = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - uuid.setAttribute("name", "uuid"); - uuid.setAttribute("type", "xsd:string"); - sequence.appendChild(uuid); - complexType.appendChild(sequence); - prop.appendChild(complexType); - schema.appendChild(prop); - } else { - Element propertyDeclaration = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); - propertyDeclaration.setAttribute("name",attributeMetadata.getName()); - propertyDeclaration.setAttribute("type", serializer.getXmlType(Class.forName(attributeMetadata.getType()))); - schema.appendChild(propertyDeclaration); - } + schema.appendChild(defineSchemaFor(attributeMetadata.getType(), attributeMetadata.getName())); Element wsrpProperties = (Element) XPathAPI.selectSingleNode( _document, @@ -148,14 +90,361 @@ class WsdlBuilder implements IArtifactBuilder { } } - public void begin(ObjectName objectName) + private Element defineSchemaFor(String type, String attributeName) throws Exception + { + if (type.equals("java.util.Map")) + { + Element prop = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + prop.setAttribute("name",attributeName); + + Element complexType = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","complexType","xsd")); + + Element sequence = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","sequence","xsd")); + + Element entry = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + entry.setAttribute("name", "entry"); + entry.setAttribute("minOccurs", "0"); + entry.setAttribute("maxOccurs", "unbounded"); + + Element complexType2 = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","complexType","xsd")); + Element sequence2 = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","sequence","xsd")); + + Element key = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + key.setAttribute("name", "key"); + key.setAttribute("type", "xsd:string"); + + Element value = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + value.setAttribute("name", "value"); + value.setAttribute("type", "xsd:anyType"); + + sequence2.appendChild(key); + sequence2.appendChild(value); + complexType2.appendChild(sequence2); + entry.appendChild(complexType2); + sequence.appendChild(entry); + complexType.appendChild(sequence); + prop.appendChild(complexType); + return prop; + } else if ("java.util.UUID".equals(type)) + { + Element prop = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + prop.setAttribute("name", attributeName); + Element complexType = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","complexType","xsd")); + Element sequence = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","sequence","xsd")); + Element uuid = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + uuid.setAttribute("name", "uuid"); + uuid.setAttribute("type", "xsd:string"); + sequence.appendChild(uuid); + complexType.appendChild(sequence); + prop.appendChild(complexType); + return prop; + } else { + Element propertyDeclaration = XmlUtils.createElement(_document, new QName("http://www.w3.org/2001/XMLSchema","element","xsd")); + propertyDeclaration.setAttribute("name",attributeName); + propertyDeclaration.setAttribute("type", serializer.getXmlType(Class.forName(type))); + return propertyDeclaration; + } + } + + public void begin(ObjectName objectName) throws BuilderException { this._objectName = objectName; + try + { + Attr location = (Attr) XPathAPI.selectSingleNode( + _document, + "/wsdl:definitions/wsdl:service/wsdl:port/wsdl-soap:address/@location"); + + StringBuilder builder = new StringBuilder("http://") + .append(InetAddress.getLocalHost().getHostName()) + .append(':') + .append(System.getProperty(Names.ADAPTER_PORT,"8080")) + .append('/') + .append("qman") + .append('/') + .append("services/QManWsResource"); + location.setValue(builder.toString()); + } catch(Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE); + throw new BuilderException(exception); + } + + try + { + schema = (Element) XPathAPI.selectSingleNode( + _document.getDocumentElement(), + "/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://amqp.apache.org/qpid/management/qman']"); + } catch(Exception exception) + { + LOGGER.error( + exception, + Messages.QMAN_100034_WSDL_SCHEMA_SECTION_NOT_FOUND); + throw new BuilderException(exception); + } +/* + + + + + + + + + + + + + + + + + + + + + +*/ + Element complexTypeResult = _document.createElement("xsd:complexType"); + complexTypeResult.setAttribute("name", "result"); + Element sequence = _document.createElement("xsd:sequence"); + complexTypeResult.appendChild(sequence); + + Element statusCode = _document.createElement("xsd:element"); + statusCode.setAttribute("name", "statusCode"); + statusCode.setAttribute("type", "xsd:long"); + + Element statusText = _document.createElement("xsd:element"); + statusCode.setAttribute("name", "statusText"); + statusCode.setAttribute("type", "xsd:string"); + + sequence.appendChild(statusCode); + sequence.appendChild(statusText); + + Element outputParams = _document.createElement("xsd:complexType"); + outputParams.setAttribute("name", "outputParameters"); + + Element complexTypeOutput = _document.createElement("xsd:complexType"); + Element outputSequence = _document.createElement("xsd:sequence"); + + outputParams.appendChild(complexTypeOutput); + complexTypeOutput.appendChild(outputSequence); + + Element entry = _document.createElement("xsd:element"); + entry.setAttribute("maxOccurs", "unbounded"); + entry.setAttribute("minOccurs", "0"); + entry.setAttribute("name", "entry"); + + outputSequence.appendChild(entry); + + Element entryComplexType = _document.createElement("xsd:complexType"); + Element entrySequence = _document.createElement("xsd:sequence"); + entryComplexType.appendChild(entrySequence); + + Element name = _document.createElement("xsd:name"); + name.setAttribute("name", "name"); + name.setAttribute("type", "xsd:string"); + + Element value = _document.createElement("xsd:element"); + value.setAttribute("name", "value"); + value.setAttribute("type", "xsd:anyType"); + + entrySequence.appendChild(name); + entrySequence.appendChild(value); + + schema.appendChild(complexTypeResult); } - public void onOperation(MBeanOperationInfo operation) + public void onOperation(MBeanOperationInfo operationMetadata) throws BuilderException { - // TODO : Operations on wsdl + // SCHEMA SECTION + /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */ + try + { + // + // + + Element methodRequestElement= _document.createElement("xsd:element"); + String methodNameRequest = operationMetadata.getName()+"Request"; + methodRequestElement.setAttribute("name", methodNameRequest); + methodRequestElement.setAttribute("type", "qman:"+methodNameRequest); + + // + Element methodResponseElement= _document.createElement("xsd:element"); + String methodNameResponse= operationMetadata.getName()+"Response"; + methodResponseElement.setAttribute("name", methodNameResponse); + methodResponseElement.setAttribute("type", "qman:"+methodNameResponse); + + schema.appendChild(methodRequestElement); + schema.appendChild(methodResponseElement); + + /* + + + + + + + + */ + + Element methodNameRequestComplexType = _document.createElement("xsd:complexType"); + methodNameRequestComplexType.setAttribute("name", methodNameRequest); + Element methodNameRequestComplexTypeSequence = _document.createElement("xsd:sequence"); + for(MBeanParameterInfo parameter : operationMetadata.getSignature()) + { + methodNameRequestComplexTypeSequence.appendChild(defineSchemaFor(parameter.getType(), parameter.getName())); + } + + methodNameRequestComplexType.appendChild(methodNameRequestComplexTypeSequence); + schema.appendChild(methodNameRequestComplexType); + + Element methodNameResponseComplexType = _document.createElement("xsd:complexType"); + methodNameResponseComplexType.setAttribute("name", methodNameResponse); + + Element methodNameResponseSequence = _document.createElement("xsd:sequence"); + methodNameResponseComplexType.appendChild(methodNameResponseSequence); + + Element result = _document.createElement("xsd:element"); + result.setAttribute("name", "result"); + result.setAttribute("type", "qman:invocationResult"); + methodNameResponseSequence.appendChild(result); + + schema.appendChild(methodNameResponseComplexType); + + /* + + + + + + + + */ + Element definitions = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions"); + + String requestMessageName = methodNameRequest+"Message"; + String responseMessageName = methodNameResponse+"Message"; + + Element requestMessage = _document.createElement("message"); + requestMessage.setAttribute("name", requestMessageName); + Element requestPart = _document.createElement("wsdl:part"); + requestPart.setAttribute("element", "qman:"+methodNameRequest); + requestPart.setAttribute("name", methodNameRequest); + requestMessage.appendChild(requestPart); + + Element responseMessage = _document.createElement("wsdl:message"); + responseMessage.setAttribute("name", responseMessageName); + Element responsePart = _document.createElement("wsdl:part"); + responsePart.setAttribute("element", "qman:"+methodNameResponse); + responsePart.setAttribute("name", methodNameResponse); + responseMessage.appendChild(responsePart); + + definitions.appendChild(requestMessage); + definitions.appendChild(responseMessage); + + + /* + + + + + + + */ + Element portType = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions/wsdl:portType"); + Element operation = _document.createElement("wsdl:operation"); + operation.setAttribute("name", operationMetadata.getName()); + + Element input = _document.createElement("wsdl:input"); + input.setAttribute("message", "qman:"+requestMessageName); + input.setAttribute("name", methodNameRequest); + input.setAttribute("wsa:action", Names.NAMESPACE_URI+"/"+operationMetadata.getName()); + + //name="SetResourcePropertiesRequest" wsa:Action="http://docs.oasis-open.org/wsrf/rpw-2/SetResourceProperties/SetResourcePropertiesRequest"/> + + operation.appendChild(input); + + Element output = _document.createElement("wsdl:output"); + output.setAttribute("message", "qman:"+responseMessageName); + output.setAttribute("name", methodNameResponse); + output.setAttribute("wsa:action", Names.NAMESPACE_URI+"/"+methodNameResponse); + + operation.appendChild(output); + + portType.appendChild(operation); + + /* + + + + + + + + + + */ + Element binding = (Element) XPathAPI.selectSingleNode(_document, "/wsdl:definitions/wsdl:binding"); + Element bindingOperation = _document.createElement("wsdl:operation"); + bindingOperation.setAttribute("name", operationMetadata.getName()); + + Element soapOperation = _document.createElement("wsdl-soap:operation"); + soapOperation.setAttribute("soapAction", Names.NAMESPACE_URI+"/"+operationMetadata.getName()); + + Element bindingInput = _document.createElement("wsdl:input"); + Element bodyIn = _document.createElement("wsdl-soap:body"); + bodyIn.setAttribute("use", "literal"); + + Element bindingOutput = _document.createElement("wsdl:output"); + Element bodyOut = _document.createElement("wsdl-soap:body"); + bodyOut.setAttribute("use", "literal"); + + bindingOutput.appendChild(bodyOut); + bindingInput.appendChild(bodyIn); + + bindingOperation.appendChild(soapOperation); + bindingOperation.appendChild(bindingInput); + bindingOperation.appendChild(bindingOutput); + + binding.appendChild(bindingOperation); + } catch(Exception exception) + { + throw new BuilderException(exception); + } } public void endAttributes() @@ -165,7 +454,7 @@ class WsdlBuilder implements IArtifactBuilder { public void endOperations() { - // N.A. + } public Document getWsdl() @@ -182,26 +471,5 @@ class WsdlBuilder implements IArtifactBuilder { public void setWsdlPath(String wsdlPath) { _document = WsdlUtils.createWSDL(_environment, wsdlPath, true); - try - { - Attr location = (Attr) XPathAPI.selectSingleNode( - _document, - "/wsdl:definitions/wsdl:service/wsdl:port/wsdl-soap:address/@location"); - - StringBuilder builder = new StringBuilder("http://") - .append(InetAddress.getLocalHost().getHostName()) - .append(':') - .append(System.getProperty(Names.ADAPTER_PORT,"8080")) - .append('/') - .append("qman") - .append('/') - .append("services/QManWsResource"); - location.setValue(builder.toString()); - } catch(Exception exception) - { - LOGGER.error( - exception, - Messages.QMAN_100026_SOAP_ADDRESS_REPLACEMENT_FAILURE); - } } } diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java index 5d158aa683..25bb871e75 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/EntityInstanceNotFoundFault.java @@ -50,17 +50,6 @@ public class EntityInstanceNotFoundFault extends QManFault */ public EntityInstanceNotFoundFault(EndpointReference endpointReference, ObjectName targetEntityName) { - super(endpointReference,EXCEPTION_QNAME,createMessage(targetEntityName)); + super(endpointReference,EXCEPTION_QNAME, targetEntityName.getCanonicalName()); } - - /** - * "Compose method" which creates the detail message for this exception. - * - * @param targetEntityName the object name. - * @return the detail message for this exception. - */ - private static String createMessage(ObjectName targetEntityName) - { - return String.format("Entity associated with name %s was not found.",targetEntityName); - } -} +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java new file mode 100644 index 0000000000..f24c2bfd46 --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/MethodInvocationFault.java @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.common; + +import javax.xml.namespace.QName; + +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.EndpointReference; +import org.apache.qpid.management.Names; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * This is the exception encapsulating the fault that will be thrown in case of + * method invocation failure. + * + * @author Andrea Gazzarini + */ +public class MethodInvocationFault extends QManFault +{ + private static final long serialVersionUID = 5977379710882983474L; + + private String _message; + private long _returnCode; + + /** + * Builds a new exception with the given endpoint reference and method invocation exception. + * This constructor will be used when the invocation thrown the MethodInvocationException. + * + * @param endpointReference the endpoint reference. + * @param methodName the name of the method. + * @param message the explanatio message. + * @param returnCode the a mnemonic code associated with the failure. + */ + public MethodInvocationFault( + EndpointReference endpointReference, + String methodName, + String message, + long returnCode) + { + super( + endpointReference, + new QName( + Names.NAMESPACE_URI, + "OperationInvocationFault", + Names.PREFIX), + String.format("OPERATION \"%s\" FAILURE. See detail section for further details.",methodName)); + this._message = message; + this._returnCode = returnCode; + } + + @Override + public Element getDetail() + { + Element detail = super.getDetail(); + Document owner = detail.getOwnerDocument(); + detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_TEXT_NAME,_message)); + detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_CODE_NAME,_returnCode)); + return detail; + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java index 81049ba460..e9f37f8afb 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/common/NoSuchAttributeFault.java @@ -20,15 +20,17 @@ */ package org.apache.qpid.management.wsdm.common; -import javax.management.ObjectName; import javax.xml.namespace.QName; +import org.apache.muse.util.xml.XmlUtils; import org.apache.muse.ws.addressing.EndpointReference; import org.apache.qpid.management.Names; +import org.w3c.dom.Document; +import org.w3c.dom.Element; /** - * This is the exception encapsulating the fault that will be thrown in case of - * method invocation failure. + * This is the exception encapsulating the fault that will be thrown when a requested + * attribute is not found on the target ws resource. * * @author Andrea Gazzarini */ @@ -36,14 +38,16 @@ public class NoSuchAttributeFault extends QManFault { private static final long serialVersionUID = 5977379710882983474L; + private String _attributeName; + /** - * Builds a new exception with the given endpoint reference and method invocation exception. - * This constructor will be used when the invocation thrown the MethodInvocationException. + * Builds a new exception with the given endpoint reference, JMX object name + * and attribute that hasn't been found. * * @param endpointReference the endpoint reference. - * @param exception the method invocation exception containing failure details. + * @param attributeName the name of the attribute that hasn't been found. */ - public NoSuchAttributeFault(EndpointReference endpointReference, ObjectName name, String attributeName) + public NoSuchAttributeFault(EndpointReference endpointReference, String attributeName) { super( endpointReference, @@ -51,18 +55,16 @@ public class NoSuchAttributeFault extends QManFault Names.NAMESPACE_URI, "NoSuchAttributeFault", Names.PREFIX), - createMessage(name, attributeName)); + "Attribute not found on this WS-Resource."); + _attributeName = attributeName; } - /** - * Creates the reason message for this fault. - * - * @param name the object name of the managed entity. - * @param attributeName the name of the attribute that wasn't found. - * @return the reason message for this fault. - */ - private static String createMessage(ObjectName name, String attributeName) + @Override + public Element getDetail() { - return String.format("Attribute %s was not found on entity %s",attributeName,name); + Element detail = super.getDetail(); + Document owner = detail.getOwnerDocument(); + detail.appendChild(XmlUtils.createElement(owner, Names.QMAN_STATUS_ATTRIBUTE_NAME,_attributeName)); + return detail; } } \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java index c65d716fb5..fc5f3fc7e4 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/resources/QManWsResource.java @@ -535,7 +535,7 @@ public class QManWsResource implements WsResource { Object[]parameters = handler.fromXML(requestBody); Object result = method.invoke(capability, parameters); - return handler.toXML(result); + return handler.toXML(result); } catch (Throwable throwable) { diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java index 88fbe5df6d..a064542658 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/ByteArraySerializer.java @@ -26,11 +26,9 @@ import javax.xml.namespace.QName; import org.apache.muse.core.serializer.Serializer; import org.apache.muse.util.xml.XmlUtils; import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.xerces.impl.dv.util.Base64; import org.w3c.dom.Element; -import sun.misc.BASE64Decoder; -import sun.misc.BASE64Encoder; - /** * Implementation of Muse Serializer for byte array type. * @@ -48,7 +46,7 @@ public class ByteArraySerializer implements Serializer { { try { - return new BASE64Decoder().decodeBuffer(xml.getTextContent()); + return Base64.decode(xml.getTextContent()); } catch (Exception exception) { throw new SoapFault(exception); @@ -77,7 +75,7 @@ public class ByteArraySerializer implements Serializer { { Element element = XmlUtils.createElement( qname, - new BASE64Encoder().encode((byte[]) object)); + Base64.encode((byte[]) object)); element.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); element.setAttribute("xsi:type","xsd:base64Binary"); return element; diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java new file mode 100644 index 0000000000..5e208a281d --- /dev/null +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/InvocationResultSerializer.java @@ -0,0 +1,112 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.management.wsdm.muse.serializer; + +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.muse.core.serializer.Serializer; +import org.apache.muse.core.serializer.SerializerRegistry; +import org.apache.muse.util.xml.XmlUtils; +import org.apache.muse.ws.addressing.soap.SoapFault; +import org.apache.qpid.management.wsdm.capabilities.Result; +import org.w3c.dom.Element; + +/** + * Implementation of Muse Serializer for Result type. + * + * @author Andrea Gazzarini + */ +public class InvocationResultSerializer implements Serializer +{ + + private Serializer _longSerializer = SerializerRegistry.getInstance().getSerializer(long.class); + private Serializer _stringSerializer = SerializerRegistry.getInstance().getSerializer(String.class); + private Serializer _mapSerializer = SerializerRegistry.getInstance().getSerializer(Map.class); + + /** + * Return a UUID representation of the given xml element. + * + * @param xml the element to unmarshal. + * @throws SoapFault when the unmarshalling fails. + */ + @SuppressWarnings("unchecked") + public Object fromXML(Element elementData) throws SoapFault + { + long statusCode = 0; + String statusText = null; + Map outputSection = null; + + Element[] elements = XmlUtils.getAllElements(elementData); + for (Element element : elements) + { + if ("statusCode".equals(element.getNodeName())) + { + statusCode = (Long) _longSerializer.fromXML(element); + } else if ("statusText".equals(element.getNodeName())) + { + statusText = (String) _stringSerializer.fromXML(element); + } else if ("outputParameters".equals(element.getNodeName())) + { + outputSection = (Map) _mapSerializer.fromXML(element); + } + } + + return new Result(statusCode,statusText,outputSection); + } + + /** + * Returns the java type associated to this class. + * + * @return the java type associated to this class. + */ + public Class getSerializableType() + { + return Result.class; + } + + /** + * Return an xml representation of the given UUID with the given name. + * + * @param object the UUID to marshal. + * @param qname the qualified (xml) name of the object to use in xml representation. + * @return the xml representation of the UUID. + * @throws SoapFault when the marshalling fails. + */ + public Element toXML(Object obj, QName qname) throws SoapFault + { + Result result = (Result) obj; + Element root = XmlUtils.createElement(qname); + Element statusCode = SerializerRegistry.getInstance().getSerializer(long.class).toXML(result.getStatusCode(), new QName("statusCode")); + Element statusText = SerializerRegistry.getInstance().getSerializer(String.class).toXML(result.getStatusText(), new QName("statusText")); + + root.appendChild(statusCode); + root.appendChild(statusText); + if (result.getOutputParameters() != null) + { + Element outputSection = SerializerRegistry.getInstance().getSerializer(Map.class).toXML(result.getOutputParameters(), new QName("outputParameters")); + root.appendChild(outputSection); + } + return root; + + } +} \ No newline at end of file diff --git a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java index 8a25baf4bd..6a404d45b9 100644 --- a/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java +++ b/java/management/client/src/main/java/org/apache/qpid/management/wsdm/muse/serializer/MapSerializer.java @@ -75,13 +75,7 @@ public class MapSerializer implements Serializer key = objectDeserializer.fromXML(element); } else if (Names.VALUE.equals(element.getNodeName())) { - if (value.getClass()==byte[].class) - { - value = byteArraySerializer.fromXML(element); - } else - { - value = objectDeserializer.fromXML(element); - } + value = objectDeserializer.fromXML(element); } } result.put(key, value); @@ -111,13 +105,10 @@ public class MapSerializer implements Serializer { Serializer objectSerializer = SerializerRegistry.getInstance().getSerializer(Object.class); Map data = (Map) obj; - - String namespaceURI = qname.getNamespaceURI(); - String prefix = qname.getPrefix(); - - QName entryQName = new QName(namespaceURI,Names.ENTRY,prefix); - QName keyQName = new QName(namespaceURI,Names.KEY,prefix); - QName valueQName = new QName(namespaceURI,Names.VALUE,prefix); + + QName entryQName = new QName(Names.ENTRY); + QName keyQName = new QName(Names.KEY); + QName valueQName = new QName(Names.VALUE); Element root = XmlUtils.createElement(qname); root.setAttribute("xmlns:xsi", XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI); diff --git a/java/management/client/src/main/java/wsdl/QManWsResource.wsdl b/java/management/client/src/main/java/wsdl/QManWsResource.wsdl index 3603319281..00139b70d1 100644 --- a/java/management/client/src/main/java/wsdl/QManWsResource.wsdl +++ b/java/management/client/src/main/java/wsdl/QManWsResource.wsdl @@ -60,7 +60,14 @@ - + + + + + + + + -- cgit v1.2.1