| /* |
| * 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.ode.utils.wsdl; |
| |
| import org.apache.ode.utils.Namespaces; |
| import org.apache.ode.utils.stl.CollectionsX; |
| import org.w3c.dom.Element; |
| |
| import javax.wsdl.Binding; |
| import javax.wsdl.BindingFault; |
| import javax.wsdl.BindingInput; |
| import javax.wsdl.BindingOperation; |
| import javax.wsdl.Definition; |
| import javax.wsdl.Fault; |
| import javax.wsdl.Operation; |
| import javax.wsdl.Part; |
| import javax.wsdl.Port; |
| import javax.wsdl.Service; |
| import javax.wsdl.extensions.ExtensibilityElement; |
| import javax.wsdl.extensions.UnknownExtensibilityElement; |
| import javax.wsdl.extensions.http.HTTPAddress; |
| import javax.wsdl.extensions.http.HTTPBinding; |
| import javax.wsdl.extensions.http.HTTPOperation; |
| import javax.wsdl.extensions.http.HTTPUrlEncoded; |
| import javax.wsdl.extensions.http.HTTPUrlReplacement; |
| import javax.wsdl.extensions.mime.MIMEContent; |
| import javax.wsdl.extensions.mime.MIMEMultipartRelated; |
| import javax.wsdl.extensions.soap.SOAPAddress; |
| import javax.wsdl.extensions.soap.SOAPBinding; |
| import javax.wsdl.extensions.soap.SOAPOperation; |
| import javax.xml.namespace.QName; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * @author <a href="mailto:midon@intalio.com">Alexis Midon</a> |
| */ |
| public class WsdlUtils { |
| |
| private static final Messages msgs = Messages.getMessages(Messages.class); |
| |
| /** |
| * Test if the given binding uses a Soap binding. |
| * |
| * @param binding |
| * @return true if {@link SOAPBinding} is assignable from the binding |
| * @see #getBindingExtension(javax.wsdl.Binding) |
| */ |
| public static boolean useSOAPBinding(Binding binding) { |
| ExtensibilityElement element = getBindingExtension(binding); |
| return SOAPBinding.class.isAssignableFrom(element.getClass()); |
| } |
| |
| |
| /** |
| * Test if the given binding uses HTTP binding. |
| * |
| * @param binding |
| * @return true if {@link HTTPBinding} is assignable from the binding |
| * @see #getBindingExtension(javax.wsdl.Binding) |
| */ |
| public static boolean useHTTPBinding(Binding binding) { |
| ExtensibilityElement element = getBindingExtension(binding); |
| // with a fully wsdl-compliant document, this element cannot be null. |
| // but ODE extends the HTTP binding and supports the HTTP verb at the operation level. |
| // A port using this extension may have no HTTPBinding at the port level. |
| if (element == null) { |
| // in this case, we check the binding information of one operation |
| final BindingOperation anOperation = (BindingOperation) binding.getBindingOperations().get(0); |
| final ExtensibilityElement opExt = getOperationExtension(anOperation); |
| return HTTPOperation.class.isAssignableFrom(opExt.getClass()); |
| } else { |
| return HTTPBinding.class.isAssignableFrom(element.getClass()); |
| } |
| } |
| |
| |
| /** |
| * @see #useSOAPBinding(javax.wsdl.Binding) |
| */ |
| public static boolean useSOAPBinding(Port port) { |
| return useSOAPBinding(port.getBinding()); |
| } |
| |
| /** |
| * @see #useHTTPBinding(javax.wsdl.Binding) |
| */ |
| public static boolean useHTTPBinding(Port port) { |
| return useHTTPBinding(port.getBinding()); |
| } |
| |
| /** |
| * @see #useSOAPBinding(javax.wsdl.Binding) |
| */ |
| public static boolean useSOAPBinding(Definition def, QName serviceName, String portName) { |
| Service serviceDef = def.getService(serviceName); |
| if (serviceDef == null) |
| throw new IllegalArgumentException(msgs.msgServiceDefinitionNotFound(serviceName)); |
| Port port = serviceDef.getPort(portName); |
| if (port == null) |
| throw new IllegalArgumentException(msgs.msgPortDefinitionNotFound(serviceName, portName)); |
| return useSOAPBinding(port); |
| } |
| |
| /** |
| * @see #useHTTPBinding(javax.wsdl.Binding) |
| */ |
| public static boolean useHTTPBinding(Definition def, QName serviceName, String portName) { |
| Service serviceDef = def.getService(serviceName); |
| if (serviceDef == null) |
| throw new IllegalArgumentException(msgs.msgServiceDefinitionNotFound(serviceName)); |
| Port port = serviceDef.getPort(portName); |
| if (port == null) |
| throw new IllegalArgumentException(msgs.msgPortDefinitionNotFound(serviceName, portName)); |
| return useHTTPBinding(port); |
| } |
| |
| /** |
| * Look up the ExtensibilityElement defining the binding for the given Port or |
| * throw an {@link IllegalArgumentException} if multiple bindings found. |
| * |
| * @param binding |
| * @return an instance of {@link SOAPBinding} or {@link HTTPBinding} or null |
| * @throws IllegalArgumentException if multiple bindings found. |
| */ |
| public static ExtensibilityElement getBindingExtension(Binding binding) { |
| Collection bindings = new ArrayList(); |
| CollectionsX.filter(bindings, binding.getExtensibilityElements(), HTTPBinding.class); |
| CollectionsX.filter(bindings, binding.getExtensibilityElements(), SOAPBinding.class); |
| if (bindings.size() == 0) { |
| return null; |
| } else if (bindings.size() > 1) { |
| // exception if multiple bindings found |
| throw new IllegalArgumentException(msgs.msgMultipleBindings(binding.getQName())); |
| } else { |
| // retrieve the single element |
| ExtensibilityElement result = (ExtensibilityElement) bindings.iterator().next(); |
| return result; |
| } |
| } |
| |
| /** |
| * @see #getBindingExtension(javax.wsdl.Binding) |
| */ |
| public static ExtensibilityElement getBindingExtension(Port port) { |
| Binding binding = port.getBinding(); |
| if (binding == null) { |
| throw new IllegalArgumentException(msgs.msgBindingNotFound(port.getName())); |
| } |
| return getBindingExtension(binding); |
| } |
| |
| /** |
| * Extract the instance of {@link javax.wsdl.extensions.http.HTTPOperation] or {@link javax.wsdl.extensions.soap.SOAPOperation} |
| * from the list of extensibility elements of the given {@link javax.wsdl.BindingOperation}. |
| * |
| * @param bindingOperation |
| * @return an instance of {@link javax.wsdl.extensions.http.HTTPOperation} or {@link javax.wsdl.extensions.soap.SOAPOperation} |
| * @throws IllegalArgumentException if not exactly 1 element is found. |
| */ |
| public static ExtensibilityElement getOperationExtension(BindingOperation bindingOperation) { |
| Collection operations = new ArrayList(); |
| CollectionsX.filter(operations, bindingOperation.getExtensibilityElements(), HTTPOperation.class); |
| CollectionsX.filter(operations, bindingOperation.getExtensibilityElements(), SOAPOperation.class); |
| |
| if (operations.size() == 0) { |
| // exception if no bindings found |
| throw new IllegalArgumentException(msgs.msgNoBindingForOperation(bindingOperation.getName())); |
| } else if (operations.size() > 1) { |
| // exception if multiple bindings found |
| throw new IllegalArgumentException(msgs.msgMultipleBindingsForOperation(bindingOperation.getName())); |
| } else { |
| // retrieve the single element |
| ExtensibilityElement result = (ExtensibilityElement) operations.iterator().next(); |
| return result; |
| } |
| |
| } |
| |
| /** |
| * @return true if the extensibility elements of the given {@link javax.wsdl.BindingInput} contains an instance of {@link javax.wsdl.extensions.http.HTTPUrlEncoded} |
| */ |
| public static boolean useUrlEncoded(BindingInput bindingInput) { |
| Collection<HTTPUrlEncoded> coll = CollectionsX.filter(bindingInput.getExtensibilityElements(), HTTPUrlEncoded.class); |
| return !coll.isEmpty(); |
| } |
| |
| /** |
| * @return true if the extensibility elements of the given {@link javax.wsdl.BindingInput} contains an instance of {@link javax.wsdl.extensions.http.HTTPUrlReplacement} |
| */ |
| public static boolean useUrlReplacement(BindingInput bindingInput) { |
| Collection<HTTPUrlReplacement> coll = CollectionsX.filter(bindingInput.getExtensibilityElements(), HTTPUrlReplacement.class); |
| return !coll.isEmpty(); |
| } |
| |
| /** |
| * @return true if the extensibility elements of the given {@link javax.wsdl.BindingInput} contains an instance of {@link javax.wsdl.extensions.mime.MIMEMultipartRelated} |
| */ |
| public static boolean useMimeMultipartRelated(BindingInput bindingInput) { |
| Collection<MIMEMultipartRelated> coll = CollectionsX.filter(bindingInput.getExtensibilityElements(), MIMEMultipartRelated.class); |
| return !coll.isEmpty(); |
| } |
| |
| /** |
| * @return the {@linkplain javax.wsdl.extensions.mime.MIMEContent#getType() type} of the instance of {@link javax.wsdl.extensions.mime.MIMEContent} |
| * contained in the extensibility element list. Or null if none. |
| * @throws IllegalArgumentException if more than 1 MIMEContent is found. |
| */ |
| public static MIMEContent getMimeContent(List extensibilityElements) { |
| Collection<MIMEContent> coll = CollectionsX.filter(extensibilityElements, MIMEContent.class); |
| if (coll.size() == 0) { |
| return null; |
| } else if (coll.size() > 1) { |
| // exception if multiple contents found |
| throw new IllegalArgumentException(msgs.msgMultipleMimeContent()); |
| } else { |
| // retrieve the single element |
| return coll.iterator().next(); |
| } |
| } |
| |
| /** |
| * Extract the instance of {@link javax.wsdl.extensions.http.HTTPAddress] or {@link javax.wsdl.extensions.soap.SOAPAddress} |
| * from the list of extensibility elements of the given {@link javax.wsdl.Port}. |
| * |
| * @param port |
| * @return an instance of {@link javax.wsdl.extensions.http.HTTPAddress} or {@link javax.wsdl.extensions.soap.SOAPAddress} |
| * @throws IllegalArgumentException if not exactly 1 element is found. |
| */ |
| public static ExtensibilityElement getAddressExtension(Port port) { |
| Collection operations = new ArrayList(); |
| CollectionsX.filter(operations, port.getExtensibilityElements(), HTTPAddress.class); |
| CollectionsX.filter(operations, port.getExtensibilityElements(), SOAPAddress.class); |
| |
| if (operations.size() == 0) { |
| // exception if no bindings found |
| throw new IllegalArgumentException(msgs.msgNoAddressForPort(port.getName())); |
| } else if (operations.size() > 1) { |
| // exception if multiple bindings found |
| throw new IllegalArgumentException(msgs.msgMultipleAddressesForPort(port.getName())); |
| } else { |
| // retrieve the single element |
| ExtensibilityElement result = (ExtensibilityElement) operations.iterator().next(); |
| return result; |
| } |
| } |
| |
| /** |
| * ODE extends the wsdl spec by allowing definition of the HTTP verb at the operation level. |
| * <br/> If you do so, an {@link UnknownExtensibilityElement} will be added to the list of extensibility elements of the {@link javax.wsdl.BindingOperation}. |
| * <br/> This method looks up for such an element and return the value of the verb attribute if the underlying {@link org.w3c.dom.Element} is {@literal <binding xmlns="http://schemas.xmlsoap.org/wsdl/http/"/>} |
| * or null. |
| * |
| * @param bindingOperation |
| */ |
| public static String getOperationVerb(BindingOperation bindingOperation) { |
| final Collection<UnknownExtensibilityElement> unknownExtElements = CollectionsX.filter(bindingOperation.getExtensibilityElements(), UnknownExtensibilityElement.class); |
| for (UnknownExtensibilityElement extensibilityElement : unknownExtElements) { |
| final Element e = extensibilityElement.getElement(); |
| if (Namespaces.ODE_HTTP_EXTENSION_NS.equalsIgnoreCase(e.getNamespaceURI()) |
| && "binding".equals(extensibilityElement.getElement().getLocalName()) |
| && e.hasAttribute("verb")) { |
| return e.getAttribute("verb"); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param fault |
| * @return true if the given fault is bound with the {@link org.apache.ode.utils.Namespaces.ODE_HTTP_EXTENSION_NS}:fault element. |
| */ |
| public static boolean isOdeFault(BindingFault fault) { |
| final Collection<UnknownExtensibilityElement> unknownExtElements = CollectionsX.filter(fault.getExtensibilityElements(), UnknownExtensibilityElement.class); |
| for (UnknownExtensibilityElement extensibilityElement : unknownExtElements) { |
| final Element e = extensibilityElement.getElement(); |
| if (Namespaces.ODE_HTTP_EXTENSION_NS.equalsIgnoreCase(e.getNamespaceURI()) |
| && "fault".equals(extensibilityElement.getElement().getLocalName())) { |
| // name attribute is optional, but if any it must match the fault name |
| if (e.hasAttribute("name")) { |
| return fault.getName().equals(e.getAttribute("name")); |
| } else { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| public static Collection<UnknownExtensibilityElement> getHttpHeaders(List extensibilityElements) { |
| final Collection<UnknownExtensibilityElement> unknownExtElements = CollectionsX.filter(extensibilityElements, UnknownExtensibilityElement.class); |
| for (UnknownExtensibilityElement extensibilityElement : unknownExtElements) { |
| final Element e = extensibilityElement.getElement(); |
| // keep only the header elements |
| if (!Namespaces.ODE_HTTP_EXTENSION_NS.equalsIgnoreCase(e.getNamespaceURI()) |
| || !"header".equals(extensibilityElement.getElement().getLocalName())) { |
| unknownExtElements.remove(extensibilityElement); |
| } |
| } |
| return unknownExtElements; |
| } |
| |
| /** |
| * Return the {@link javax.wsdl.Fault} that has the given element as message part. |
| * |
| * @param operation the operation |
| * @param elName the qname to look for |
| * @return the first fault for which the element of message part matches the given qname |
| */ |
| @SuppressWarnings("unchecked") |
| public static Fault inferFault(Operation operation, QName elName) { |
| for (Fault f : (Collection<Fault>) operation.getFaults().values()) { |
| if (f.getMessage() == null) continue; |
| Collection<Part> parts = f.getMessage().getParts().values(); |
| if (parts.isEmpty()) continue; |
| Part p = parts.iterator().next(); |
| if (p.getElementName() == null) continue; |
| if (p.getElementName().equals(elName)) return f; |
| } |
| return null; |
| } |
| |
| |
| /** |
| * ODE extends the wsdl spec by allowing definition of the HTTP verb at the operation level. |
| * <br/>The current implementation implementations allows you to have a {@literal <binding xmlns="http://schemas.xmlsoap.org/wsdl/http/"/>} element |
| * at the port level <strong>and</strong> at the operation level. In such a case the operation's verb overrides the port's verb. |
| * <br/> This method applies the later rule. |
| * <br/> If defined the operation's verb is returned, else the port's verb. |
| * |
| * @param binding |
| * @param bindingOperation |
| * @return If defined the operation's verb is returned, else the port's verb. |
| * @see #getOperationVerb(javax.wsdl.BindingOperation) |
| */ |
| public static String resolveVerb(Binding binding, BindingOperation bindingOperation) { |
| final HTTPBinding httpBinding = (HTTPBinding) WsdlUtils.getBindingExtension(binding); |
| String portVerb = httpBinding != null ? httpBinding.getVerb() : null; |
| String operationVerb = WsdlUtils.getOperationVerb(bindingOperation); |
| return operationVerb != null ? operationVerb : portVerb; |
| } |
| |
| } |