001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.jaxws.message.impl;
020:
021: import org.apache.axiom.om.OMElement;
022: import org.apache.axis2.jaxws.message.Block;
023: import org.apache.axis2.jaxws.message.Protocol;
024: import org.apache.axis2.jaxws.message.util.StackableReader;
025: import org.apache.axis2.jaxws.message.util.XMLStreamReaderFilter;
026:
027: import javax.xml.namespace.QName;
028: import javax.xml.stream.XMLStreamException;
029: import javax.xml.ws.WebServiceException;
030: import java.util.List;
031:
032: /**
033: * XMLStreamReaderForXMLSpine
034: * <p/>
035: * An XMLSpine is composed of many different parts: a sparse OM tree, header blocks, body blocks,
036: * etc.
037: * <p/>
038: * The XMLStreamReaderForXMLSpine provides an XMLStreamReader that over all of these combined
039: * objects (without building a full OM tree). It does this by using a StackableXMLStreamReader for
040: * the underlying implementation and pushing the XMLStreamReaders for the blocks onto the stack at
041: * the appropriate points in the message.
042: */
043: public class XMLStreamReaderForXMLSpine extends XMLStreamReaderFilter {
044:
045: // Components of an XMLSpine
046: OMElement root;
047: private List<Block> headerBlocks = null;
048: private List<Block> bodyBlocks = null;
049: private List<Block> detailBlocks = null;
050: private boolean consume = false;
051: Protocol protocol = null;
052:
053: // Local Constants
054: private static final String BODY = "Body";
055: private static final String HEADER = "Header";
056: private static final String FAULT = "Fault";
057: private static final String DETAIL11 = "detail";
058: private static final String DETAIL12 = "Detail";
059:
060: boolean inFault = false;
061: private List<Block> insertBlocks = null;
062:
063: /**
064: * @param root of the XMLSpine
065: * @param headerBlocks
066: * @param bodyBocks
067: * @param detailBlocks
068: * @param consume
069: */
070: public XMLStreamReaderForXMLSpine(OMElement root,
071: Protocol protocol, List<Block> headerBlocks,
072: List<Block> bodyBlocks, List<Block> detailBlocks,
073: boolean consume) {
074: // Create a stackable reader and prime it with the root om tree
075: // The XMLStreamReader's for the blocks will be pushed onto the
076: // stack as the message is processed.
077: super (new StackableReader(root.getXMLStreamReader()));
078: this .root = root;
079: this .protocol = protocol;
080: this .headerBlocks = headerBlocks;
081: this .bodyBlocks = bodyBlocks;
082: this .detailBlocks = detailBlocks;
083: this .consume = consume;
084: }
085:
086: @Override
087: public int next() throws XMLStreamException {
088: // The next method is overridden so that we can push
089: // the block's XMLStreamReaders onto the stack at the
090: // appropriate places in the message (pretty slick).
091:
092: // Insert pending blocks onto the stack
093: if (insertBlocks != null) {
094: pushBlocks(insertBlocks, consume);
095: insertBlocks = null;
096:
097: }
098:
099: // Get the next event
100: int event = super .next();
101:
102: // If this is a start element event, then we may need to insert
103: // the blocks prior to the next event
104: if (isStartElement()) {
105: QName qName = super .getName();
106: // Insert body blocks after the Body
107: if (qName.getLocalPart().equals(BODY)
108: && qName.getNamespaceURI().equals(
109: root.getNamespace().getNamespaceURI())) {
110: if (bodyBlocks != null) {
111: insertBlocks = bodyBlocks;
112: bodyBlocks = null;
113: }
114: }
115: // Insert header blocks after the header
116: else if (qName.getLocalPart().equals(HEADER)
117: && qName.getNamespaceURI().equals(
118: root.getNamespace().getNamespaceURI())) {
119: if (headerBlocks != null) {
120: insertBlocks = headerBlocks;
121: headerBlocks = null;
122: }
123: } else if (qName.getLocalPart().equals(FAULT)
124: && qName.getNamespaceURI().equals(
125: root.getNamespace().getNamespaceURI())) {
126: inFault = true;
127: }
128: // Insert Detail blocks afger the detail...note that
129: // the detail name is different in SOAP 1.1 and SOAP 1.2
130: else if (inFault) {
131: if (qName.getLocalPart().equals(DETAIL11)
132: && protocol.equals(Protocol.soap11)
133: || qName.getLocalPart().equals(DETAIL12)
134: && protocol.equals(Protocol.soap12)) {
135: if (detailBlocks != null) {
136: insertBlocks = detailBlocks;
137: detailBlocks = null;
138: }
139: }
140: }
141: }
142: return event;
143: }
144:
145: /**
146: * Push the XMLStreamReaders for the blocks
147: *
148: * @param blocks
149: */
150: private void pushBlocks(List<Block> blocks, boolean consume)
151: throws XMLStreamException {
152: // Push the XMLStreamReaders for the blocks onto the
153: // delegate. This is done in reverse order of the blocks so that the
154: // first block's xmlstreamreader is ontop of the stack.
155: try {
156: StackableReader sr = (StackableReader) delegate;
157: for (int i = blocks.size() - 1; i >= 0; i--) {
158: Block block = blocks.get(i);
159: if (block != null) {
160: sr.push(block.getXMLStreamReader(consume));
161: }
162: }
163: } catch (WebServiceException me) {
164: throw new XMLStreamException(me);
165: }
166: }
167: }
|