/* * 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.util.AXIOMUtil; 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.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 */ public static EndpointReference fromString(String eprString) throws AxisFault { try { return fromOM(AXIOMUtil.stringToOM(eprString)); } 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)); } }