/* * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.xml.internal.ws.addressing; import com.sun.xml.internal.ws.api.server.*; import com.sun.xml.internal.ws.api.addressing.WSEndpointReference; import com.sun.xml.internal.ws.api.addressing.AddressingVersion; import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; import com.sun.xml.internal.ws.util.xml.XMLStreamWriterFilter; import com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter; import com.sun.xml.internal.ws.server.WSEndpointImpl; import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants; import com.sun.istack.internal.Nullable; import com.sun.istack.internal.NotNull; import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.namespace.NamespaceContext; import java.io.IOException; import java.util.List; import java.util.Collection; import java.util.Collections; /** * This class acts as a filter for the Extension elements in the wsa:EndpointReference in the wsdl. * In addition to filtering the EPR extensions from WSDL, it adds the extensions configured by the JAX-WS runtime * specifc to an endpoint. * * @author Rama Pulavarthi */ public class EPRSDDocumentFilter implements SDDocumentFilter { private final WSEndpointImpl<?> endpoint; //initialize lazily List<BoundEndpoint> beList; public EPRSDDocumentFilter(@NotNull WSEndpointImpl<?> endpoint) { this.endpoint = endpoint; } private @Nullable WSEndpointImpl<?> getEndpoint(String serviceName, String portName) { if (serviceName == null || portName == null) return null; if (endpoint.getServiceName().getLocalPart().equals(serviceName) && endpoint.getPortName().getLocalPart().equals(portName)) return endpoint; if(beList == null) { //check if it is run in a Java EE Container and get hold of other endpoints in the application Module module = endpoint.getContainer().getSPI(Module.class); if (module != null) { beList = module.getBoundEndpoints(); } else { beList = Collections.<BoundEndpoint>emptyList(); } } for (BoundEndpoint be : beList) { WSEndpoint wse = be.getEndpoint(); if (wse.getServiceName().getLocalPart().equals(serviceName) && wse.getPortName().getLocalPart().equals(portName)) { return (WSEndpointImpl) wse; } } return null; } public XMLStreamWriter filter(SDDocument doc, XMLStreamWriter w) throws XMLStreamException, IOException { if (!doc.isWSDL()) { return w; } return new XMLStreamWriterFilter(w) { private boolean eprExtnFilterON = false; //when true, all writer events are filtered out private boolean portHasEPR = false; private int eprDepth = -1; // -1 -> outside wsa:epr, 0 -> on wsa:epr start/end , > 0 inside wsa:epr private String serviceName = null; //non null when inside wsdl:service scope private boolean onService = false; //flag to get service name when on wsdl:service element start private int serviceDepth = -1; // -1 -> outside wsdl:service, 0 -> on wsdl:service start/end , > 0 inside wsdl:service private String portName = null; //non null when inside wsdl:port scope private boolean onPort = false; //flag to get port name when on wsdl:port element start private int portDepth = -1; // -1 -> outside wsdl:port, 0 -> on wsdl:port start/end , > 0 inside wsdl:port private String portAddress; // when a complete epr is written, endpoint address is used as epr address private boolean onPortAddress = false; //flag to get endpoint address when on soap:address element start private void handleStartElement(String localName, String namespaceURI) throws XMLStreamException { resetOnElementFlags(); if (serviceDepth >= 0) { serviceDepth++; } if (portDepth >= 0) { portDepth++; } if (eprDepth >= 0) { eprDepth++; } if (namespaceURI.equals(WSDLConstants.QNAME_SERVICE.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_SERVICE.getLocalPart())) { onService = true; serviceDepth = 0; } else if (namespaceURI.equals(WSDLConstants.QNAME_PORT.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_PORT.getLocalPart())) { if (serviceDepth >= 1) { onPort = true; portDepth = 0; } } else if (namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME) && localName.equals("EndpointReference")) { if (serviceDepth >= 1 && portDepth >= 1) { portHasEPR = true; eprDepth = 0; } } else if ((namespaceURI.equals(WSDLConstants.NS_SOAP_BINDING_ADDRESS.getNamespaceURI()) || namespaceURI.equals(WSDLConstants.NS_SOAP12_BINDING_ADDRESS.getNamespaceURI())) && localName.equals("address") && portDepth ==1) { onPortAddress = true; } WSEndpoint endpoint = getEndpoint(serviceName,portName); //filter epr for only for the port corresponding to this endpoint //if (service.getLocalPart().equals(serviceName) && port.getLocalPart().equals(portName)) { if ( endpoint != null) { if ((eprDepth == 1) && !namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME)) { //epr extension element eprExtnFilterON = true; } /* if (eprExtnFilterON) { writeEPRExtensions(); } */ } } private void resetOnElementFlags() { if (onService) { onService = false; } if (onPort) { onPort = false; } if (onPortAddress) { onPortAddress = false; } } private void writeEPRExtensions(Collection<WSEndpointReference.EPRExtension> eprExtns) throws XMLStreamException { if (eprExtns != null) { for (WSEndpointReference.EPRExtension e : eprExtns) { XMLStreamReaderToXMLStreamWriter c = new XMLStreamReaderToXMLStreamWriter(); XMLStreamReader r = e.readAsXMLStreamReader(); c.bridge(r, writer); XMLStreamReaderFactory.recycle(r); } } } @Override public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { handleStartElement(localName, namespaceURI); if (!eprExtnFilterON) { super.writeStartElement(prefix, localName, namespaceURI); } } @Override public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException { handleStartElement(localName, namespaceURI); if (!eprExtnFilterON) { super.writeStartElement(namespaceURI, localName); } } @Override public void writeStartElement(String localName) throws XMLStreamException { if (!eprExtnFilterON) { super.writeStartElement(localName); } } private void handleEndElement() throws XMLStreamException { resetOnElementFlags(); //End of wsdl:port, write complete EPR if not present. if (portDepth == 0) { if (!portHasEPR && getEndpoint(serviceName,portName) != null) { //write the complete EPR with address. writer.writeStartElement(AddressingVersion.W3C.getPrefix(),"EndpointReference", AddressingVersion.W3C.nsUri ); writer.writeNamespace(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.nsUri); writer.writeStartElement(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.eprType.address, AddressingVersion.W3C.nsUri); writer.writeCharacters(portAddress); writer.writeEndElement(); writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions()); writer.writeEndElement(); } } //End of wsa:EndpointReference, write EPR extension elements if (eprDepth == 0) { if (portHasEPR && getEndpoint(serviceName,portName) != null) { writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions()); } eprExtnFilterON = false; } if(serviceDepth >= 0 ) { serviceDepth--; } if(portDepth >= 0) { portDepth--; } if(eprDepth >=0) { eprDepth--; } if (serviceDepth == -1) { serviceName = null; } if (portDepth == -1) { portHasEPR = false; portAddress = null; portName = null; } } @Override public void writeEndElement() throws XMLStreamException { handleEndElement(); if (!eprExtnFilterON) { super.writeEndElement(); } } private void handleAttribute(String localName, String value) { if (localName.equals("name")) { if (onService) { serviceName = value; onService = false; } else if (onPort) { portName = value; onPort = false; } } if (localName.equals("location") && onPortAddress) { portAddress = value; } } @Override public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException { handleAttribute(localName, value); if (!eprExtnFilterON) { super.writeAttribute(prefix, namespaceURI, localName, value); } } @Override public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException { handleAttribute(localName, value); if (!eprExtnFilterON) { super.writeAttribute(namespaceURI, localName, value); } } @Override public void writeAttribute(String localName, String value) throws XMLStreamException { handleAttribute(localName, value); if (!eprExtnFilterON) { super.writeAttribute(localName, value); } } @Override public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException { if (!eprExtnFilterON) { super.writeEmptyElement(namespaceURI, localName); } } @Override public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException { if (!eprExtnFilterON) { super.writeNamespace(prefix, namespaceURI); } } @Override public void setNamespaceContext(NamespaceContext context) throws XMLStreamException { if (!eprExtnFilterON) { super.setNamespaceContext(context); } } @Override public void setDefaultNamespace(String uri) throws XMLStreamException { if (!eprExtnFilterON) { super.setDefaultNamespace(uri); } } @Override public void setPrefix(String prefix, String uri) throws XMLStreamException { if (!eprExtnFilterON) { super.setPrefix(prefix, uri); } } @Override public void writeProcessingInstruction(String target, String data) throws XMLStreamException { if (!eprExtnFilterON) { super.writeProcessingInstruction(target, data); } } @Override public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { if (!eprExtnFilterON) { super.writeEmptyElement(prefix, localName, namespaceURI); } } @Override public void writeCData(String data) throws XMLStreamException { if (!eprExtnFilterON) { super.writeCData(data); } } @Override public void writeCharacters(String text) throws XMLStreamException { if (!eprExtnFilterON) { super.writeCharacters(text); } } @Override public void writeComment(String data) throws XMLStreamException { if (!eprExtnFilterON) { super.writeComment(data); } } @Override public void writeDTD(String dtd) throws XMLStreamException { if (!eprExtnFilterON) { super.writeDTD(dtd); } } @Override public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException { if (!eprExtnFilterON) { super.writeDefaultNamespace(namespaceURI); } } @Override public void writeEmptyElement(String localName) throws XMLStreamException { if (!eprExtnFilterON) { super.writeEmptyElement(localName); } } @Override public void writeEntityRef(String name) throws XMLStreamException { if (!eprExtnFilterON) { super.writeEntityRef(name); } } @Override public void writeProcessingInstruction(String target) throws XMLStreamException { if (!eprExtnFilterON) { super.writeProcessingInstruction(target); } } @Override public void writeCharacters(char[] text, int start, int len) throws XMLStreamException { if (!eprExtnFilterON) { super.writeCharacters(text, start, len); } } }; } }