All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axis2.addressing.EndpointReference Maven / Gradle / Ivy

Go to download

Core Parts of Axis2. This includes Axis2 engine, Client API, Addressing support, etc.,

There is a newer version: 1.8.2
Show newest version
/*
 * 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.OMAbstractFactory;
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.OMXMLBuilderFactory;
import org.apache.axiom.util.UIDGenerator;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.externalize.ExternalizeConstants;
import org.apache.axis2.context.externalize.SafeObjectInputStream;
import org.apache.axis2.context.externalize.SafeObjectOutputStream;
import org.apache.axis2.context.externalize.SafeSerializable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Externalizable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Class EndpointReference
 * This class models the WS-A EndpointReferenceType. But this can be used without any WS-A handlers as well
 * Since the models for this in Submission and Final versions are different, lets make this to comply with
 * WS-A Final version. So any information found with WS-A submission will be "pumped" in to this model.
 */
public class EndpointReference implements Externalizable, SafeSerializable {

    private static final long serialVersionUID = 5278892171162372439L;

    private static final Log log = LogFactory.getLog(EndpointReference.class);
    
    //  supported revision levels, add a new level to manage compatible changes
    private static final int REVISION_2 = 2;
    // current revision level of this object
    private static final int revisionID = REVISION_2;

    private static final String myClassName = "EndpointReference";

    /**
     * An ID which can be used to correlate operations on an instance of
     * this object in the log files
     */
    private String logCorrelationIDString;
    
    /**
     * The list of URIs that should be considered equivalent to 
     * the WS-Addressing anonymous URI
     */
    private static volatile List anonymousEquivalentURIs = new ArrayList();


