/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.binding.axis2.util; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.wsdl.Binding; import javax.wsdl.BindingInput; import javax.wsdl.BindingOperation; import javax.wsdl.BindingOutput; import javax.wsdl.Input; import javax.wsdl.Message; import javax.wsdl.Operation; import javax.wsdl.Output; import javax.wsdl.Part; import javax.wsdl.extensions.soap.SOAPBinding; import javax.wsdl.extensions.soap.SOAPHeader; import javax.wsdl.extensions.soap.SOAPOperation; import javax.xml.namespace.QName; /** * Metadata for a WSDL operation */ @SuppressWarnings({"all"}) public class WebServiceOperationMetaData implements Serializable { private static final long serialVersionUID = 2425306250256227724L; // WSDL Binding and BindingOperation private Binding binding; private BindingOperation bindingOperation; // Fields to cache derived metadata private transient Set inputHeaderParts; private transient Set outputHeaderParts; private transient String style; private transient String use; private transient String soapAction; private transient List signature; private String encoding; private transient QName rpcOperationName; public WebServiceOperationMetaData(Binding binding, BindingOperation bindingOperation) { this.binding = binding; this.bindingOperation = bindingOperation; } public WebServiceOperationMetaData(Binding binding, BindingOperation bindingOperation, String style, String use, String encoding, String soapAction) { this.binding = binding; this.bindingOperation = bindingOperation; this.style = style; this.use = use; this.encoding = encoding; this.soapAction = soapAction; } public Set getInputHeaderParts() { if (inputHeaderParts == null) { // Build a set of header parts that we need to exclude inputHeaderParts = new HashSet(); BindingInput bindingInput = bindingOperation.getBindingInput(); if (bindingInput != null) { Operation operation = bindingOperation.getOperation(); javax.wsdl.Message message = operation.getInput().getMessage(); List elements = bindingInput.getExtensibilityElements(); for (Iterator i = elements.iterator(); i.hasNext();) { Object extensibilityElement = i.next(); Part part = getPartFromSOAPHeader(message, extensibilityElement); if (part != null) { inputHeaderParts.add(part); } } } } return inputHeaderParts; } public Set getOutputHeaderParts() { if (outputHeaderParts == null) { // Build a set of header parts that we need to exclude outputHeaderParts = new HashSet(); BindingOutput bindingOutput = bindingOperation.getBindingOutput(); if (bindingOutput != null) { Operation operation = bindingOperation.getOperation(); javax.wsdl.Message message = operation.getOutput().getMessage(); List elements = bindingOutput.getExtensibilityElements(); for (Iterator i = elements.iterator(); i.hasNext();) { Object extensibilityElement = i.next(); Part part = getPartFromSOAPHeader(message, extensibilityElement); if (part != null) { outputHeaderParts.add(part); } } } } return outputHeaderParts; } private Part getPartFromSOAPHeader(Message message, Object extensibilityElement) { Part part = null; if (extensibilityElement instanceof SOAPHeader) { SOAPHeader soapHeader = (SOAPHeader) extensibilityElement; QName msgName = soapHeader.getMessage(); if (message.getQName().equals(msgName)) { part = message.getPart(soapHeader.getPart()); } } else if (extensibilityElement instanceof SOAPHeader) { SOAPHeader soapHeader = (SOAPHeader) extensibilityElement; QName msgName = soapHeader.getMessage(); if (message.getQName().equals(msgName)) { part = message.getPart(soapHeader.getPart()); } } return part; } public String getStyle() { if (style == null) { SOAPOperation soapOperation = (SOAPOperation) WebServicePortMetaData .getExtensibilityElement(bindingOperation.getExtensibilityElements(), SOAPOperation.class); if (soapOperation != null) { style = soapOperation.getStyle(); } if (style == null) { SOAPBinding soapBinding = WebServicePortMetaData .getExtensibilityElement(binding.getExtensibilityElements(), SOAPBinding.class); if (soapBinding != null) { style = soapBinding.getStyle(); } } if (style == null) { style = "document"; } } return style; } /** * Returns the SOAP action for the given operation. */ public String getSOAPAction() { if (soapAction == null) { final List wsdlBindingOperationExtensions = bindingOperation.getExtensibilityElements(); final SOAPOperation soapOp = WebServicePortMetaData.getExtensibilityElement(wsdlBindingOperationExtensions, SOAPOperation.class); if (soapOp != null) { soapAction = soapOp.getSoapActionURI(); } } return soapAction; } public QName getRPCOperationName() { if (rpcOperationName == null) { javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(true); String ns = (soapBody != null) ? soapBody.getNamespaceURI() : binding.getPortType().getQName().getNamespaceURI(); String name = bindingOperation.getOperation().getName(); rpcOperationName = new QName(ns, name); } return rpcOperationName; } private List getSOAPBodyParts(boolean input) { javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(input); if (soapBody != null) { List parts = soapBody.getParts(); if (parts != null) { List names = new ArrayList(); for (Iterator i = parts.iterator(); i.hasNext();) { Object part = i.next(); if (part instanceof String) { names.add((String) part); } else if (part instanceof Part) { names.add(((Part) part).getName()); } } return names; } else { return null; } } else { return null; } } private javax.wsdl.extensions.soap.SOAPBody getSOAPBody(boolean input) { List elements = null; if (input) { BindingInput bindingInput = bindingOperation.getBindingInput(); if (bindingInput == null) { return null; } elements = bindingInput.getExtensibilityElements(); } else { BindingOutput bindingOutput = bindingOperation.getBindingOutput(); if (bindingOutput == null) { return null; } elements = bindingOutput.getExtensibilityElements(); } javax.wsdl.extensions.soap.SOAPBody soapBody = WebServicePortMetaData.getExtensibilityElement(elements, javax.wsdl.extensions.soap.SOAPBody.class); return soapBody; } /** * Returns the use attribute */ public String getUse() { if (use == null) { javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(true); if (soapBody != null) { use = soapBody.getUse(); } if (use == null) { use = "literal"; } } return use; } @SuppressWarnings("unchecked") public String getEncoding() { if (encoding == null) { javax.wsdl.extensions.soap.SOAPBody soapBody = getSOAPBody(true); if (soapBody != null) { List styles = (List) soapBody.getEncodingStyles(); if (styles != null && !styles.isEmpty()) { encoding = styles.get(0); } } if (encoding == null) { encoding = ""; } } return encoding; } public boolean isDocLitWrapped() { boolean flag = getStyle().equals("document") && getUse().equals("literal"); if (!flag) { return false; } Message msg = getMessage(true); if (msg == null) { return false; } List parts = msg.getOrderedParts(null); if (parts.size() != 1) { return false; } Part part = (Part) parts.get(0); QName element = part.getElementName(); if (element == null) { return false; } return element.getLocalPart().equals(bindingOperation.getOperation().getName()); } /* * public SOAPMediator createMediator(boolean serverMode) throws SOAPException { * // create a new mediator for each invoke for thread-safety * boolean rpcStyle = getStyle().equals("rpc"); boolean rpcEncoded = isEncoded(); * * SOAPMediator mediator = null; * * if (!rpcStyle) { // Document mediator = new SOAPDocumentLiteralMediatorImpl(this, serverMode); * } else { if (!rpcEncoded) mediator = new * SOAPRPCLiteralMediatorImpl(this, serverMode); // RPC-literal else mediator = * new SOAPRPCEncodedMediatorImpl(this, serverMode); // RPC-encoded } * return mediator; } */ /** * Get the operation signature from the WSDL operation */ public List getOperationSignature() { if (signature == null) { signature = new ArrayList(); Operation operation = bindingOperation.getOperation(); if (operation == null) { return signature; } final Input input = operation.getInput(); if (input == null) { return signature; } String sstyle = getStyle(); if ("rpc".equals(sstyle)) { Collection partNames = input.getMessage().getParts().values(); for (Iterator i = partNames.iterator(); i.hasNext();) { Part part = (Part) i.next(); signature.add(part.getName()); } } else { /* * WS-I Basic Profile 1.1 4.7.6 Operation Signatures Definition: operation signature * * The profile defines the "operation signature" to be the fully qualified name of the child element of * SOAP body of the SOAP input * message described by an operation in a WSDL binding. * * In the case of rpc-literal binding, the operation name is used as a wrapper for the part accessors. * In the document-literal case, designed so that they meet this requirement. * * An endpoint that supports multiple operations must unambiguously identify the operation being * invoked based on the input message * that it receives. This is only possible if all the operations specified in the wsdl:binding * associated with an endpoint have a * unique operation signature. * * R2710 The operations in a wsdl:binding in a DESCRIPTION MUST result in operation signatures that are * different from one another. */ List bodyParts = getSOAPBodyParts(true); Collection parts = input.getMessage().getParts().values(); // Exclude the parts to be transmitted in SOAP header if (bodyParts == null) { parts.removeAll(getInputHeaderParts()); } for (Iterator i = parts.iterator(); i.hasNext();) { Part part = (Part) i.next(); if (bodyParts == null) { // All parts QName elementName = part.getElementName(); if (elementName == null) { elementName = new QName("", part.getName()); // TODO: [rfeng] throw new // ServiceRuntimeException("Message part for // document style must refer to an XSD element // using a QName: " + part); } signature.add(elementName); } else { // "parts" in soap:body if (bodyParts.contains(part.getName())) { QName elementName = part.getElementName(); if (elementName == null) { elementName = new QName("", part.getName()); // TODO: [rfeng] throw new // ServiceRuntimeException("Message part for // document style must refer to an XSD // element using a QName: " + part); } signature.add(elementName); } } } } } return signature; } public Message getMessage(boolean isInput) { Operation operation = bindingOperation.getOperation(); if (operation == null) { return null; } if (isInput) { final Input input = operation.getInput(); return input == null ? null : input.getMessage(); } else { final Output output = operation.getOutput(); return output == null ? null : output.getMessage(); } } public Part getInputPart(int index) { Part part = null; Message message = getMessage(true); if (message == null) { return part; } List parts = message.getOrderedParts(null); return (Part) parts.get(index); } public Part getOutputPart(int index) { Part part = null; Message message = getMessage(false); if (message == null) { return part; } List parts = message.getOrderedParts(null); return (Part) parts.get(index); } /** * Get a list of indexes for each part in the SOAP body * * @param isInput */ public List getBodyPartIndexes(boolean isInput) { List indexes = new ArrayList(); Message message = getMessage(isInput); if (message == null) { return indexes; } List bodyParts = getSOAPBodyParts(isInput); List parts = message.getOrderedParts(null); Set headerParts = isInput ? getInputHeaderParts() : getOutputHeaderParts(); int index = 0; for (Iterator i = parts.iterator(); i.hasNext(); index++) { Part part = (Part) i.next(); if (headerParts.contains(part)) { continue; } if (bodyParts == null) { // All parts indexes.add(index); } else { // "parts" in soap:body if (bodyParts.contains(part.getName())) { indexes.add(index); } } } return indexes; } /** * Get the corresponding index for a part in the SOAP header by element name * * @param elementName * @param isInput */ public int getHeaderPartIndex(QName elementName, boolean isInput) { Message message = getMessage(isInput); if (message == null) { return -1; } List parts = message.getOrderedParts(null); Set headerParts = isInput ? getInputHeaderParts() : getOutputHeaderParts(); int index = 0; for (Iterator i = parts.iterator(); i.hasNext(); index++) { Part part = (Part) i.next(); // Test if the part is in header section if (headerParts.contains(part) && elementName.equals(part.getElementName())) { return index; } } return -1; } public BindingOperation getBindingOperation() { return bindingOperation; } }