Thu, 31 Aug 2017 15:18:52 +0800
merge
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 */
26 package com.sun.xml.internal.ws.message.jaxb;
28 import com.sun.istack.internal.NotNull;
29 import com.sun.istack.internal.XMLStreamException2;
30 import com.sun.xml.internal.bind.api.Bridge;
31 import com.sun.xml.internal.stream.buffer.MutableXMLStreamBuffer;
32 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
33 import com.sun.xml.internal.stream.buffer.XMLStreamBufferResult;
34 import com.sun.xml.internal.ws.api.message.Header;
35 import com.sun.xml.internal.ws.encoding.SOAPBindingCodec;
36 import com.sun.xml.internal.ws.message.AbstractHeaderImpl;
37 import com.sun.xml.internal.ws.message.RootElementSniffer;
38 import com.sun.xml.internal.ws.spi.db.BindingContext;
39 import com.sun.xml.internal.ws.spi.db.XMLBridge;
40 import com.sun.xml.internal.ws.streaming.XMLStreamWriterUtil;
41 import org.xml.sax.Attributes;
42 import org.xml.sax.ContentHandler;
43 import org.xml.sax.ErrorHandler;
44 import org.xml.sax.SAXException;
45 import org.xml.sax.SAXParseException;
47 import javax.xml.bind.JAXBElement;
48 import javax.xml.bind.JAXBException;
49 import javax.xml.bind.Unmarshaller;
50 import javax.xml.bind.util.JAXBResult;
51 import javax.xml.namespace.QName;
52 import javax.xml.soap.SOAPException;
53 import javax.xml.soap.SOAPMessage;
54 import javax.xml.soap.SOAPHeader;
55 import javax.xml.stream.XMLStreamException;
56 import javax.xml.stream.XMLStreamReader;
57 import javax.xml.stream.XMLStreamWriter;
58 import java.io.OutputStream;
60 /**
61 * {@link Header} whose physical data representation is a JAXB bean.
62 *
63 * @author Kohsuke Kawaguchi
64 */
65 public final class JAXBHeader extends AbstractHeaderImpl {
67 /**
68 * The JAXB object that represents the header.
69 */
70 private final Object jaxbObject;
72 private final XMLBridge bridge;
74 // information about this header. lazily obtained.
75 private String nsUri;
76 private String localName;
77 private Attributes atts;
79 /**
80 * Once the header is turned into infoset,
81 * this buffer keeps it.
82 */
83 private XMLStreamBuffer infoset;
85 public JAXBHeader(BindingContext context, Object jaxbObject) {
86 this.jaxbObject = jaxbObject;
87 // this.bridge = new MarshallerBridge(context);
88 this.bridge = context.createFragmentBridge();
90 if (jaxbObject instanceof JAXBElement) {
91 JAXBElement e = (JAXBElement) jaxbObject;
92 this.nsUri = e.getName().getNamespaceURI();
93 this.localName = e.getName().getLocalPart();
94 }
95 }
97 public JAXBHeader(XMLBridge bridge, Object jaxbObject) {
98 this.jaxbObject = jaxbObject;
99 this.bridge = bridge;
101 QName tagName = bridge.getTypeInfo().tagName;
102 this.nsUri = tagName.getNamespaceURI();
103 this.localName = tagName.getLocalPart();
104 }
106 /**
107 * Lazily parse the first element to obtain attribute values on it.
108 */
109 private void parse() {
110 RootElementSniffer sniffer = new RootElementSniffer();
111 try {
112 bridge.marshal(jaxbObject,sniffer,null);
113 } catch (JAXBException e) {
114 // if it's due to us aborting the processing after the first element,
115 // we can safely ignore this exception.
116 //
117 // if it's due to error in the object, the same error will be reported
118 // when the readHeader() method is used, so we don't have to report
119 // an error right now.
120 nsUri = sniffer.getNsUri();
121 localName = sniffer.getLocalName();
122 atts = sniffer.getAttributes();
123 }
124 }
127 public @NotNull String getNamespaceURI() {
128 if(nsUri==null)
129 parse();
130 return nsUri;
131 }
133 public @NotNull String getLocalPart() {
134 if(localName==null)
135 parse();
136 return localName;
137 }
139 public String getAttribute(String nsUri, String localName) {
140 if(atts==null)
141 parse();
142 return atts.getValue(nsUri,localName);
143 }
145 public XMLStreamReader readHeader() throws XMLStreamException {
146 if(infoset==null) {
147 MutableXMLStreamBuffer buffer = new MutableXMLStreamBuffer();
148 writeTo(buffer.createFromXMLStreamWriter());
149 infoset = buffer;
150 }
151 return infoset.readAsXMLStreamReader();
152 }
154 public <T> T readAsJAXB(Unmarshaller unmarshaller) throws JAXBException {
155 try {
156 JAXBResult r = new JAXBResult(unmarshaller);
157 // bridge marshals a fragment, so we need to add start/endDocument by ourselves
158 r.getHandler().startDocument();
159 bridge.marshal(jaxbObject,r);
160 r.getHandler().endDocument();
161 return (T)r.getResult();
162 } catch (SAXException e) {
163 throw new JAXBException(e);
164 }
165 }
166 /** @deprecated */
167 public <T> T readAsJAXB(Bridge<T> bridge) throws JAXBException {
168 return bridge.unmarshal(new JAXBBridgeSource(this.bridge,jaxbObject));
169 }
171 public <T> T readAsJAXB(XMLBridge<T> bond) throws JAXBException {
172 return bond.unmarshal(new JAXBBridgeSource(this.bridge,jaxbObject),null);
173 }
175 public void writeTo(XMLStreamWriter sw) throws XMLStreamException {
176 try {
177 // Get the encoding of the writer
178 String encoding = XMLStreamWriterUtil.getEncoding(sw);
180 // Get output stream and use JAXB UTF-8 writer
181 OutputStream os = bridge.supportOutputStream() ? XMLStreamWriterUtil.getOutputStream(sw) : null;
182 if (os != null && encoding != null && encoding.equalsIgnoreCase(SOAPBindingCodec.UTF8_ENCODING)) {
183 bridge.marshal(jaxbObject, os, sw.getNamespaceContext(), null);
184 } else {
185 bridge.marshal(jaxbObject,sw, null);
186 }
187 } catch (JAXBException e) {
188 throw new XMLStreamException2(e);
189 }
190 }
192 public void writeTo(SOAPMessage saaj) throws SOAPException {
193 try {
194 SOAPHeader header = saaj.getSOAPHeader();
195 if (header == null)
196 header = saaj.getSOAPPart().getEnvelope().addHeader();
197 bridge.marshal(jaxbObject,header);
198 } catch (JAXBException e) {
199 throw new SOAPException(e);
200 }
201 }
203 public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException {
204 try {
205 bridge.marshal(jaxbObject,contentHandler,null);
206 } catch (JAXBException e) {
207 SAXParseException x = new SAXParseException(e.getMessage(),null,null,-1,-1,e);
208 errorHandler.fatalError(x);
209 throw x;
210 }
211 }
212 }