001    /** 
002     * 
003     * Copyright 2004 Protique Ltd
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * You may obtain a copy of the License at 
008     * 
009     * http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS, 
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
014     * See the License for the specific language governing permissions and 
015     * limitations under the License. 
016     * 
017     **/
018    package org.codehaus.activesoap.util;
019    
020    import javax.xml.namespace.QName;
021    import javax.xml.stream.XMLStreamConstants;
022    import javax.xml.stream.XMLStreamException;
023    import javax.xml.stream.XMLStreamReader;
024    import javax.xml.stream.util.StreamReaderDelegate;
025    
026    /**
027     * An {@link StreamReaderDelegate} which creates a logical sub-document
028     * from a stream until a certain close element is discovered - such as for making
029     * the contents of a SOAP body appear as a logical XML document.
030     *
031     * @version $Revision: 1.6 $
032     */
033    public class DocumentFilterXMLStreamReader extends StreamReaderDelegate implements XMLStreamConstants {
034        boolean first = true;
035        boolean finished = false;
036        private final QName name;
037        private boolean second;
038    
039    
040        public DocumentFilterXMLStreamReader(XMLStreamReader in) {
041            this(in.getName(), in);
042        }
043    
044    
045        public DocumentFilterXMLStreamReader(QName name, XMLStreamReader in) {
046            super(in);
047            this.name = name;
048        }
049    
050        public void disableStartDocumentEvent() {
051            first = false;
052        }
053    
054        public boolean hasNext() throws XMLStreamException {
055            if (first) {
056                return true;
057            }
058            else if (finished) {
059                return false;
060            }
061            return super.hasNext();
062        }
063    
064        public int next() throws XMLStreamException {
065            if (first) {
066                first = false;
067                second = true;
068                return START_DOCUMENT;
069            }
070            else if (second) {
071                second = false;
072                return super.getEventType();
073            }
074            else if (finished) {
075                return END_DOCUMENT;
076            }
077            else {
078                int answer = super.next();
079                // TODO : to avoid bug in RI disable this line
080                //if (answer == END_ELEMENT && name.equals(getName())) {
081                if (answer == END_ELEMENT && name.getLocalPart().equals(getLocalName()) && name.getNamespaceURI().equals(getNamespaceURI())) {
082                    finished = true;
083                }
084                return answer;
085            }
086        }
087    
088        public int nextTag() throws XMLStreamException {
089            int eventType = next();
090            if (eventType == START_DOCUMENT) {
091                eventType = next();     
092            }
093            while ((eventType == CHARACTERS && isWhiteSpace()) // skip whitespace
094                    || (eventType == CDATA && isWhiteSpace())
095                    // skip whitespace
096                    || eventType == SPACE
097                    || eventType == PROCESSING_INSTRUCTION
098                    || eventType == COMMENT
099                    ) {
100                eventType = next();
101            }
102            if (eventType != START_ELEMENT && eventType != END_ELEMENT) {
103                throw new XMLStreamException("expected start or end tag but got type: " + eventType, getLocation());
104            }
105            return eventType;
106        }
107    
108        public int getEventType() {
109            if (first) {
110                return START_DOCUMENT;
111            }
112            else if (finished) {
113                return END_DOCUMENT;
114            }
115            return super.getEventType();
116        }
117    }
118