177 */ 178 public final @NotNull Message decode(@NotNull XMLStreamReader reader) { 179 return decode(reader,new AttachmentSetImpl()); 180 } 181 182 /** 183 * Decodes a message from {@link XMLStreamReader} that points to 184 * the beginning of a SOAP infoset. 185 * 186 * @param reader 187 * can point to the start document or the start element. 188 * @param attachmentSet 189 * {@link StreamSOAPCodec} can take attachments parsed outside, 190 * so that this codec can be used as a part of a biggre codec 191 * (like MIME multipart codec.) 192 */ 193 public final Message decode(XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) { 194 return decode(soapVersion, reader, attachmentSet); 195 } 196 197 public static final Message decode(SOAPVersion soapVersion, XMLStreamReader reader, 198 @NotNull AttachmentSet attachmentSet) { 199 200 // Move to soap:Envelope and verify 201 if(reader.getEventType()!=XMLStreamConstants.START_ELEMENT) 202 XMLStreamReaderUtil.nextElementContent(reader); 203 XMLStreamReaderUtil.verifyReaderState(reader,XMLStreamConstants.START_ELEMENT); 204 if (SOAP_ENVELOPE.equals(reader.getLocalName()) && !soapVersion.nsUri.equals(reader.getNamespaceURI())) { 205 throw new VersionMismatchException(soapVersion, soapVersion.nsUri, reader.getNamespaceURI()); 206 } 207 XMLStreamReaderUtil.verifyTag(reader, soapVersion.nsUri, SOAP_ENVELOPE); 208 209 TagInfoset envelopeTag = new TagInfoset(reader); 210 211 // Collect namespaces on soap:Envelope 212 Map<String,String> namespaces = new HashMap<String,String>(); 213 for(int i=0; i< reader.getNamespaceCount();i++){ 214 namespaces.put(reader.getNamespacePrefix(i), reader.getNamespaceURI(i)); 215 } 216 217 // Move to next element 218 XMLStreamReaderUtil.nextElementContent(reader); 219 XMLStreamReaderUtil.verifyReaderState(reader, 220 javax.xml.stream.XMLStreamConstants.START_ELEMENT); 221 222 HeaderList headers = null; 223 TagInfoset headerTag = null; 224 225 if (reader.getLocalName().equals(SOAP_HEADER) 226 && reader.getNamespaceURI().equals(soapVersion.nsUri)) { 227 headerTag = new TagInfoset(reader); 228 229 // Collect namespaces on soap:Header 230 for(int i=0; i< reader.getNamespaceCount();i++){ 231 namespaces.put(reader.getNamespacePrefix(i), reader.getNamespaceURI(i)); 232 } 233 // skip <soap:Header> 234 XMLStreamReaderUtil.nextElementContent(reader); 235 236 // If SOAP header blocks are present (i.e. not <soap:Header/>) 237 if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) { 238 headers = new HeaderList(soapVersion); 239 240 try { 241 // Cache SOAP header blocks 242 StreamHeaderDecoder headerDecoder = SOAPVersion.SOAP_11.equals(soapVersion) ? StreamSOAP11Codec.SOAP11StreamHeaderDecoder : StreamSOAP12Codec.SOAP12StreamHeaderDecoder; 243 cacheHeaders(reader, namespaces, headers, headerDecoder); 244 } catch (XMLStreamException e) { 245 // TODO need to throw more meaningful exception 246 throw new WebServiceException(e); 247 } 248 } 249 250 // Move to soap:Body 251 XMLStreamReaderUtil.nextElementContent(reader); 252 } 253 254 // Verify that <soap:Body> is present 255 XMLStreamReaderUtil.verifyTag(reader, soapVersion.nsUri, SOAP_BODY); 256 TagInfoset bodyTag = new TagInfoset(reader); 257 258 String bodyPrologue = XMLStreamReaderUtil.nextWhiteSpaceContent(reader); 259 return new StreamMessage(envelopeTag,headerTag,attachmentSet,headers,bodyPrologue,bodyTag,null,reader,soapVersion); 260 // when there's no payload, 261 // it's tempting to use EmptyMessageImpl, but it doesn't preserve the infoset 262 // of <envelope>,<header>, and <body>, so we need to stick to StreamMessage. 263 } 264 265 public void decode(ReadableByteChannel in, String contentType, Packet packet ) { 266 throw new UnsupportedOperationException(); 267 } 268 269 public final StreamSOAPCodec copy() { 270 return this; 271 } 272 273 private static XMLStreamBuffer cacheHeaders(XMLStreamReader reader, 274 Map<String, String> namespaces, HeaderList headers, 275 StreamHeaderDecoder headerDecoder) throws XMLStreamException { 276 MutableXMLStreamBuffer buffer = createXMLStreamBuffer(); 277 StreamReaderBufferCreator creator = new StreamReaderBufferCreator(); 278 creator.setXMLStreamBuffer(buffer); 279 280 // Reader is positioned at the first header block 281 while(reader.getEventType() == javax.xml.stream.XMLStreamConstants.START_ELEMENT) { 282 Map<String,String> headerBlockNamespaces = namespaces; 283 284 // Collect namespaces on SOAP header block 285 if (reader.getNamespaceCount() > 0) { 286 headerBlockNamespaces = new HashMap<String,String>(namespaces); 287 for (int i = 0; i < reader.getNamespaceCount(); i++) { 288 headerBlockNamespaces.put(reader.getNamespacePrefix(i), reader.getNamespaceURI(i)); 289 } 290 } 291 292 // Mark 293 XMLStreamBuffer mark = new XMLStreamBufferMark(headerBlockNamespaces, creator); 294 // Create Header 295 headers.add(headerDecoder.decodeHeader(reader, mark)); 296 297 298 // Cache the header block 299 // After caching Reader will be positioned at next header block or 300 // the end of the </soap:header> 301 creator.createElementFragment(reader, false); 302 if (reader.getEventType() != XMLStreamConstants.START_ELEMENT && 303 reader.getEventType() != XMLStreamConstants.END_ELEMENT) { 304 XMLStreamReaderUtil.nextElementContent(reader); 305 } 306 } 307 308 return buffer; 309 } 310 311 protected interface StreamHeaderDecoder { 312 public Header decodeHeader(XMLStreamReader reader, XMLStreamBuffer mark); 313 } 314 315 private static MutableXMLStreamBuffer createXMLStreamBuffer() { 316 // TODO: Decode should own one MutableXMLStreamBuffer for reuse 317 // since it is more efficient. ISSUE: possible issue with 318 // lifetime of information in the buffer if accessed beyond 319 // the pipe line. 320 return new MutableXMLStreamBuffer(); 321 } 322 323 public void decode(InputStream in, String contentType, Packet packet, AttachmentSet att ) throws IOException { 324 List<String> expectedContentTypes = getExpectedContentTypes(); 325 if (contentType != null && !isContentTypeSupported(contentType,expectedContentTypes)) { 326 throw new UnsupportedMediaException(contentType, expectedContentTypes); 327 } 328 com.oracle.webservices.internal.api.message.ContentType pct = packet.getInternalContentType(); 329 ContentTypeImpl cti = (pct != null && pct instanceof ContentTypeImpl) ? 330 (ContentTypeImpl)pct : new ContentTypeImpl(contentType); 331 String charset = cti.getCharSet(); 332 if (charset != null && !Charset.isSupported(charset)) { 333 throw new UnsupportedMediaException(charset); 334 } 335 if (charset != null) { 336 packet.invocationProperties.put(DECODED_MESSAGE_CHARSET, charset); 337 } else { 338 packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET); 339 } 340 packet.setMessage(streamDecoder.decode(in, charset, att, soapVersion)); | 177 */ 178 public final @NotNull Message decode(@NotNull XMLStreamReader reader) { 179 return decode(reader,new AttachmentSetImpl()); 180 } 181 182 /** 183 * Decodes a message from {@link XMLStreamReader} that points to 184 * the beginning of a SOAP infoset. 185 * 186 * @param reader 187 * can point to the start document or the start element. 188 * @param attachmentSet 189 * {@link StreamSOAPCodec} can take attachments parsed outside, 190 * so that this codec can be used as a part of a biggre codec 191 * (like MIME multipart codec.) 192 */ 193 public final Message decode(XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) { 194 return decode(soapVersion, reader, attachmentSet); 195 } 196 197 public static final Message decode(SOAPVersion soapVersion, XMLStreamReader reader, @NotNull AttachmentSet attachmentSet) { 198 // Move to soap:Envelope and verify 199 if(reader.getEventType()!=XMLStreamConstants.START_ELEMENT) 200 XMLStreamReaderUtil.nextElementContent(reader); 201 XMLStreamReaderUtil.verifyReaderState(reader,XMLStreamConstants.START_ELEMENT); 202 if (SOAP_ENVELOPE.equals(reader.getLocalName()) && !soapVersion.nsUri.equals(reader.getNamespaceURI())) { 203 throw new VersionMismatchException(soapVersion, soapVersion.nsUri, reader.getNamespaceURI()); 204 } 205 XMLStreamReaderUtil.verifyTag(reader, soapVersion.nsUri, SOAP_ENVELOPE); 206 return new StreamMessage(soapVersion, reader, attachmentSet); 207 } 208 209 public void decode(ReadableByteChannel in, String contentType, Packet packet ) { 210 throw new UnsupportedOperationException(); 211 } 212 213 public final StreamSOAPCodec copy() { 214 return this; 215 } 216 217 public void decode(InputStream in, String contentType, Packet packet, AttachmentSet att ) throws IOException { 218 List<String> expectedContentTypes = getExpectedContentTypes(); 219 if (contentType != null && !isContentTypeSupported(contentType,expectedContentTypes)) { 220 throw new UnsupportedMediaException(contentType, expectedContentTypes); 221 } 222 com.oracle.webservices.internal.api.message.ContentType pct = packet.getInternalContentType(); 223 ContentTypeImpl cti = (pct != null && pct instanceof ContentTypeImpl) ? 224 (ContentTypeImpl)pct : new ContentTypeImpl(contentType); 225 String charset = cti.getCharSet(); 226 if (charset != null && !Charset.isSupported(charset)) { 227 throw new UnsupportedMediaException(charset); 228 } 229 if (charset != null) { 230 packet.invocationProperties.put(DECODED_MESSAGE_CHARSET, charset); 231 } else { 232 packet.invocationProperties.remove(DECODED_MESSAGE_CHARSET); 233 } 234 packet.setMessage(streamDecoder.decode(in, charset, att, soapVersion)); |