    /**
     * 
     * 
xs:anyURI
* xs:any* * xs:any* * *
*/ private String name; private String address; private ArrayList addressAttributes; private ArrayList metaData; private ArrayList metaDataAttributes; private Map referenceParameters; private ArrayList extensibleElements; private ArrayList attributes; /** * No-Arg Constructor * Required for Externalizable objects */ public EndpointReference() {} /** * Adds a parameter to the list of anonymous equivalent URIs. * @param anonymousEquivalentURI any URI that has an address that * begins with this value will be considered to be anonymous */ public static void addAnonymousEquivalentURI(String anonymousEquivalentURI){ if (log.isTraceEnabled()) log.trace("addAnonymousEquivalentURI: " + anonymousEquivalentURI); // Avoid synchronization in hasAnonymousAddress by using the // technique outlined at http://is.gd/gv3 synchronized (anonymousEquivalentURIs) { ArrayList newList = new ArrayList(anonymousEquivalentURIs); newList.add(anonymousEquivalentURI); anonymousEquivalentURIs = newList; } } /** * @param address */ public EndpointReference(String address) { this.address = address; } /** * @param omElement */ public void addReferenceParameter(OMElement omElement) { if (omElement == null) { return; } if (referenceParameters == null) { referenceParameters = new HashMap(); } referenceParameters.put(omElement.getQName(), omElement); } /** * @param qname * @param value - the text of the OMElement. Remember that this is a convenient method for the user, * which has limited capability. If you want more power use @See EndpointReference#addReferenceParameter(OMElement) */ public void addReferenceParameter(QName qname, String value) { if (qname == null) { return; } OMElement omElement = OMAbstractFactory.getOMFactory().createOMElement(qname, null); omElement.setText(value); addReferenceParameter(omElement); } /** * This will return a Map of reference parameters with QName as the key and an OMElement * as the value * * @return - map of the reference parameters, where the key is the QName of the reference parameter * and the value is an OMElement */ public Map getAllReferenceParameters() { return referenceParameters; } public String getAddress() { return address; } /** * @param address - xs:anyURI */ public void setAddress(String address) { this.address = address; } public ArrayList getAddressAttributes() { return addressAttributes; } public void setAddressAttributes(ArrayList al) { addressAttributes = al; } public ArrayList getMetadataAttributes() { return metaDataAttributes; } public void setMetadataAttributes(ArrayList al) { metaDataAttributes = al; } /** * This method identifies whether the address is a WS-Addressing spec defined * anonymous URI. * * @return true if the address is a WS-Addressing spec defined anonymous URI. * * @see #hasAnonymousAddress() */ public boolean isWSAddressingAnonymous() { return (AddressingConstants.Final.WSA_ANONYMOUS_URL.equals(address) || AddressingConstants.Submission.WSA_ANONYMOUS_URL.equals(address)); } /** * This method is used to identify when response messages should be sent using * the back channel of a two-way transport. * * @return true if the address is a WS-Addressing spec defined anonymous URI, * or starts with a string that is specified to be equivalent to an anonymous * URI. * * @see #addAnonymousEquivalentURI(String) */ public boolean hasAnonymousAddress() { boolean result = isWSAddressingAnonymous(); if(!result && address != null) { // If the address is not WS-A anonymous it might still be considered anonymous // Avoid synchronization by using the // technique outlined at http://is.gd/gv3 List localList = anonymousEquivalentURIs; if(!localList.isEmpty()){ Iterator it = localList.iterator(); while(it.hasNext()){ result = address.startsWith((String)it.next()); if(result){ break; } } } } if (log.isTraceEnabled()) { log.trace("hasAnonymousAddress: " + address + " is Anonymous: " + result); } return result; } /** * hasNoneAddress * * @return true if the address is the 'None URI' from the final addressing spec. */ public boolean hasNoneAddress() { boolean result = AddressingConstants.Final.WSA_NONE_URI.equals(address); if (log.isTraceEnabled()) { log.trace("hasNoneAddress: " + address + " is None: " + result); } return result; } /** * @param localName * @param ns * @param value */ public void addAttribute(String localName, OMNamespace ns, String value) { if (attributes == null) { attributes = new ArrayList(); } attributes.add(OMAbstractFactory.getOMFactory().createOMAttribute(localName, ns, value)); } public ArrayList getAttributes() { return attributes; } /** * @param omAttribute */ public void addAttribute(OMAttribute omAttribute) { if (attributes == null) { attributes = new ArrayList(); } attributes.add(omAttribute); } public ArrayList getExtensibleElements() { return extensibleElements; } /** * {any} * * @param extensibleElements */ public void setExtensibleElements(ArrayList extensibleElements) { this.extensibleElements = extensibleElements; } public void addExtensibleElement(OMElement extensibleElement) { if (extensibleElement != null) { if (this.extensibleElements == null) { this.extensibleElements = new ArrayList(); } this.extensibleElements.add(extensibleElement); } } public ArrayList getMetaData() { return metaData; } public void addMetaData(OMNode metaData) { if (metaData != null) { if (this.metaData == null) { this.metaData = new ArrayList(); } this.metaData.add(metaData); } } /** * @deprecated */ public String getName() { return name; } /** * @param name * @deprecated */ public void setName(String name) { this.name = name; } /** * Set a Map with QName as the key and an OMElement * as the value * * @param referenceParameters */ public void setReferenceParameters(Map referenceParameters) { this.referenceParameters = referenceParameters; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ public String toString() { StringBuffer buffer = new StringBuffer("Address: " + address); if (addressAttributes != null) { buffer.append(", Address Attributes: ").append(addressAttributes); } if (metaData != null) { buffer.append(", Metadata: ").append(metaData); } if (metaDataAttributes != null) { buffer.append(", Metadata Attributes: ").append(metaDataAttributes); } if (referenceParameters != null) { buffer.append(", Reference Parameters: ").append(referenceParameters); } if (extensibleElements != null) { buffer.append(", Extensibility elements: ").append(extensibleElements); } if (attributes != null) { buffer.append(", Attributes: ").append(attributes); } return buffer.toString(); } /** * Compares key parts of the state from the current instance of * this class with the specified instance to see if they are * equivalent. *

* This differs from the java.lang.Object.equals() method in * that the equals() method generally looks at both the * object identity (location in memory) and the object state * (data). *

* * @param epr The object to compare with * @return TRUE if this object is equivalent with the specified object * that is, key fields match * FALSE, otherwise */ public boolean isEquivalent(EndpointReference epr) { // NOTE: the input object is expected to exist (ie, be non-null) if ((this.name != null) && (epr.getName() != null)) { if (!this.name.equals(epr.getName())) { return false; } } else if ((this.name == null) && (epr.getName() == null)) { // continue } else { // mismatch return false; } if ((this.address != null) && (epr.getAddress() != null)) { if (!this.address.equals(epr.getAddress())) { return false; } } else if ((this.address == null) && (epr.getAddress() == null)) { // continue } else { // mismatch return false; } // TODO: is a strict test ok to use? ArrayList eprMetaData = epr.getMetaData(); if ((this.metaData != null) && (eprMetaData != null)) { if (!this.metaData.equals(eprMetaData)) { // This is a strict test // Returns true if and only if the specified object // is also a list, both lists have the same size, and // all corresponding pairs of elements in the two lists // are equal, ie, two lists are defined to be equal if // they contain the same elements in the same order. return false; } } else if ((this.metaData == null) && (eprMetaData == null)) { // keep going } else { // one of the lists is null return false; } ArrayList eprExtensibleElements = epr.getExtensibleElements(); if ((this.extensibleElements != null) && (eprExtensibleElements != null)) { if (!this.extensibleElements.equals(eprExtensibleElements)) { // This is a strict test // Returns true if and only if the specified object // is also a list, both lists have the same size, and // all corresponding pairs of elements in the two lists // are equal, ie, two lists are defined to be equal if // they contain the same elements in the same order. return false; } } else if ((this.extensibleElements == null) && (eprExtensibleElements == null)) { // keep going } else { // one of the lists is null return false; } ArrayList eprAttributes = epr.getAttributes(); if ((this.attributes != null) && (eprAttributes != null)) { if (!this.attributes.equals(eprAttributes)) { // This is a strict test // Returns true if and only if the specified object // is also a list, both lists have the same size, and // all corresponding pairs of elements in the two lists // are equal, ie, two lists are defined to be equal if // they contain the same elements in the same order. return false; } } else if ((this.attributes == null) && (eprAttributes == null)) { // keep going } else { // one of the lists is null return false; } // TODO: check the Map referenceParameters for equivalency return true; } //REVIEW: The following code is rather heavyweight, because we have to build // the OM tree -- it would probably be better to have two serialization/deserialization // paths and therefore, for trivial EPRs, store a smaller amount of info /** * Write the EPR to the specified OutputStream. Because of potential * OMElements/Attributes, we need to actually serialize the OM structures * (at least in some cases.) */ public synchronized void writeExternal(java.io.ObjectOutput o) throws IOException { SafeObjectOutputStream out = SafeObjectOutputStream.install(o); // revision ID out.writeInt(revisionID); // Correlation ID String logCorrelationIDString = getLogCorrelationIDString(); // String object id out.writeObject(logCorrelationIDString); // Write out the content as xml out.writeUTF("start xml"); // write marker OMElement om = EndpointReferenceHelper.toOM(OMAbstractFactory.getOMFactory(), this, new QName("urn:axis2", "omepr", "ser"), AddressingConstants.Final.WSA_NAMESPACE); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { om.serialize(baos); } catch (Exception e) { IOException ioe = new IOException("Unable to serialize the EndpointReference with logCorrelationID [" +logCorrelationIDString+"]"); ioe.initCause(e); if (log.isDebugEnabled()) { log.debug("writeObject(): Unable to serialize the EPR with logCorrelationID [" +logCorrelationIDString+"] original error ["+e.getClass().getName() +"] message ["+e.getMessage()+"]",e); } throw ioe; } out.writeInt(baos.size()); out.write(baos.toByteArray()); out.writeUTF("end xml"); // write marker if (log.isDebugEnabled()) { byte[] buffer = baos.toByteArray(); String content = new String(buffer); log.debug("writeObject(): EPR logCorrelationID ["+logCorrelationIDString+"] " +" EPR content size ["+baos.size()+"]" +" EPR content ["+content+"]"); } } /** * Read the EPR to the specified InputStream. */ public void readExternal(java.io.ObjectInput inObject) throws IOException, ClassNotFoundException { SafeObjectInputStream in = SafeObjectInputStream.install(inObject); // revision ID int revID = in.readInt(); // make sure the object data is in a revision level we can handle if (revID != REVISION_2) { throw new ClassNotFoundException(ExternalizeConstants.UNSUPPORTED_REVID); } // String object id logCorrelationIDString = (String) in.readObject(); // Read xml content in.readUTF(); // read marker int numBytes = in.readInt(); byte[] serBytes = new byte[numBytes]; // read the data from the input stream int bytesRead = 0; int numberOfBytesLastRead; while (bytesRead < numBytes) { numberOfBytesLastRead = in.read(serBytes, bytesRead, numBytes - bytesRead); if (numberOfBytesLastRead == -1) { // TODO: What should we do if the reconstitution fails? // For now, log the event and throw an exception if (log.isDebugEnabled()) { log.debug("readObject(): EPR logCorrelationID ["+logCorrelationIDString+"] " + " ***WARNING*** unexpected end to data: data read from input stream [" + bytesRead + "] expected data size [" + numBytes + "]"); } IOException ioe = new IOException("Unable to deserialize the EndpointReference with logCorrelationID [" +logCorrelationIDString+"]" +" Cause: Unexpected end to data from input stream"); throw ioe; } bytesRead += numberOfBytesLastRead; } if (bytesRead == 0) { IOException ioe = new IOException("Unable to deserialize the EndpointReference with logCorrelationID [" +logCorrelationIDString+"]" +" Cause: No data from input stream"); throw ioe; } in.readUTF(); // read marker ByteArrayInputStream bais = new ByteArrayInputStream(serBytes); if (log.isDebugEnabled()) { String content = new String(serBytes); log.debug("readObject(): EPR logCorrelationID ["+logCorrelationIDString+"] " +" expected content size ["+numBytes+"]" +" content size ["+content.length()+"]" +" EPR buffered content ["+content+"]"); } XMLStreamReader xmlReader = null; try { OMElement om = OMXMLBuilderFactory.createOMBuilder(bais).getDocumentElement(); // expand the OM so we can close the stream reader om.build(); // trace point if (log.isDebugEnabled()) { log.debug(myClassName + ":readObject(): " + " EPR ["+logCorrelationIDString + "]" + " EPR OM content ["+om.toString()+ "]"); } EndpointReferenceHelper.fromOM(this, om, AddressingConstants.Final.WSA_NAMESPACE); } catch (Exception e) { IOException ioe = new IOException("Unable to deserialize the EndpointReference with logCorrelationID [" +logCorrelationIDString+"]"); ioe.initCause(e); if (log.isDebugEnabled()) { log.debug("readObject(): Unable to deserialize the EPR with logCorrelationID [" +logCorrelationIDString+"] original error ["+e.getClass().getName() +"] message ["+e.getMessage()+"]",e); } throw ioe; } finally { // Make sure that the reader is properly closed // Note that closing a ByteArrayInputStream has no effect if (xmlReader != null) { try { xmlReader.close(); } catch (Exception e2) { IOException ioe2 = new IOException("Unable to close the XMLStreamReader for the EndpointReference with logCorrelationID [" +logCorrelationIDString+"]"); ioe2.initCause(e2); if (log.isDebugEnabled()) { log.debug("readObject(): Unable to close the XMLStreamReader for the EPR with logCorrelationID [" +logCorrelationIDString+"] original error ["+e2.getClass().getName() +"] message ["+e2.getMessage()+"]",e2); } throw ioe2; } } } } /** * Get the ID associated with this object instance. * * @return A string that can be output to a log file as an identifier * for this object instance. It is suitable for matching related log * entries. */ public String getLogCorrelationIDString() { if (logCorrelationIDString == null) { logCorrelationIDString = myClassName + "@" + UIDGenerator.generateUID(); } return logCorrelationIDString; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy