1 /*
   2  * Copyright (c) 1997, 2010, 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.ws.util.xml.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.ArrayList;
  47 import java.util.Collections;
  48 
  49 /**
  50  * This class acts as a filter for the Extension elements in the wsa:EndpointReference in the wsdl.
  51  * In addition to filtering the EPR extensions from WSDL, it adds the extensions configured by the JAX-WS runtime
  52  * specifc to an endpoint.
  53  *
  54  * @author Rama Pulavarthi
  55  */
  56 public class EPRSDDocumentFilter implements SDDocumentFilter {
  57     private final WSEndpointImpl<?> endpoint;
  58     //initialize lazily
  59     List<BoundEndpoint> beList;
  60     public EPRSDDocumentFilter(@NotNull WSEndpointImpl<?> endpoint) {
  61         this.endpoint = endpoint;
  62     }
  63 
  64     private @Nullable WSEndpointImpl<?> getEndpoint(String serviceName, String portName) {
  65         if (serviceName == null || portName == null)
  66             return null;
  67         if (endpoint.getServiceName().getLocalPart().equals(serviceName) && endpoint.getPortName().getLocalPart().equals(portName))
  68             return endpoint;
  69 
  70         if(beList == null) {
  71             //check if it is run in a Java EE Container and get hold of other endpoints in the application
  72             Module module = endpoint.getContainer().getSPI(Module.class);
  73             if (module != null) {
  74                 beList = module.getBoundEndpoints();
  75             } else {
  76                 beList = Collections.<BoundEndpoint>emptyList();
  77             }
  78         }
  79 
  80         for (BoundEndpoint be : beList) {
  81             WSEndpoint wse = be.getEndpoint();
  82             if (wse.getServiceName().getLocalPart().equals(serviceName) && wse.getPortName().getLocalPart().equals(portName)) {
  83                 return (WSEndpointImpl) wse;
  84             }
  85         }
  86 
  87         return null;
  88 
  89     }
  90 
  91     public XMLStreamWriter filter(SDDocument doc, XMLStreamWriter w) throws XMLStreamException, IOException {
  92         if (!doc.isWSDL()) {
  93             return w;
  94         }
  95 
  96         return new XMLStreamWriterFilter(w) {
  97             private boolean eprExtnFilterON = false; //when true, all writer events are filtered out
  98 
  99             private boolean portHasEPR = false;
 100             private int eprDepth = -1; // -1 -> outside wsa:epr, 0 -> on wsa:epr start/end , > 0 inside wsa:epr
 101 
 102             private String serviceName = null; //non null when inside wsdl:service scope
 103             private boolean onService = false; //flag to get service name when on wsdl:service element start
 104             private int serviceDepth = -1;  // -1 -> outside wsdl:service, 0 -> on wsdl:service start/end , > 0 inside wsdl:service
 105 
 106             private String portName = null; //non null when inside wsdl:port scope
 107             private boolean onPort = false; //flag to get port name when on wsdl:port element start
 108             private int portDepth = -1; // -1 -> outside wsdl:port, 0 -> on wsdl:port start/end , > 0 inside wsdl:port
 109 
 110             private String portAddress; // when a complete epr is written, endpoint address is used as epr address
 111             private boolean onPortAddress = false; //flag to get endpoint address when on soap:address element start
 112 
 113             private void handleStartElement(String localName, String namespaceURI) throws XMLStreamException {
 114                 resetOnElementFlags();
 115                 if (serviceDepth >= 0) {
 116                     serviceDepth++;
 117                 }
 118                 if (portDepth >= 0) {
 119                     portDepth++;
 120                 }
 121                 if (eprDepth >= 0) {
 122                     eprDepth++;
 123                 }
 124 
 125                 if (namespaceURI.equals(WSDLConstants.QNAME_SERVICE.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_SERVICE.getLocalPart())) {
 126                     onService = true;
 127                     serviceDepth = 0;
 128                 } else if (namespaceURI.equals(WSDLConstants.QNAME_PORT.getNamespaceURI()) && localName.equals(WSDLConstants.QNAME_PORT.getLocalPart())) {
 129                     if (serviceDepth >= 1) {
 130                         onPort = true;
 131                         portDepth = 0;
 132                     }
 133                 } else if (namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME) && localName.equals("EndpointReference")) {
 134                     if (serviceDepth >= 1 && portDepth >= 1) {
 135                         portHasEPR = true;
 136                         eprDepth = 0;
 137                     }
 138                 } else if ((namespaceURI.equals(WSDLConstants.NS_SOAP_BINDING_ADDRESS.getNamespaceURI()) || namespaceURI.equals(WSDLConstants.NS_SOAP12_BINDING_ADDRESS.getNamespaceURI()))
 139                         &&  localName.equals("address") && portDepth ==1) {
 140                     onPortAddress = true;
 141                 }
 142                 WSEndpoint endpoint = getEndpoint(serviceName,portName);
 143                 //filter epr for only for the port corresponding to this endpoint
 144                 //if (service.getLocalPart().equals(serviceName) && port.getLocalPart().equals(portName)) {
 145                 if ( endpoint != null) {
 146                     if ((eprDepth == 1) && !namespaceURI.equals(W3CAddressingConstants.WSA_NAMESPACE_NAME)) {
 147                         //epr extension element
 148                         eprExtnFilterON = true;
 149 
 150                     }
 151 
 152                     /*
 153                     if (eprExtnFilterON) {
 154                         writeEPRExtensions();
 155                     }
 156                     */
 157                 }
 158             }
 159 
 160             private void resetOnElementFlags() {
 161                 if (onService) {
 162                     onService = false;
 163                 }
 164                 if (onPort) {
 165                     onPort = false;
 166                 }
 167                 if (onPortAddress) {
 168                     onPortAddress = false;
 169                 }
 170 
 171             }
 172 
 173 
 174             private void writeEPRExtensions(Collection<WSEndpointReference.EPRExtension> eprExtns) throws XMLStreamException {
 175                if (eprExtns != null) {
 176                         for (WSEndpointReference.EPRExtension e : eprExtns) {
 177                             XMLStreamReaderToXMLStreamWriter c = new XMLStreamReaderToXMLStreamWriter();
 178                             XMLStreamReader r = e.readAsXMLStreamReader();
 179                             c.bridge(r, writer);
 180                             XMLStreamReaderFactory.recycle(r);
 181                         }
 182                     }
 183             }
 184 
 185             @Override
 186             public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
 187                 handleStartElement(localName, namespaceURI);
 188                 if (!eprExtnFilterON) {
 189                     super.writeStartElement(prefix, localName, namespaceURI);
 190                 }
 191             }
 192 
 193             @Override
 194             public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
 195                 handleStartElement(localName, namespaceURI);
 196                 if (!eprExtnFilterON) {
 197                     super.writeStartElement(namespaceURI, localName);
 198                 }
 199             }
 200 
 201             @Override
 202             public void writeStartElement(String localName) throws XMLStreamException {
 203                 if (!eprExtnFilterON) {
 204                     super.writeStartElement(localName);
 205                 }
 206             }
 207 
 208             private void handleEndElement() throws XMLStreamException {
 209                 resetOnElementFlags();
 210                 //End of wsdl:port, write complete EPR if not present.
 211                 if (portDepth == 0) {
 212 
 213                     if (!portHasEPR && getEndpoint(serviceName,portName) != null) {
 214 
 215                         //write the complete EPR with address.
 216                         writer.writeStartElement(AddressingVersion.W3C.getPrefix(),"EndpointReference", AddressingVersion.W3C.nsUri );
 217                         writer.writeNamespace(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.nsUri);
 218                         writer.writeStartElement(AddressingVersion.W3C.getPrefix(), AddressingVersion.W3C.eprType.address, AddressingVersion.W3C.nsUri);
 219                         writer.writeCharacters(portAddress);
 220                         writer.writeEndElement();
 221                         writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions());
 222                         writer.writeEndElement();
 223 
 224                     }
 225                 }
 226                 //End of wsa:EndpointReference, write EPR extension elements
 227                 if (eprDepth == 0) {
 228                     if (portHasEPR && getEndpoint(serviceName,portName) != null) {
 229                         writeEPRExtensions(getEndpoint(serviceName, portName).getEndpointReferenceExtensions());
 230                     }
 231                     eprExtnFilterON = false;
 232                 }
 233 
 234                 if(serviceDepth >= 0 )  {
 235                     serviceDepth--;
 236                 }
 237                 if(portDepth >= 0) {
 238                     portDepth--;
 239                 }
 240                 if(eprDepth >=0) {
 241                     eprDepth--;
 242                 }
 243 
 244                 if (serviceDepth == -1) {
 245                     serviceName = null;
 246                 }
 247                 if (portDepth == -1) {
 248                     portHasEPR = false;
 249                     portAddress = null;
 250                     portName = null;
 251                 }
 252             }
 253 
 254             @Override
 255             public void writeEndElement() throws XMLStreamException {
 256                 handleEndElement();
 257                 if (!eprExtnFilterON) {
 258                     super.writeEndElement();
 259                 }
 260             }
 261 
 262             private void handleAttribute(String localName, String value) {
 263                 if (localName.equals("name")) {
 264                     if (onService) {
 265                         serviceName = value;
 266                         onService = false;
 267                     } else if (onPort) {
 268                         portName = value;
 269                         onPort = false;
 270                     }
 271                 }
 272                 if (localName.equals("location") && onPortAddress) {
 273                     portAddress = value;
 274                 }
 275 
 276 
 277             }
 278 
 279             @Override
 280             public void writeAttribute(String prefix, String namespaceURI, String localName, String value) throws XMLStreamException {
 281                 handleAttribute(localName, value);
 282                 if (!eprExtnFilterON) {
 283                     super.writeAttribute(prefix, namespaceURI, localName, value);
 284                 }
 285             }
 286 
 287             @Override
 288             public void writeAttribute(String namespaceURI, String localName, String value) throws XMLStreamException {
 289                 handleAttribute(localName, value);
 290                 if (!eprExtnFilterON) {
 291                     super.writeAttribute(namespaceURI, localName, value);
 292                 }
 293             }
 294 
 295             @Override
 296             public void writeAttribute(String localName, String value) throws XMLStreamException {
 297                 handleAttribute(localName, value);
 298                 if (!eprExtnFilterON) {
 299                     super.writeAttribute(localName, value);
 300                 }
 301             }
 302 
 303 
 304             @Override
 305             public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException {
 306                 if (!eprExtnFilterON) {
 307                     super.writeEmptyElement(namespaceURI, localName);
 308                 }
 309             }
 310 
 311             @Override
 312             public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
 313                 if (!eprExtnFilterON) {
 314                     super.writeNamespace(prefix, namespaceURI);
 315                 }
 316             }
 317 
 318             @Override
 319             public void setNamespaceContext(NamespaceContext context) throws XMLStreamException {
 320                 if (!eprExtnFilterON) {
 321                     super.setNamespaceContext(context);
 322                 }
 323             }
 324 
 325             @Override
 326             public void setDefaultNamespace(String uri) throws XMLStreamException {
 327                 if (!eprExtnFilterON) {
 328                     super.setDefaultNamespace(uri);
 329                 }
 330             }
 331 
 332             @Override
 333             public void setPrefix(String prefix, String uri) throws XMLStreamException {
 334                 if (!eprExtnFilterON) {
 335                     super.setPrefix(prefix, uri);
 336                 }
 337             }
 338 
 339             @Override
 340             public void writeProcessingInstruction(String target, String data) throws XMLStreamException {
 341                 if (!eprExtnFilterON) {
 342                     super.writeProcessingInstruction(target, data);
 343                 }
 344             }
 345 
 346             @Override
 347             public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
 348                 if (!eprExtnFilterON) {
 349                     super.writeEmptyElement(prefix, localName, namespaceURI);
 350                 }
 351             }
 352 
 353             @Override
 354             public void writeCData(String data) throws XMLStreamException {
 355                 if (!eprExtnFilterON) {
 356                     super.writeCData(data);
 357                 }
 358             }
 359 
 360             @Override
 361             public void writeCharacters(String text) throws XMLStreamException {
 362                 if (!eprExtnFilterON) {
 363                     super.writeCharacters(text);
 364                 }
 365             }
 366 
 367             @Override
 368             public void writeComment(String data) throws XMLStreamException {
 369                 if (!eprExtnFilterON) {
 370                     super.writeComment(data);
 371                 }
 372             }
 373 
 374             @Override
 375             public void writeDTD(String dtd) throws XMLStreamException {
 376                 if (!eprExtnFilterON) {
 377                     super.writeDTD(dtd);
 378                 }
 379             }
 380 
 381             @Override
 382             public void writeDefaultNamespace(String namespaceURI) throws XMLStreamException {
 383                 if (!eprExtnFilterON) {
 384                     super.writeDefaultNamespace(namespaceURI);
 385                 }
 386             }
 387 
 388             @Override
 389             public void writeEmptyElement(String localName) throws XMLStreamException {
 390                 if (!eprExtnFilterON) {
 391                     super.writeEmptyElement(localName);
 392                 }
 393             }
 394 
 395             @Override
 396             public void writeEntityRef(String name) throws XMLStreamException {
 397                 if (!eprExtnFilterON) {
 398                     super.writeEntityRef(name);
 399                 }
 400             }
 401 
 402             @Override
 403             public void writeProcessingInstruction(String target) throws XMLStreamException {
 404                 if (!eprExtnFilterON) {
 405                     super.writeProcessingInstruction(target);
 406                 }
 407             }
 408 
 409 
 410             @Override
 411             public void writeCharacters(char[] text, int start, int len) throws XMLStreamException {
 412                 if (!eprExtnFilterON) {
 413                     super.writeCharacters(text, start, len);
 414                 }
 415             }
 416 
 417         };
 418 
 419     }
 420 
 421 }