blob: 52fbb41ae3201c3882f0795f1df029b207092498 [file] [log] [blame]
/*
* 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;
}
}