1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.ws.addressing;
  27 
  28 import com.sun.xml.internal.ws.api.server.*;
  29 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
  30 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
  31 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
  32 import com.sun.xml.internal.ws.util.xml.XMLStreamWriterFilter;
  33 import com.sun.xml.internal.org.jvnet.staxex.util.XMLStreamReaderToXMLStreamWriter;
  34 import com.sun.xml.internal.ws.server.WSEndpointImpl;
  35 import com.sun.xml.internal.ws.wsdl.parser.WSDLConstants;
  36 import com.sun.istack.internal.Nullable;
  37 import com.sun.istack.internal.NotNull;
  38 
  39 import javax.xml.stream.XMLStreamWriter;
  40 import javax.xml.stream.XMLStreamException;
  41 import javax.xml.stream.XMLStreamReader;
  42 import javax.xml.namespace.NamespaceContext;
  43 import java.io.IOException;
  44 import java.util.List;
  45 import java.util.Collection;
  46 import java.util.Collections;
  47 
  48 /**
  49  * This class acts as a filter for the Extension elements in the wsa:EndpointReference in the wsdl.
  50  * In addition to filtering the EPR extensions from WSDL, it adds the extensions configured by the JAX-WS runtime
  51  * specifc to an endpoint.
  52  *
  53  * @author Rama Pulavarthi
  54  */
  55 public class EPRSDDocumentFilter implements SDDocumentFilter {
  56     private final WSEndpointImpl<?> endpoint;
  57     //initialize lazily
  58     List<BoundEndpoint> beList;
  59     public EPRSDDocumentFilter(@NotNull WSEndpointImpl<?> endpoint) {
  60         this.endpoint = endpoint;
  61     }
  62 
  63     private @Nullable WSEndpointImpl<?> getEndpoint(String serviceName, String portName) {
  64         if (serviceName == null || portName == null)
  65             return null;
  66         if (endpoint.getServiceName().getLocalPart().equals(serviceName) && endpoint.getPortName().getLocalPart().equals(portName))
  67             return endpoint;
  68 
  69         if(beList == null) {
  70             //check if it is run in a Java EE Container and get hold of other endpoints in the application
  71             Module module = endpoint.getContainer().getSPI(Module.class);
  72             if (module != null) {
  73                 beList = module.getBoundEndpoints();
  74             } else {
  75                 beList = Collections.<BoundEndpoint>emptyList();
  76             }
  77         }
  78 
  79         for (BoundEndpoint be : beList) {
  80             WSEndpoint wse = be.getEndpoint();
  81             if (wse.getServiceName().getLocalPart().equals(serviceName) && wse.getPortName().getLocalPart().equals(portName)) {
  82                 return (WSEndpointImpl) wse;
  83             }
  84         }
  85 
  86         return null;
  87 
  88     }
  89 
  90     public XMLStreamWriter filter(SDDocument doc, XMLStreamWriter w) throws XMLStreamException, IOException {
  91         if (!doc.isWSDL()) {
  92             return w;
  93         }
  94 
  95         return new XMLStreamWriterFilter(w) {
  96             private boolean eprExtnFilterON = false; //when true, all writer events are filtered out
  97 
  98             private boolean portHasEPR = false;
  99             private int eprDepth = -1; // -1 -> outside wsa:epr, 0 -> on wsa:epr start/end , > 0 inside wsa:epr
 100 
 101             private String serviceName = null; //non null when inside wsdl:service scope
 102             private boolean onService = false; //flag to get service name when on wsdl:service element start
 103             private int serviceDepth = -1;  // -1 -> outside wsdl:service, 0 -> on wsdl:service start/end , > 0 inside wsdl:service
 104 
 105             private String portName = null; //non null when inside wsdl:port scope
 106             private boolean onPort = false; //flag to get port name when on wsdl:port element start
 107             private int portDepth = -1; // -1 -> outside wsdl:port, 0 -> on wsdl:port start/end , > 0 inside wsdl:port
 108 
 109             private String portAddress; // when a complete epr is written, endpoint address is used as epr address
 110             private boolean onPortAddress = false; //flag to get endpoint address when on soap:address element start
 111 
 112             private void handleStartElement(String localName, String namespaceURI) throws XMLStreamException {
 113                 resetOnElementFlags();
 114                 if (serviceDepth >= 0) {
 115                     serviceDepth++;
 116                 }
 117                 if (portDepth >= 0) {
 118                     portDepth++;
 119                 }
 120                 if (eprDepth >= 0) {
 121                     eprDepth++;
 122                 }
 123 
 124                 if (namespaceURI.equals(WSDLConstants.QNAME_SERVICE.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_SERVICE.getLocalPart())) {
 125                     onService = true;
 126                     serviceDepth = 0;
 127                 } else if (namespaceURI.equals(WSDLConstants.QNAME_PORT.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_PORT.getLocalPart())) {
 128                     if (serviceDepth >= 1) {
 129                         onPort = true;
 130                         portDepth = 0;
 131                     }
 132                 } else if (namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME) && localName.equals("EndpointReference")) {
 133                     if (serviceDepth >= 1 && portDepth >= 1) {
 134                         portHasEPR = true;
 135                         eprDepth = 0;
 136                     }
 137                 } else if ((namespaceURI.equals(WSDLConstants.NS_SOAP_BINDING_ADDRESS.getNamespaceURI()) || namespaceURI.equals(WSDLConstants.NS_SOAP12_BINDING_ADDRESS.getNamespaceURI()))
 138                         &&  localName.equals("address") && portDepth ==1) {
 139                     onPortAddress = true;
 140                 }
 141                 WSEndpoint endpoint = getEndpoint(serviceName,portName);
 142                 //filter epr for only for the port corresponding to this endpoint
 143                 //if (service.getLocalPart().equals(serviceName) && port.getLocalPart().equals(portName)) {
 144                 if ( endpoint != null) {
 145                     if ((eprDepth == 1) && !namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME)) {
 146                         //epr extension element
 147                         eprExtnFilterON = true;
 148 
 149                     }
 150 
 151                     /*
 152                     if (eprExtnFilterON) {
 153                         writeEPRExtensions();
 154                     }
 155                     */
 156                 }
 157             }
 158 
 159             private void resetOnElementFlags() {
 160                 if (onService) {
 161                     onService = false;
 162                 }
 163                 if (onPort) {
 164                     onPort = false;
 165                 }
 166                 if (onPortAddress) {
 167                     onPortAddress = false;
 168                 }
 169 
 170             }
 171 
 172 
 173             private void writeEPRExtensions(Collection<WSEndpointReference.EPRExtension> eprExtns) throws XMLStreamException {
 174                if (eprExtns != null) {
 175                         for (WSEndpointReference.EPRExtension e : eprExtns) {
 176                             XMLStreamReaderToXMLStreamWriter c = new XMLStreamReaderToXMLStreamWriter();
 177                             XMLStreamReader r = e.readAsXMLStreamReader();
 178                             c.bridge(r, writer);
 179                             XMLStreamReaderFactory.recycle(r);
 180                         }
 181                     }
 182             }
 183 
 184             @Override
 185             public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
 186                 handleStartElement(localName, namespaceURI);
 187                 if (!eprExtnFilterON) {
 188                     super.writeStartElement(prefix, localName, namespaceURI);
 189                 }
 190             }
 191 
 192             @Override
 193             public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
 194                 handleStartElement(localName, namespaceURI);
 195                 if (!eprExtnFilterON) {
 196                     super.writeStartElement(namespaceURI, localName);
 197                 }
 198             }
 199 
 200             @Override
 201             public void writeStartElement(String localName) throws XMLStreamException {
 202                 if (!eprExtnFilterON) {
 203                     super.writeStartElement(localName);
 204                 }
 205             }
 206 
 207             private void handleEndElement() throws XMLStreamException {
 208                 resetOnElementFlags();
 209                 //End of wsdl:port, write complete EPR if not present.
 210                 if (portDepth == 0) {
 211 
 212                     if (!portHasEPR && getEndpoint(serviceName,portName) != null) {
 213 
 214                         //write the complete EPR with address.
 215                         writer.writeStartElement(AddressingVersion.W3C.getPrefix(),"EndpointReference", AddressingVersion.W3C.nsUri );
 216                         writer.writeNamespace(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.nsUri);
 217                         writer.writeStartElement(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.eprType.address, AddressingVersion.W3C.nsUri);
 218                         writer.writeCharacters(portAddress);
 219                         writer.writeEndElement();
 220                         writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions());
 221                         writer.writeEndElement();
 222 
 223                     }
 224                 }
 225                 //End of wsa:EndpointReference, write EPR extension elements
 226                 if (eprDepth == 0) {
 227                     if (portHasEPR && getEndpoint(serviceName,portName) != null) {
 228                         writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions());
 229                     }
 230                     eprExtnFilterON = false;
 231                 }
 232 
 233                 if(serviceDepth >= 0 )  {
 234                     serviceDepth--;
 235                 }
 236                 if(portDepth >= 0) {
 237                     portDepth--;
 238                 }
 239                 if(eprDepth >=0) {
 240                     eprDepth--;
 241                 }
 242 
 243                 if (serviceDepth == -1) {
 244                     serviceName = null;
 245                 }
 246                 if (portDepth == -1) {
 247                     portHasEPR = false;
 248                     portAddress = null;
 249                     portName = null;
 250                 }
 251             }
 252 
 253             @Override
 254             public void writeEndElement() throws XMLStreamException {
 255                 handleEndElement();
 256                 if (!eprExtnFilterON) {
 257                     super.writeEndElement();
 258                 }
 259             }
 260 
 261             private void handleAttribute(String localName, String value) {
 262                 if (localName.equals("name")) {
 263                     if (onService) {
 264                         serviceName = value;
 265                         onService = false;
 266                     } else if (onPort) {
 267                         portName = value;
 268                         onPort = false;
 269                     }
 270                 }
 271                 if (localName.equals("location") && onPortAddress) {
 272                     portAddress = value;
 273                 }
 274 
 275 
 276             }
 277 
 278             @Override
 279             public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
 280                 handleAttribute(localName, value);
 281                 if (!eprExtnFilterON) {
 282                     super.writeAttribute(prefix, namespaceURI, localName, value);
 283                 }
 284             }
 285 
 286             @Override
 287             public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
 288                 handleAttribute(localName, value);
 289                 if (!eprExtnFilterON) {
 290                     super.writeAttribute(namespaceURI, localName, value);
 291                 }
 292             }
 293 
 294             @Override
 295             public void writeAttribute(String localName, String value) throws XMLStreamException {
 296                 handleAttribute(localName, value);
 297                 if (!eprExtnFilterON) {
 298                     super.writeAttribute(localName, value);
 299                 }
 300             }
 301 
 302 
 303             @Override
 304             public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
 305                 if (!eprExtnFilterON) {
 306                     super.writeEmptyElement(namespaceURI, localName);
 307                 }
 308             }
 309 
 310             @Override
 311             public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
 312                 if (!eprExtnFilterON) {
 313                     super.writeNamespace(prefix, namespaceURI);
 314                 }
 315             }
 316 
 317             @Override
 318             public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
 319                 if (!eprExtnFilterON) {
 320                     super.setNamespaceContext(context);
 321                 }
 322             }
 323 
 324             @Override
 325             public void setDefaultNamespace(String uri) throws XMLStreamException {
 326                 if (!eprExtnFilterON) {
 327                     super.setDefaultNamespace(uri);
 328                 }
 329             }
 330 
 331             @Override
 332             public void setPrefix(String prefix, String uri) throws XMLStreamException {
 333                 if (!eprExtnFilterON) {
 334                     super.setPrefix(prefix, uri);
 335                 }
 336             }
 337 
 338             @Override
 339             public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
 340                 if (!eprExtnFilterON) {
 341                     super.writeProcessingInstruction(target, data);
 342                 }
 343             }
 344 
 345             @Override
 346             public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
 347                 if (!eprExtnFilterON) {
 348                     super.writeEmptyElement(prefix, localName, namespaceURI);
 349                 }
 350             }
 351 
 352             @Override
 353             public void writeCData(String data) throws XMLStreamException {
 354                 if (!eprExtnFilterON) {
 355                     super.writeCData(data);
 356                 }
 357             }
 358 
 359             @Override
 360             public void writeCharacters(String text) throws XMLStreamException {
 361                 if (!eprExtnFilterON) {
 362                     super.writeCharacters(text);
 363                 }
 364             }
 365 
 366             @Override
 367             public void writeComment(String data) throws XMLStreamException {
 368                 if (!eprExtnFilterON) {
 369                     super.writeComment(data);
 370                 }
 371             }
 372 
 373             @Override
 374             public void writeDTD(String dtd) throws XMLStreamException {
 375                 if (!eprExtnFilterON) {
 376                     super.writeDTD(dtd);
 377                 }
 378             }
 379 
 380             @Override
 381             public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
 382                 if (!eprExtnFilterON) {
 383                     super.writeDefaultNamespace(namespaceURI);
 384                 }
 385             }
 386 
 387             @Override
 388             public void writeEmptyElement(String localName) throws XMLStreamException {
 389                 if (!eprExtnFilterON) {
 390                     super.writeEmptyElement(localName);
 391                 }
 392             }
 393 
 394             @Override
 395             public void writeEntityRef(String name) throws XMLStreamException {
 396                 if (!eprExtnFilterON) {
 397                     super.writeEntityRef(name);
 398                 }
 399             }
 400 
 401             @Override
 402             public void writeProcessingInstruction(String target) throws XMLStreamException {
 403                 if (!eprExtnFilterON) {
 404                     super.writeProcessingInstruction(target);
 405                 }
 406             }
 407 
 408 
 409             @Override
 410             public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
 411                 if (!eprExtnFilterON) {
 412                     super.writeCharacters(text, start, len);
 413                 }
 414             }
 415 
 416         };
 417 
 418     }
 419 
 420 }