1 /*
   2  * Copyright (c) 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.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     public Object getProperty(String name) throws IllegalArgumentException {
  63         if (usePayloadReaderDelegate) return payloadReader.getProperty(name);
  64         return super.getProperty(name);
  65     }
  66 
  67     public int next() throws XMLStreamException {
  68 //        boolean previouslyUsingPayloadReader = usePayloadReaderDelegate;
  69         //call checkReaderStatus to advance to payloadReader if needed
  70         checkReaderStatus(true);
  71 
  72         if (usePayloadReaderDelegate) return payloadReader.getEventType();
  73 
  74         //if we just moved to payload reader, don't advance the pointer
  75 //        if (usePayloadReaderDelegate && !previouslyUsingPayloadReader) return payloadReader.getEventType();
  76 
  77 //        if (usePayloadReaderDelegate) return payloadReader.next();
  78         return getEventType();
  79     }
  80 
  81     public void require(int type, String namespaceURI, String localName)
  82             throws XMLStreamException {
  83         if (usePayloadReaderDelegate) payloadReader.require(type, namespaceURI, localName);
  84         else super.require(type, namespaceURI, localName);
  85     }
  86 
  87     public String getElementText() throws XMLStreamException {
  88         if (usePayloadReaderDelegate) return payloadReader.getElementText();
  89         return super.getElementText();
  90     }
  91 
  92     public int nextTag() throws XMLStreamException {
  93         if (usePayloadReaderDelegate) return payloadReader.nextTag();
  94         return super.nextTag();
  95     }
  96 
  97     public boolean hasNext() throws XMLStreamException {
  98         checkReaderStatus(false);
  99         boolean hasNext;
 100         if (usePayloadReaderDelegate) {
 101             hasNext = payloadReader.hasNext();
 102         } else {
 103             hasNext = super.hasNext();
 104         }
 105 
 106         /*if (!hasNext && payloadReader != null) {
 107             usePayloadReaderDelegate = true;
 108             hasNext = payloadReader.hasNext();
 109         }*/
 110         return hasNext;
 111     }
 112 
 113     private void checkReaderStatus(boolean advanceToNext) throws XMLStreamException {
 114         //if we are using payloadReader, make sure it is not exhausted
 115         //if it is, return to DOM based reader for remaining end elements (body and envelope)
 116         if (usePayloadReaderDelegate) {
 117             if (!payloadReader.hasNext()) {
 118                 usePayloadReaderDelegate = false;
 119             }
 120         } else if (START_ELEMENT == getEventType()) {
 121             //if not on payload reader, check if we need to switch to payload reader
 122 
 123             //if the current event is the SOAP body element start,
 124             //and the body is lazy, switch to the payload reader
 125             if (bodyQName.equals(getName())) {
 126                 //if we are just switching to payload reader, don't advance...payload reader
 127                 //will already be on the first payload element
 128                 usePayloadReaderDelegate = true;
 129                 advanceToNext = false;
 130             }
 131         }
 132 
 133         if (advanceToNext) {
 134             if (usePayloadReaderDelegate) {
 135                 payloadReader.next();
 136             } else {
 137                 super.next();
 138             }
 139         }
 140     }
 141 
 142     public void close() throws XMLStreamException {
 143         if (usePayloadReaderDelegate) payloadReader.close();
 144         else super.close();
 145     }
 146 
 147     public String getNamespaceURI(String prefix) {
 148         if (usePayloadReaderDelegate) return payloadReader.getNamespaceURI(prefix);
 149         return super.getNamespaceURI(prefix);
 150     }
 151 
 152     public boolean isStartElement() {
 153         if (usePayloadReaderDelegate) return payloadReader.isStartElement();
 154         return super.isStartElement();
 155     }
 156 
 157     public boolean isEndElement() {
 158         if (usePayloadReaderDelegate) return payloadReader.isEndElement();
 159         return super.isEndElement();
 160     }
 161 
 162     public boolean isCharacters() {
 163         if (usePayloadReaderDelegate) return payloadReader.isCharacters();
 164         return super.isEndElement();
 165     }
 166 
 167     public boolean isWhiteSpace() {
 168         if (usePayloadReaderDelegate) return payloadReader.isWhiteSpace();
 169         return super.isWhiteSpace();
 170     }
 171 
 172     public String getAttributeValue(String namespaceURI, String localName) {
 173         if (usePayloadReaderDelegate) return payloadReader.getAttributeValue(namespaceURI, localName);
 174         return super.getAttributeValue(namespaceURI, localName);
 175     }
 176 
 177     public int getAttributeCount() {
 178         if (usePayloadReaderDelegate) return payloadReader.getAttributeCount();
 179         return super.getAttributeCount();
 180     }
 181 
 182     public QName getAttributeName(int index) {
 183         if (usePayloadReaderDelegate) return payloadReader.getAttributeName(index);
 184         return super.getAttributeName(index);
 185     }
 186 
 187     public String getAttributeNamespace(int index) {
 188         if (usePayloadReaderDelegate) return payloadReader.getAttributeNamespace(index);
 189         return super.getAttributeNamespace(index);
 190     }
 191 
 192     public String getAttributeLocalName(int index) {
 193         if (usePayloadReaderDelegate) return payloadReader.getAttributeLocalName(index);
 194         return super.getAttributeLocalName(index);
 195     }
 196 
 197     public String getAttributePrefix(int index) {
 198         if (usePayloadReaderDelegate) return payloadReader.getAttributePrefix(index);
 199         return super.getAttributePrefix(index);
 200     }
 201 
 202     public String getAttributeType(int index) {
 203         if (usePayloadReaderDelegate) return payloadReader.getAttributeType(index);
 204         return super.getAttributeType(index);
 205     }
 206 
 207     public String getAttributeValue(int index) {
 208         if (usePayloadReaderDelegate) return payloadReader.getAttributeValue(index);
 209         return super.getAttributeValue(index);
 210     }
 211 
 212     public boolean isAttributeSpecified(int index) {
 213         if (usePayloadReaderDelegate) return payloadReader.isAttributeSpecified(index);
 214         return super.isAttributeSpecified(index);
 215     }
 216 
 217     public int getNamespaceCount() {
 218         if (usePayloadReaderDelegate) return payloadReader.getNamespaceCount();
 219         return super.getNamespaceCount();
 220     }
 221 
 222     public String getNamespacePrefix(int index) {
 223         if (usePayloadReaderDelegate) return payloadReader.getNamespacePrefix(index);
 224         return super.getNamespacePrefix(index);
 225     }
 226 
 227     public String getNamespaceURI(int index) {
 228         if (usePayloadReaderDelegate) return payloadReader.getNamespaceURI(index);
 229         return super.getNamespaceURI(index);
 230     }
 231 
 232     public NamespaceContext getNamespaceContext() {
 233         if (usePayloadReaderDelegate) return payloadReader.getNamespaceContext();
 234         return super.getNamespaceContext();
 235     }
 236 
 237     public int getEventType() {
 238         if (usePayloadReaderDelegate) return payloadReader.getEventType();
 239         return super.getEventType();
 240     }
 241 
 242     public String getText() {
 243         if (usePayloadReaderDelegate) return payloadReader.getText();
 244         return super.getText();
 245     }
 246 
 247     public char[] getTextCharacters() {
 248         if (usePayloadReaderDelegate) return payloadReader.getTextCharacters();
 249         return super.getTextCharacters();
 250     }
 251 
 252     public int getTextCharacters(int sourceStart, char[] target,
 253             int targetStart, int length) throws XMLStreamException {
 254         if (usePayloadReaderDelegate) return payloadReader.getTextCharacters(sourceStart, target, targetStart,
 255                 length);
 256         return super.getTextCharacters(sourceStart, target, targetStart, length);
 257     }
 258 
 259     public int getTextStart() {
 260         if (usePayloadReaderDelegate) return payloadReader.getTextStart();
 261         return super.getTextStart();
 262     }
 263 
 264     public int getTextLength() {
 265         if (usePayloadReaderDelegate) return payloadReader.getTextLength();
 266         return super.getTextLength();
 267     }
 268 
 269     public String getEncoding() {
 270         if (usePayloadReaderDelegate) return payloadReader.getEncoding();
 271         return super.getEncoding();
 272     }
 273 
 274     public boolean hasText() {
 275         if (usePayloadReaderDelegate) return payloadReader.hasText();
 276         return super.hasText();
 277     }
 278 
 279     public Location getLocation() {
 280         if (usePayloadReaderDelegate) return payloadReader.getLocation();
 281         return super.getLocation();
 282     }
 283 
 284     public QName getName() {
 285         if (usePayloadReaderDelegate) return payloadReader.getName();
 286         return super.getName();
 287     }
 288 
 289     public String getLocalName() {
 290         if (usePayloadReaderDelegate) return payloadReader.getLocalName();
 291         return super.getLocalName();
 292     }
 293 
 294     public boolean hasName() {
 295         if (usePayloadReaderDelegate) return payloadReader.hasName();
 296         return super.hasName();
 297     }
 298 
 299     public String getNamespaceURI() {
 300         if (usePayloadReaderDelegate) return payloadReader.getNamespaceURI();
 301         return super.getNamespaceURI();
 302     }
 303 
 304     public String getPrefix() {
 305         if (usePayloadReaderDelegate) return payloadReader.getPrefix();
 306         return super.getPrefix();
 307     }
 308 
 309     public String getVersion() {
 310         if (usePayloadReaderDelegate) return payloadReader.getVersion();
 311         return super.getVersion();
 312     }
 313 
 314     public boolean isStandalone() {
 315         if (usePayloadReaderDelegate) return payloadReader.isStandalone();
 316         return super.isStandalone();
 317     }
 318 
 319     public boolean standaloneSet() {
 320         if (usePayloadReaderDelegate) return payloadReader.standaloneSet();
 321         return super.standaloneSet();
 322     }
 323 
 324     public String getCharacterEncodingScheme() {
 325         if (usePayloadReaderDelegate) return payloadReader.getCharacterEncodingScheme();
 326         return super.getCharacterEncodingScheme();
 327     }
 328 
 329     public String getPITarget() {
 330         if (usePayloadReaderDelegate) return payloadReader.getPITarget();
 331         return super.getPITarget();
 332     }
 333 
 334     public String getPIData() {
 335         if (usePayloadReaderDelegate) return payloadReader.getPIData();
 336         return super.getPIData();
 337     }
 338 
 339     //make sure that message is not realized as a result of call
 340     //to getFirstChild
 341     protected Node getFirstChild(Node node) {
 342         if (node instanceof BodyImpl) {
 343             return ((BodyImpl) node).getFirstChildNoMaterialize();
 344         } else {
 345             return node.getFirstChild();
 346         }
 347     }
 348 
 349     protected Node getNextSibling(Node node) {
 350         if (node instanceof BodyImpl) {
 351             //body is not expected to have a next sibling - even if it does
 352             //we would have to materialize the node to retrieve it.
 353             //Since we don't want to materialize it right now, just return null
 354             return null;
 355         }
 356         return node.getNextSibling();
 357     }
 358 
 359 }