1/*
2 * Copyright (c) 1997, 2013, 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
26package com.sun.xml.internal.ws.encoding.fastinfoset;
27
28import com.sun.xml.internal.fastinfoset.stax.StAXDocumentSerializer;
29import com.sun.xml.internal.fastinfoset.stax.StAXDocumentParser;
30import com.sun.xml.internal.ws.api.pipe.Codec;
31import com.sun.xml.internal.ws.api.pipe.ContentType;
32import com.sun.xml.internal.ws.api.message.Packet;
33import com.sun.xml.internal.ws.api.SOAPVersion;
34import com.sun.xml.internal.ws.api.pipe.StreamSOAPCodec;
35import com.sun.xml.internal.ws.message.stream.StreamHeader;
36import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
37import com.sun.xml.internal.ws.encoding.ContentTypeImpl;
38
39import javax.xml.stream.XMLStreamException;
40import javax.xml.stream.XMLStreamWriter;
41import javax.xml.stream.XMLStreamReader;
42import javax.xml.ws.WebServiceException;
43import java.io.OutputStream;
44import java.io.InputStream;
45import java.io.IOException;
46import java.nio.channels.WritableByteChannel;
47import java.nio.channels.ReadableByteChannel;
48
49/**
50 * A stream SOAP codec for handling SOAP message infosets to fast
51 * infoset documents.
52 *
53 * <p>
54 * This implementation currently defers to {@link StreamSOAPCodec} for the decoding
55 * using {@link XMLStreamReader}.
56 *
57 * @author Paul Sandoz
58 */
59public abstract class FastInfosetStreamSOAPCodec implements Codec {
60    private static final FastInfosetStreamReaderFactory READER_FACTORY = FastInfosetStreamReaderFactory.getInstance();
61
62    private StAXDocumentParser _statefulParser;
63    private StAXDocumentSerializer _serializer;
64
65    private final StreamSOAPCodec _soapCodec;
66
67    private final boolean _retainState;
68
69    protected final ContentType _defaultContentType;
70
71    /* package */ FastInfosetStreamSOAPCodec(StreamSOAPCodec soapCodec, SOAPVersion soapVersion, boolean retainState, String mimeType) {
72//        _soapCodec = StreamSOAPCodec.create(soapVersion);
73        _soapCodec = soapCodec;
74        _retainState = retainState;
75        _defaultContentType = new ContentTypeImpl(mimeType);
76    }
77
78    /* package */ FastInfosetStreamSOAPCodec(FastInfosetStreamSOAPCodec that) {
79        this._soapCodec = (StreamSOAPCodec) that._soapCodec.copy();
80        this._retainState = that._retainState;
81        this._defaultContentType = that._defaultContentType;
82    }
83
84    public String getMimeType() {
85        return _defaultContentType.getContentType();
86    }
87
88    public ContentType getStaticContentType(Packet packet) {
89        return getContentType(packet.soapAction);
90    }
91
92    public ContentType encode(Packet packet, OutputStream out) {
93        if (packet.getMessage() != null) {
94            final XMLStreamWriter writer = getXMLStreamWriter(out);
95            try {
96                packet.getMessage().writeTo(writer);
97                writer.flush();
98            } catch (XMLStreamException e) {
99                throw new WebServiceException(e);
100            }
101        }
102        return getContentType(packet.soapAction);
103    }
104
105    public ContentType encode(Packet packet, WritableByteChannel buffer) {
106        //TODO: not yet implemented
107        throw new UnsupportedOperationException();
108    }
109
110    public void decode(InputStream in, String contentType, Packet response) throws IOException {
111        response.setMessage(
112                _soapCodec.decode(getXMLStreamReader(in)));
113    }
114
115    public void decode(ReadableByteChannel in, String contentType, Packet response) {
116        throw new UnsupportedOperationException();
117    }
118
119    protected abstract StreamHeader createHeader(XMLStreamReader reader, XMLStreamBuffer mark);
120
121    protected abstract ContentType getContentType(String soapAction);
122
123    private XMLStreamWriter getXMLStreamWriter(OutputStream out) {
124        if (_serializer != null) {
125            _serializer.setOutputStream(out);
126            return _serializer;
127        } else {
128            return _serializer = FastInfosetCodec.createNewStreamWriter(out, _retainState);
129        }
130    }
131
132    private XMLStreamReader getXMLStreamReader(InputStream in) {
133        // If the _retainState is true (FI stateful) then pick up Codec assiciated XMLStreamReader
134        if (_retainState) {
135            if (_statefulParser != null) {
136                _statefulParser.setInputStream(in);
137                return _statefulParser;
138            } else {
139                return _statefulParser = FastInfosetCodec.createNewStreamReader(in, _retainState);
140            }
141        }
142
143        // Otherwise thread assiciated XMLStreamReader
144        return READER_FACTORY.doCreate(null, in, false);
145    }
146
147    /**
148     * Creates a new {@link FastInfosetStreamSOAPCodec} instance.
149     *
150     * @param version the SOAP version of the codec.
151     * @return a new {@link FastInfosetStreamSOAPCodec} instance.
152     */
153    public static FastInfosetStreamSOAPCodec create(StreamSOAPCodec soapCodec, SOAPVersion version) {
154        return create(soapCodec, version, false);
155    }
156
157    /**
158     * Creates a new {@link FastInfosetStreamSOAPCodec} instance.
159     *
160     * @param version the SOAP version of the codec.
161     * @param retainState if true the Codec should retain the state of
162     *        vocabulary tables for multiple encode/decode invocations.
163     * @return a new {@link FastInfosetStreamSOAPCodec} instance.
164     */
165    public static FastInfosetStreamSOAPCodec create(StreamSOAPCodec soapCodec,
166            SOAPVersion version, boolean retainState) {
167        if(version==null)
168            // this decoder is for SOAP, not for XML/HTTP
169            throw new IllegalArgumentException();
170        switch(version) {
171            case SOAP_11:
172                return new FastInfosetStreamSOAP11Codec(soapCodec, retainState);
173            case SOAP_12:
174                return new FastInfosetStreamSOAP12Codec(soapCodec, retainState);
175            default:
176                throw new AssertionError();
177        }
178    }
179}
180