1 /*
   2  * Copyright (c) 2013, 2017, 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.messaging.saaj.util.stax;
  27 
  28 import javax.xml.namespace.NamespaceContext;
  29 import javax.xml.namespace.QName;
  30 import javax.xml.soap.SOAPException;
  31 import javax.xml.stream.Location;
  32 import javax.xml.stream.XMLStreamException;
  33 import javax.xml.stream.XMLStreamReader;
  34 
  35 import org.w3c.dom.Node;
  36 
  37 import com.sun.xml.internal.messaging.saaj.soap.impl.BodyImpl;
  38 import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl;
  39 
  40 /**
  41  * "Hybrid" reader which
  42  * @author desagar
  43  *
  44  */
  45 public class LazyEnvelopeStaxReader extends com.sun.xml.internal.org.jvnet.staxex.util.DOMStreamReader {
  46 //    EnvelopeImpl env;
  47     XMLStreamReader payloadReader = null;
  48     boolean usePayloadReaderDelegate = false;
  49     private QName bodyQName;
  50 
  51     public LazyEnvelopeStaxReader(EnvelopeImpl env) throws SOAPException, XMLStreamException {
  52         super(env);
  53 //        this.env = env;
  54         bodyQName = new QName(env.getNamespaceURI(), "Body");
  55         payloadReader = env.getStaxBridge().getPayloadReader();
  56         int eventType = getEventType();
  57         while (eventType != START_ELEMENT) {
  58             eventType = nextTag();
  59         }
  60     }
  61 
  62     @Override
  63     public Object getProperty(String name) throws IllegalArgumentException {
  64         if (usePayloadReaderDelegate) return payloadReader.getProperty(name);
  65         return super.getProperty(name);
  66     }
  67 
  68     @Override
  69     public int next() throws XMLStreamException {
  70 //        boolean previouslyUsingPayloadReader = usePayloadReaderDelegate;
  71         //call checkReaderStatus to advance to payloadReader if needed
  72         checkReaderStatus(true);
  73 
  74         if (usePayloadReaderDelegate) return payloadReader.getEventType();
  75 
  76         //if we just moved to payload reader, don't advance the pointer
  77 //        if (usePayloadReaderDelegate && !previouslyUsingPayloadReader) return payloadReader.getEventType();
  78 
  79 //        if (usePayloadReaderDelegate) return payloadReader.next();
  80         return getEventType();
  81     }
  82 
  83     @Override
  84     public void require(int type, String namespaceURI, String localName)
  85             throws XMLStreamException {
  86         if (usePayloadReaderDelegate) payloadReader.require(type, namespaceURI, localName);
  87         else super.require(type, namespaceURI, localName);
  88     }
  89 
  90     @Override
  91     public String getElementText() throws XMLStreamException {
  92         if (usePayloadReaderDelegate) return payloadReader.getElementText();
  93         return super.getElementText();
  94     }
  95 
  96     @Override
  97     public int nextTag() throws XMLStreamException {
  98         if (usePayloadReaderDelegate) return payloadReader.nextTag();
  99         return super.nextTag();
 100     }
 101 
 102     @Override
 103     public boolean hasNext() throws XMLStreamException {
 104         checkReaderStatus(false);
 105         boolean hasNext;
 106         if (usePayloadReaderDelegate) {
 107             hasNext = payloadReader.hasNext();
 108         } else {
 109             hasNext = super.hasNext();
 110         }
 111 
 112         /*if (!hasNext && payloadReader != null) {
 113             usePayloadReaderDelegate = true;
 114             hasNext = payloadReader.hasNext();
 115         }*/
 116         return hasNext;
 117     }
 118 
 119     private void checkReaderStatus(boolean advanceToNext) throws XMLStreamException {
 120         //if we are using payloadReader, make sure it is not exhausted
 121         //if it is, return to DOM based reader for remaining end elements (body and envelope)
 122         if (usePayloadReaderDelegate) {
 123             if (!payloadReader.hasNext()) {
 124                 usePayloadReaderDelegate = false;
 125             }
 126         } else if (START_ELEMENT == getEventType()) {
 127             //if not on payload reader, check if we need to switch to payload reader
 128 
 129             //if the current event is the SOAP body element start,
 130             //and the body is lazy, switch to the payload reader
 131             if (bodyQName.equals(getName())) {
 132                 //if we are just switching to payload reader, don't advance...payload reader
 133                 //will already be on the first payload element
 134                 usePayloadReaderDelegate = true;
 135                 advanceToNext = false;
 136             }
 137         }
 138 
 139         if (advanceToNext) {
 140             if (usePayloadReaderDelegate) {
 141                 payloadReader.next();
 142             } else {
 143                 super.next();
 144             }
 145         }
 146     }
 147 
 148     @Override
 149     public void close() throws XMLStreamException {
 150         if (usePayloadReaderDelegate) payloadReader.close();
 151         else super.close();
 152     }
 153 
 154     @Override
 155     public String getNamespaceURI(String prefix) {
 156         if (usePayloadReaderDelegate) return payloadReader.getNamespaceURI(prefix);
 157         return super.getNamespaceURI(prefix);
 158     }
 159 
 160     @Override
 161     public boolean isStartElement() {
 162         if (usePayloadReaderDelegate) return payloadReader.isStartElement();
 163         return super.isStartElement();
 164     }
 165 
 166     @Override
 167     public boolean isEndElement() {
 168         if (usePayloadReaderDelegate) return payloadReader.isEndElement();
 169         return super.isEndElement();
 170     }
 171 
 172     @Override
 173     public boolean isCharacters() {
 174         if (usePayloadReaderDelegate) return payloadReader.isCharacters();
 175         return super.isEndElement();
 176     }
 177 
 178     @Override
 179     public boolean isWhiteSpace() {
 180         if (usePayloadReaderDelegate) return payloadReader.isWhiteSpace();
 181         return super.isWhiteSpace();
 182     }
 183 
 184     @Override
 185     public String getAttributeValue(String namespaceURI, String localName) {
 186         if (usePayloadReaderDelegate) return payloadReader.getAttributeValue(namespaceURI, localName);
 187         return super.getAttributeValue(namespaceURI, localName);
 188     }
 189 
 190     @Override
 191     public int getAttributeCount() {
 192         if (usePayloadReaderDelegate) return payloadReader.getAttributeCount();
 193         return super.getAttributeCount();
 194     }
 195 
 196     @Override
 197     public QName getAttributeName(int index) {
 198         if (usePayloadReaderDelegate) return payloadReader.getAttributeName(index);
 199         return super.getAttributeName(index);
 200     }
 201 
 202     @Override
 203     public String getAttributeNamespace(int index) {
 204         if (usePayloadReaderDelegate) return payloadReader.getAttributeNamespace(index);
 205         return super.getAttributeNamespace(index);
 206     }
 207 
 208     @Override
 209     public String getAttributeLocalName(int index) {
 210         if (usePayloadReaderDelegate) return payloadReader.getAttributeLocalName(index);
 211         return super.getAttributeLocalName(index);
 212     }
 213 
 214     @Override
 215     public String getAttributePrefix(int index) {
 216         if (usePayloadReaderDelegate) return payloadReader.getAttributePrefix(index);
 217         return super.getAttributePrefix(index);
 218     }
 219 
 220     @Override
 221     public String getAttributeType(int index) {
 222         if (usePayloadReaderDelegate) return payloadReader.getAttributeType(index);
 223         return super.getAttributeType(index);
 224     }
 225 
 226     @Override
 227     public String getAttributeValue(int index) {
 228         if (usePayloadReaderDelegate) return payloadReader.getAttributeValue(index);
 229         return super.getAttributeValue(index);
 230     }
 231 
 232     @Override
 233     public boolean isAttributeSpecified(int index) {
 234         if (usePayloadReaderDelegate) return payloadReader.isAttributeSpecified(index);
 235         return super.isAttributeSpecified(index);
 236     }
 237 
 238     @Override
 239     public int getNamespaceCount() {
 240         if (usePayloadReaderDelegate) return payloadReader.getNamespaceCount();
 241         return super.getNamespaceCount();
 242     }
 243 
 244     @Override
 245     public String getNamespacePrefix(int index) {
 246         if (usePayloadReaderDelegate) return payloadReader.getNamespacePrefix(index);
 247         return super.getNamespacePrefix(index);
 248     }
 249 
 250     @Override
 251     public String getNamespaceURI(int index) {
 252         if (usePayloadReaderDelegate) return payloadReader.getNamespaceURI(index);
 253         return super.getNamespaceURI(index);
 254     }
 255 
 256     @Override
 257     public NamespaceContext getNamespaceContext() {
 258         if (usePayloadReaderDelegate) return payloadReader.getNamespaceContext();
 259         return super.getNamespaceContext();
 260     }
 261 
 262     @Override
 263     public int getEventType() {
 264         if (usePayloadReaderDelegate) return payloadReader.getEventType();
 265         return super.getEventType();
 266     }
 267 
 268     @Override
 269     public String getText() {
 270         if (usePayloadReaderDelegate) return payloadReader.getText();
 271         return super.getText();
 272     }
 273 
 274     @Override
 275     public char[] getTextCharacters() {
 276         if (usePayloadReaderDelegate) return payloadReader.getTextCharacters();
 277         return super.getTextCharacters();
 278     }
 279 
 280     @Override
 281     public int getTextCharacters(int sourceStart, char[] target,
 282             int targetStart, int length) throws XMLStreamException {
 283         if (usePayloadReaderDelegate) return payloadReader.getTextCharacters(sourceStart, target, targetStart,
 284                 length);
 285         return super.getTextCharacters(sourceStart, target, targetStart, length);
 286     }
 287 
 288     @Override
 289     public int getTextStart() {
 290         if (usePayloadReaderDelegate) return payloadReader.getTextStart();
 291         return super.getTextStart();
 292     }
 293 
 294     @Override
 295     public int getTextLength() {
 296         if (usePayloadReaderDelegate) return payloadReader.getTextLength();
 297         return super.getTextLength();
 298     }
 299 
 300     @Override
 301     public String getEncoding() {
 302         if (usePayloadReaderDelegate) return payloadReader.getEncoding();
 303         return super.getEncoding();
 304     }
 305 
 306     @Override
 307     public boolean hasText() {
 308         if (usePayloadReaderDelegate) return payloadReader.hasText();
 309         return super.hasText();
 310     }
 311 
 312     @Override
 313     public Location getLocation() {
 314         if (usePayloadReaderDelegate) return payloadReader.getLocation();
 315         return super.getLocation();
 316     }
 317 
 318     @Override
 319     public QName getName() {
 320         if (usePayloadReaderDelegate) return payloadReader.getName();
 321         return super.getName();
 322     }
 323 
 324     @Override
 325     public String getLocalName() {
 326         if (usePayloadReaderDelegate) return payloadReader.getLocalName();
 327         return super.getLocalName();
 328     }
 329 
 330     @Override
 331     public boolean hasName() {
 332         if (usePayloadReaderDelegate) return payloadReader.hasName();
 333         return super.hasName();
 334     }
 335 
 336     @Override
 337     public String getNamespaceURI() {
 338         if (usePayloadReaderDelegate) return payloadReader.getNamespaceURI();
 339         return super.getNamespaceURI();
 340     }
 341 
 342     @Override
 343     public String getPrefix() {
 344         if (usePayloadReaderDelegate) return payloadReader.getPrefix();
 345         return super.getPrefix();
 346     }
 347 
 348     @Override
 349     public String getVersion() {
 350         if (usePayloadReaderDelegate) return payloadReader.getVersion();
 351         return super.getVersion();
 352     }
 353 
 354     @Override
 355     public boolean isStandalone() {
 356         if (usePayloadReaderDelegate) return payloadReader.isStandalone();
 357         return super.isStandalone();
 358     }
 359 
 360     @Override
 361     public boolean standaloneSet() {
 362         if (usePayloadReaderDelegate) return payloadReader.standaloneSet();
 363         return super.standaloneSet();
 364     }
 365 
 366     @Override
 367     public String getCharacterEncodingScheme() {
 368         if (usePayloadReaderDelegate) return payloadReader.getCharacterEncodingScheme();
 369         return super.getCharacterEncodingScheme();
 370     }
 371 
 372     @Override
 373     public String getPITarget() {
 374         if (usePayloadReaderDelegate) return payloadReader.getPITarget();
 375         return super.getPITarget();
 376     }
 377 
 378     @Override
 379     public String getPIData() {
 380         if (usePayloadReaderDelegate) return payloadReader.getPIData();
 381         return super.getPIData();
 382     }
 383 
 384     //make sure that message is not realized as a result of call
 385     //to getFirstChild
 386     protected Node getFirstChild(Node node) {
 387         if (node instanceof BodyImpl) {
 388             return ((BodyImpl) node).getFirstChildNoMaterialize();
 389         } else {
 390             return node.getFirstChild();
 391         }
 392     }
 393 
 394     protected Node getNextSibling(Node node) {
 395         if (node instanceof BodyImpl) {
 396             //body is not expected to have a next sibling - even if it does
 397             //we would have to materialize the node to retrieve it.
 398             //Since we don't want to materialize it right now, just return null
 399             return null;
 400         }
 401         return node.getNextSibling();
 402     }
 403 
 404 }