blob: 52429ee69dcb27ca92b26a5b5418da354cdf1d1a [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.axis2.addressing;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.AttributeHelper;
import org.apache.axiom.om.util.ElementHelper;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.metadata.InterfaceName;
import org.apache.axis2.addressing.metadata.ServiceName;
import org.apache.axis2.addressing.metadata.WSDLLocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* The methods in this class are used to process {@link EndpointReference} objects
* according to the rules of the 2005/08 (Final) and 2004/08 (submission) WS-Addressing
* specifications.
*/
public class EndpointReferenceHelper {
private static final Log log = LogFactory.getLog(EndpointReferenceHelper.class);
private final static Map finalQNames = new IdentityHashMap();
private final static Map submissionQNames = new IdentityHashMap();
/**
* Populates an endpoint reference based on the <code>OMElement</code> and
* WS-Addressing namespace that is passed in.
*
* @param epr an endpoint reference instance to hold the info.
* @param eprOMElement an element of endpoint reference type
* @param addressingNamespace the namespace of the WS-Addressing spec to comply with.
* @throws AxisFault if unable to locate an address element, or if the specified namespace
* is different to the actual namespace.
* @see #fromOM(OMElement)
*/
public static void fromOM(EndpointReference epr, OMElement eprOMElement,
String addressingNamespace) throws AxisFault {
String namespace = fromOM(epr, eprOMElement);
if (!namespace.equals(addressingNamespace))
throw new AxisFault("The endpoint reference does not match the specified namespace.");
}
/**
* Populates an endpoint reference based on the <code>OMElement</code>. Returns the
* WS-Addressing namespace of the endpoint reference.
*
* @param epr an endpoint reference instance to hold the info. If the endpoint
* reference is null then just the WS-Addressing namespace is returned.
* @param eprOMElement an element of endpoint reference type
* @return a string representing the WS-Addressing namespace of the endpoint reference.
* @throws AxisFault if unable to locate an address element.
*/
public static String fromOM(EndpointReference epr, OMElement eprOMElement)
throws AxisFault {
boolean isFinalAddressingNamespace = false;
Map map = null;
//First pass, identify the addressing namespace.
OMElement address = eprOMElement
.getFirstChildWithName((QName) finalQNames.get(AddressingConstants.EPR_ADDRESS));
if (address != null) {
map = finalQNames;
isFinalAddressingNamespace = true;
if (log.isDebugEnabled()) {
log.debug("fromOM: Found address element for namespace, " +
AddressingConstants.Final.WSA_NAMESPACE);
}
} else {
address = eprOMElement.getFirstChildWithName(
(QName) submissionQNames.get(AddressingConstants.EPR_ADDRESS));
if (address != null) {
map = submissionQNames;
isFinalAddressingNamespace = false;
if (log.isDebugEnabled()) {
log.debug("fromOM: Found address element for namespace, " +
AddressingConstants.Submission.WSA_NAMESPACE);
}
} else {
throw new AxisFault(
"Unable to locate an address element for the endpoint reference type.");
}
}
//Second pass, identify the properties.
if (epr != null)
fromOM(epr, eprOMElement, map, isFinalAddressingNamespace);
return ((QName) map.get(AddressingConstants.EPR_ADDRESS)).getNamespaceURI();
}
/**
* Populates an endpoint reference based on the <code>String</code> that is
* passed in. If the http://schemas.xmlsoap.org/ws/2004/08/addressing namespace
* is in effect then any reference properties will be saved as reference parameters.
* Regardless of the addressing namespace in effect, any elements present in the
* <code>String</code> that are not recognised are saved as extensibility elements.
*
* @param eprString string from the element of endpoint reference type
* @throws AxisFault if unable to locate an address element
* @deprecated use {@link #fromString(String)} instead.
*/
public static EndpointReference fromOM(String eprString) throws AxisFault {
return fromString(eprString);
}
/**
* Populates an endpoint reference based on the <code>String</code> that is
* passed in. If the http://schemas.xmlsoap.org/ws/2004/08/addressing namespace
* is in effect then any reference properties will be saved as reference parameters.
* Regardless of the addressing namespace in effect, any elements present in the
* <code>String</code> that are not recognised are saved as extensibility elements.
*
* @param eprString string from the element of endpoint reference type
* @throws AxisFault if unable to locate an address element
*/
public static EndpointReference fromString(String eprString) throws AxisFault {
try {
return fromOM(new StAXOMBuilder(
new ByteArrayInputStream(eprString.getBytes())).getDocumentElement());
} catch (XMLStreamException e) {
throw AxisFault.makeFault(e);
}
}
/**
* Populates an endpoint reference based on the <code>OMElement</code> that is
* passed in. If the http://schemas.xmlsoap.org/ws/2004/08/addressing namespace
* is in effect then any reference properties will be saved as reference parameters.
* Regardless of the addressing namespace in effect, any elements present in the
* <code>OMElement</code> that are not recognised are saved as extensibility elements.
*
* @param eprOMElement an element of endpoint reference type
* @throws AxisFault if unable to locate an address element
*/
public static EndpointReference fromOM(OMElement eprOMElement) throws AxisFault {
EndpointReference epr = new EndpointReference("");
fromOM(epr, eprOMElement);
return epr;
}
/**
* Creates an <code>OMElement</code> based on the properties of the endpoint
* reference. The output may differ based on the addressing namespace that is
* in effect when this method is called. If the http://www.w3.org/2005/08/addressing
* namespace is in effect, and a metadata property has been defined for the
* endpoint reference, then there will be a metadata element to contain the
* property in the output. If the http://schemas.xmlsoap.org/ws/2004/08/addressing
* namespace is in effect, however, then no metadata element will be included
* in the output, even if a metadata property element has been defined.
*
* @param factory
* @param epr
* @param qname
* @param addressingNamespace
* @return
* @throws AxisFault
*/
public static OMElement toOM(OMFactory factory, EndpointReference epr, QName qname,
String addressingNamespace) throws AxisFault {
OMElement eprElement = null;
if (log.isDebugEnabled()) {
log.debug("toOM: Factory, " + factory);
log.debug("toOM: Endpoint reference, " + epr);
log.debug("toOM: Element qname, " + qname);
log.debug("toOM: Addressing namespace, " + addressingNamespace);
}
if (addressingNamespace == null) {
throw new AxisFault("Addressing namespace cannot be null.");
}
if (qname.getPrefix() != null) {
OMNamespace wrapNs =
factory.createOMNamespace(qname.getNamespaceURI(), qname.getPrefix());
if (factory instanceof SOAPFactory) {
eprElement =
((SOAPFactory) factory).createSOAPHeaderBlock(qname.getLocalPart(), wrapNs);
} else {
eprElement = factory.createOMElement(qname.getLocalPart(), wrapNs);
}
OMNamespace wsaNS = factory.createOMNamespace(addressingNamespace,
AddressingConstants.WSA_DEFAULT_PREFIX);
OMElement addressE =
factory.createOMElement(AddressingConstants.EPR_ADDRESS, wsaNS, eprElement);
String address = epr.getAddress();
addressE.setText(address);
ArrayList addressAttributes = epr.getAddressAttributes();
if (addressAttributes != null) {
Iterator attrIter = addressAttributes.iterator();
while (attrIter.hasNext()) {
OMAttribute omAttribute = (OMAttribute) attrIter.next();
AttributeHelper.importOMAttribute(omAttribute, addressE);
}
}
List metaData = epr.getMetaData();
if (metaData != null &&
AddressingConstants.Final.WSA_NAMESPACE.equals(addressingNamespace)) {
OMElement metadataE = factory.createOMElement(
AddressingConstants.Final.WSA_METADATA, wsaNS, eprElement);
for (int i = 0, size = metaData.size(); i < size; i++) {
OMElement omElement = (OMElement) metaData.get(i);
metadataE.addChild(ElementHelper.importOMElement(omElement, factory));
}
ArrayList metadataAttributes = epr.getMetadataAttributes();
if (metadataAttributes != null) {
Iterator attrIter = metadataAttributes.iterator();
while (attrIter.hasNext()) {
OMAttribute omAttribute = (OMAttribute) attrIter.next();
AttributeHelper.importOMAttribute(omAttribute, metadataE);
}
}
}
Map referenceParameters = epr.getAllReferenceParameters();
if (referenceParameters != null) {
OMElement refParameterElement = factory.createOMElement(
AddressingConstants.EPR_REFERENCE_PARAMETERS, wsaNS, eprElement);
Iterator iterator = referenceParameters.values().iterator();
while (iterator.hasNext()) {
OMElement omElement = (OMElement) iterator.next();
refParameterElement.addChild(ElementHelper.importOMElement(omElement, factory));
}
}
List attributes = epr.getAttributes();
if (attributes != null) {
for (int i = 0, size = attributes.size(); i < size; i++) {
OMAttribute omAttribute = (OMAttribute) attributes.get(i);
AttributeHelper.importOMAttribute(omAttribute, eprElement);
}
}
// add xs:any
List extensibleElements = epr.getExtensibleElements();
if (extensibleElements != null) {
for (int i = 0, size = extensibleElements.size(); i < size; i++) {
OMElement omElement = (OMElement) extensibleElements.get(i);
eprElement.addChild(ElementHelper.importOMElement(omElement, factory));
}
}
} else {
throw new AxisFault("prefix must be specified");
}
return eprElement;
}
private static void fromOM(EndpointReference epr, OMElement eprOMElement, Map map,
boolean isFinalAddressingNamespace) {
Iterator childElements = eprOMElement.getChildElements();
while (childElements.hasNext()) {
OMElement eprChildElement = (OMElement) childElements.next();
QName qname = eprChildElement.getQName();
if (map.get(AddressingConstants.EPR_ADDRESS).equals(qname)) {
//We need to identify the address element again in order to ensure
//that it is not included with the extensibility elements.
epr.setAddress(eprChildElement.getText());
Iterator allAddrAttributes = eprChildElement.getAllAttributes();
ArrayList addressAttributes = new ArrayList();
while (allAddrAttributes.hasNext()) {
OMAttribute attribute = (OMAttribute) allAddrAttributes.next();
addressAttributes.add(attribute);
}
epr.setAddressAttributes(addressAttributes);
} else if (map.get(AddressingConstants.EPR_REFERENCE_PARAMETERS).equals(qname)) {
Iterator iterator = eprChildElement.getChildElements();
while (iterator.hasNext()) {
OMElement element = (OMElement) iterator.next();
epr.addReferenceParameter(element);
}
} else if (isFinalAddressingNamespace &&
map.get(AddressingConstants.Final.WSA_METADATA).equals(qname)) {
Iterator iterator = eprChildElement.getChildElements();
while (iterator.hasNext()) {
OMNode node = (OMNode) iterator.next();
epr.addMetaData(node);
}
Iterator allMDAttributes = eprChildElement.getAllAttributes();
ArrayList metadataAttributes = new ArrayList();
while (allMDAttributes.hasNext()) {
OMAttribute attribute = (OMAttribute) allMDAttributes.next();
metadataAttributes.add(attribute);
}
epr.setMetadataAttributes(metadataAttributes);
} else if (!isFinalAddressingNamespace &&
map.get(AddressingConstants.Submission.EPR_REFERENCE_PROPERTIES).equals(qname))
{
// since we have the model for WS-Final, we don't have a place to keep this reference properties.
// The only compatible place is reference properties
Iterator iterator = eprChildElement.getChildElements();
while (iterator.hasNext()) {
OMElement element = (OMElement) iterator.next();
epr.addReferenceParameter(element);
}
} else {
epr.addExtensibleElement(eprChildElement);
}
}
Iterator attributes = eprOMElement.getAllAttributes();
while (attributes.hasNext()) {
OMAttribute attribute = (OMAttribute) attributes.next();
epr.addAttribute(attribute);
}
if (log.isDebugEnabled()) {
log.debug("fromOM: Endpoint reference, " + epr);
}
}
/**
* Retrieves the WS-Addressing EPR ServiceName element from an EPR.
*
* @param epr the EPR to retrieve the element from
* @param addressingNamespace the WS-Addressing namespace associated with
* the EPR.
* @return an instance of <code>ServiceName</code>. The return value is
* never <code>null</code>.
* @throws AxisFault
*/
public static ServiceName getServiceNameMetadata(EndpointReference epr, String addressingNamespace) throws AxisFault {
ServiceName serviceName = new ServiceName();
List elements = null;
if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace))
elements = epr.getExtensibleElements();
else
elements = epr.getMetaData();
if (elements != null) {
//Retrieve the service name and endpoint name.
for (int i = 0, size = elements.size(); i < size; i++) {
OMElement omElement = (OMElement) elements.get(i);
if (ServiceName.isServiceNameElement(omElement)) {
serviceName.fromOM(omElement);
break;
}
}
}
return serviceName;
}
/**
* Retrieves the WS-Addressing EPR PortType, or InterfaceName, element from an EPR,
* as appropriate.
*
* @param epr the EPR to retrieve the element from
* @param addressingNamespace the WS-Addressing namespace associated with
* the EPR.
* @return an instance of <code>InterfaceName</code>. The return value is
* never <code>null</code>.
* @throws AxisFault
*/
public static InterfaceName getInterfaceNameMetadata(EndpointReference epr, String addressingNamespace) throws AxisFault {
InterfaceName interfaceName = new InterfaceName();
List elements = null;
if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace))
elements = epr.getExtensibleElements();
else
elements = epr.getMetaData();
if (elements != null) {
//Retrieve the service name and endpoint name.
for (int i = 0, size = elements.size(); i < size; i++) {
OMElement omElement = (OMElement) elements.get(i);
if (InterfaceName.isInterfaceNameElement(omElement)) {
interfaceName.fromOM(omElement);
break;
}
}
}
return interfaceName;
}
/**
* Retrieves the wsdli:wsdlLocation attribute from an EPR.
*
* @param epr the EPR to retrieve the attribute from
* @param addressingNamespace the WS-Addressing namespace associated with
* the EPR.
* @return an instance of <code>WSDLLocation</code>. The return value is
* never <code>null</code>.
* @throws AxisFault
*/
public static WSDLLocation getWSDLLocationMetadata(EndpointReference epr, String addressingNamespace) throws AxisFault {
WSDLLocation wsdlLocation = new WSDLLocation();
List attributes = null;
if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace))
attributes = epr.getAttributes();
else
attributes = epr.getMetadataAttributes();
if (attributes != null) {
//Retrieve the wsdl location.
for (int i = 0, size = attributes.size(); i < size; i++) {
OMAttribute omAttribute = (OMAttribute) attributes.get(i);
if (WSDLLocation.isWSDLLocationAttribute(omAttribute)) {
wsdlLocation.fromOM(omAttribute);
break;
}
}
}
return wsdlLocation;
}
/**
* Adds an instance of <code>ServiceName</code> as metadata to the specified EPR.
* The metadata is mapped to a WS-Addressing EPR ServiceName element.
*
* @param factory an <code>OMFactory</code>
* @param epr the EPR to retrieve the attribute from
* @param addressingNamespace the WS-Addressing namespace associated with
* the EPR.
* @param serviceName an instance of <code>ServiceName</code> that contains the
* metadata
* @throws AxisFault
*/
public static void setServiceNameMetadata(OMFactory factory, EndpointReference epr, String addressingNamespace, ServiceName serviceName) throws AxisFault {
if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace)) {
OMElement omElement = serviceName.toOM(factory, ServiceName.subQName);
epr.addExtensibleElement(omElement);
}
else {
OMElement omElement = serviceName.toOM(factory, ServiceName.wsamQName);
epr.addMetaData(omElement);
}
}
/**
* Adds an instance of <code>InterfaceName</code> as metadata to the specified EPR.
* The metadata is mapped to a WS-Addressing EPR PortType or InterfaceName element.
*
* @param factory an <code>OMFactory</code>
* @param epr the EPR to retrieve the attribute from
* @param addressingNamespace the WS-Addressing namespace associated with
* the EPR.
* @param interfaceName an instance of <code>InterfaceName</code> that contains the
* metadata
* @throws AxisFault
*/
public static void setInterfaceNameMetadata(OMFactory factory, EndpointReference epr, String addressingNamespace, InterfaceName interfaceName) throws AxisFault {
if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace)) {
OMElement omElement = interfaceName.toOM(factory, InterfaceName.subQName);
epr.addExtensibleElement(omElement);
}
else {
OMElement omElement = interfaceName.toOM(factory, InterfaceName.wsamQName);
epr.addMetaData(omElement);
}
}
/**
* Adds an instance of <code>WSDLLocation</code> as metadata to the specified EPR.
* The metadata is mapped to a wsdli:wsdlLocation attribute.
*
* @param factory an <code>OMFactory</code>
* @param epr the EPR to retrieve the attribute from
* @param addressingNamespace the WS-Addressing namespace associated with
* the EPR.
* @param wsdlLocation an instance of <code>WSDLLocation</code> that contains the
* metadata
* @throws AxisFault
*/
public static void setWSDLLocationMetadata(OMFactory factory, EndpointReference epr, String addressingNamespace, WSDLLocation wsdlLocation) throws AxisFault {
OMAttribute attribute = wsdlLocation.toOM(factory);
if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace)) {
epr.addAttribute(attribute);
}
else {
ArrayList list = new ArrayList();
list.add(attribute);
epr.setMetadataAttributes(list);
}
}
static {
finalQNames.put(AddressingConstants.EPR_ADDRESS, new QName(
AddressingConstants.Final.WSA_NAMESPACE, AddressingConstants.EPR_ADDRESS));
finalQNames.put(AddressingConstants.EPR_REFERENCE_PARAMETERS, new QName(
AddressingConstants.Final.WSA_NAMESPACE,
AddressingConstants.EPR_REFERENCE_PARAMETERS));
finalQNames.put(AddressingConstants.Final.WSA_METADATA, new QName(
AddressingConstants.Final.WSA_NAMESPACE, AddressingConstants.Final.WSA_METADATA));
submissionQNames.put(AddressingConstants.EPR_ADDRESS, new QName(
AddressingConstants.Submission.WSA_NAMESPACE, AddressingConstants.EPR_ADDRESS));
submissionQNames.put(AddressingConstants.EPR_REFERENCE_PARAMETERS, new QName(
AddressingConstants.Submission.WSA_NAMESPACE,
AddressingConstants.EPR_REFERENCE_PARAMETERS));
submissionQNames.put(AddressingConstants.Submission.EPR_REFERENCE_PROPERTIES, new QName(
AddressingConstants.Submission.WSA_NAMESPACE,
AddressingConstants.Submission.EPR_REFERENCE_PROPERTIES));
}
}