src/share/jaxws_classes/com/sun/xml/internal/ws/encoding/SOAPBindingCodec.java

changeset 368
0989ad8c0860
parent 286
f50545b5e2f1
child 637
9c07ef4934dd
equal deleted inserted replaced
366:8c0b6bccfe47 368:0989ad8c0860
1 /* 1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 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. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this 7 * published by the Free Software Foundation. Oracle designates this
49 import java.io.InputStream; 49 import java.io.InputStream;
50 import java.io.OutputStream; 50 import java.io.OutputStream;
51 import java.lang.reflect.Method; 51 import java.lang.reflect.Method;
52 import java.nio.channels.ReadableByteChannel; 52 import java.nio.channels.ReadableByteChannel;
53 import java.nio.channels.WritableByteChannel; 53 import java.nio.channels.WritableByteChannel;
54 import java.util.StringTokenizer; 54 //import java.util.StringTokenizer;
55 55
56 /** 56 /**
57 * SOAP binding {@link Codec} that can handle MTOM, SwA, and SOAP messages 57 * SOAP binding {@link Codec} that can handle MTOM, SwA, and SOAP messages
58 * encoded using XML or Fast Infoset. 58 * encoded using XML or Fast Infoset.
59 * 59 *
72 public class SOAPBindingCodec extends MimeCodec implements com.sun.xml.internal.ws.api.pipe.SOAPBindingCodec { 72 public class SOAPBindingCodec extends MimeCodec implements com.sun.xml.internal.ws.api.pipe.SOAPBindingCodec {
73 73
74 public static final String UTF8_ENCODING = "utf-8"; 74 public static final String UTF8_ENCODING = "utf-8";
75 public static final String DEFAULT_ENCODING = UTF8_ENCODING; 75 public static final String DEFAULT_ENCODING = UTF8_ENCODING;
76 76
77 /**
78 * Based on request's Accept header this is set.
79 * Currently only set if MTOMFeature is enabled.
80 *
81 * Should be used on server-side, for encoding the response.
82 */
83 private boolean acceptMtomMessages;
84
85 /**
86 * If the request's Content-Type is multipart/related; type=application/xop+xml, then this set to to true
87 *
88 * Used on server-side, for encoding the repsonse.
89 */
90 private boolean isRequestMtomMessage;
91
92 private enum TriState {UNSET,TRUE,FALSE}
93
94 /**
95 * This captures is decode is called before encode,
96 * if true, infers that this is being used on Server-side
97 */
98 private TriState decodeFirst = TriState.UNSET;
99 77
100 /** 78 /**
101 * True if Fast Infoset functionality has been 79 * True if Fast Infoset functionality has been
102 * configured to be disabled, or the Fast Infoset 80 * configured to be disabled, or the Fast Infoset
103 * runtime is not available. 81 * runtime is not available.
130 private final MimeCodec xmlSwaCodec; 108 private final MimeCodec xmlSwaCodec;
131 109
132 // The Fast Infoset SWA codec 110 // The Fast Infoset SWA codec
133 private final MimeCodec fiSwaCodec; 111 private final MimeCodec fiSwaCodec;
134 112
135 // private final SOAPBindingImpl binding;
136 // private final WebServiceFeature[] feature;
137
138 /** 113 /**
139 * The XML SOAP MIME type 114 * The XML SOAP MIME type
140 */ 115 */
141 private final String xmlMimeType; 116 private final String xmlMimeType;
142 117
157 132
158 public StreamSOAPCodec getXMLCodec() { 133 public StreamSOAPCodec getXMLCodec() {
159 return xmlSoapCodec; 134 return xmlSoapCodec;
160 } 135 }
161 136
162 private class AcceptContentType implements ContentType { 137 private ContentTypeImpl setAcceptHeader(Packet p, ContentTypeImpl c) {
163 private ContentType _c; 138 String _accept;
164 private String _accept; 139 if (!ignoreContentNegotiationProperty && p.contentNegotiation != ContentNegotiation.none) {
165 140 _accept = connegXmlAccept;
166 public AcceptContentType set(Packet p, ContentType c) { 141 } else {
167 if (!ignoreContentNegotiationProperty && p.contentNegotiation != ContentNegotiation.none) { 142 _accept = xmlAccept;
168 _accept = connegXmlAccept; 143 }
169 } else { 144 c.setAcceptHeader(_accept);
170 _accept = xmlAccept; 145 return c;
171 } 146 }
172 _c = c;
173 return this;
174 }
175
176 public String getContentType() {
177 return _c.getContentType();
178 }
179
180 public String getSOAPActionHeader() {
181 return _c.getSOAPActionHeader();
182 }
183
184 public String getAcceptHeader() {
185 return _accept;
186 }
187 }
188
189 private AcceptContentType _adaptingContentType = new AcceptContentType();
190 147
191 public SOAPBindingCodec(WSFeatureList features) { 148 public SOAPBindingCodec(WSFeatureList features) {
192 this(features, Codecs.createSOAPEnvelopeXmlCodec(features)); 149 this(features, Codecs.createSOAPEnvelopeXmlCodec(features));
193 } 150 }
194 151
250 ignoreContentNegotiationProperty = true; 207 ignoreContentNegotiationProperty = true;
251 } 208 }
252 209
253 xmlAccept = clientAcceptedContentTypes; 210 xmlAccept = clientAcceptedContentTypes;
254 211
255 // if(!(binding instanceof SOAPBindingImpl))
256 if(getSoapVersion(features) == null) 212 if(getSoapVersion(features) == null)
257 throw new WebServiceException("Expecting a SOAP binding but found "); 213 throw new WebServiceException("Expecting a SOAP binding but found ");
258 // this.binding = (SOAPBindingImpl)binding;
259 } 214 }
260 215
261 public String getMimeType() { 216 public String getMimeType() {
262 return null; 217 return null;
263 } 218 }
264 219
265 public ContentType getStaticContentType(Packet packet) { 220 public ContentType getStaticContentType(Packet packet) {
266 ContentType toAdapt = getEncoder(packet).getStaticContentType(packet); 221 ContentType toAdapt = getEncoder(packet).getStaticContentType(packet);
267 return (toAdapt != null) ? _adaptingContentType.set(packet, toAdapt) : null; 222 return setAcceptHeader(packet, (ContentTypeImpl)toAdapt);
268 } 223 }
269 224
270 public ContentType encode(Packet packet, OutputStream out) throws IOException { 225 public ContentType encode(Packet packet, OutputStream out) throws IOException {
271 preEncode(packet); 226 preEncode(packet);
272 ContentType ct = _adaptingContentType.set(packet, getEncoder(packet).encode(packet, out)); 227 ContentType ct = getEncoder(packet).encode(packet, out);
228 ct = setAcceptHeader(packet, (ContentTypeImpl)ct);
273 postEncode(); 229 postEncode();
274 return ct; 230 return ct;
275 } 231 }
276 232
277 public ContentType encode(Packet packet, WritableByteChannel buffer) { 233 public ContentType encode(Packet packet, WritableByteChannel buffer) {
278 preEncode(packet); 234 preEncode(packet);
279 ContentType ct = _adaptingContentType.set(packet, getEncoder(packet).encode(packet, buffer)); 235 ContentType ct = getEncoder(packet).encode(packet, buffer);
236 ct = setAcceptHeader(packet, (ContentTypeImpl)ct);
280 postEncode(); 237 postEncode();
281 return ct; 238 return ct;
282 } 239 }
283 240
284 /** 241 /**
285 * Should be called before encode(). 242 * Should be called before encode().
286 * Set the state so that such state is used by encode process. 243 * Set the state so that such state is used by encode process.
287 */ 244 */
288 private void preEncode(Packet p) { 245 private void preEncode(Packet p) {
289 if (decodeFirst == TriState.UNSET)
290 decodeFirst = TriState.FALSE;
291 } 246 }
292 247
293 /** 248 /**
294 * Should be called after encode() 249 * Should be called after encode()
295 * Reset the encoding state. 250 * Reset the encoding state.
296 */ 251 */
297 private void postEncode() { 252 private void postEncode() {
298 decodeFirst = TriState.UNSET;
299 acceptMtomMessages = false;
300 isRequestMtomMessage = false;
301 } 253 }
302 254
303 /** 255 /**
304 * Should be called before decode(). 256 * Should be called before decode().
305 * Set the state so that such state is used by decode(). 257 * Set the state so that such state is used by decode().
312 /** 264 /**
313 * Should be called after decode(). 265 * Should be called after decode().
314 * Set the state so that such state is used by encode(). 266 * Set the state so that such state is used by encode().
315 */ 267 */
316 private void postDecode(Packet p) { 268 private void postDecode(Packet p) {
317 if(decodeFirst == TriState.UNSET) 269 p.setFastInfosetDisabled(isFastInfosetDisabled);
318 decodeFirst = TriState.TRUE; 270 if(features.isEnabled(MTOMFeature.class)) p.checkMtomAcceptable();
319 if(features.isEnabled(MTOMFeature.class)) 271 // p.setMtomAcceptable( isMtomAcceptable(p.acceptableMimeTypes) );
320 acceptMtomMessages =isMtomAcceptable(p.acceptableMimeTypes); 272 MTOMFeature mtomFeature = features.get(MTOMFeature.class);
273 if (mtomFeature != null) {
274 p.setMtomFeature(mtomFeature);
275 }
321 if (!useFastInfosetForEncoding) { 276 if (!useFastInfosetForEncoding) {
322 useFastInfosetForEncoding = isFastInfosetAcceptable(p.acceptableMimeTypes); 277 useFastInfosetForEncoding = p.getFastInfosetAcceptable(fiMimeType);
323 } 278 // useFastInfosetForEncoding = isFastInfosetAcceptable(p.acceptableMimeTypes);
324 } 279 }
325
326
327 private boolean isServerSide() {
328 return decodeFirst == TriState.TRUE;
329 } 280 }
330 281
331 public void decode(InputStream in, String contentType, Packet packet) throws IOException { 282 public void decode(InputStream in, String contentType, Packet packet) throws IOException {
332 if (contentType == null) { 283 if (contentType == null) {
333 contentType = xmlMimeType; 284 contentType = xmlMimeType;
334 } 285 }
335 286 packet.setContentType(new ContentTypeImpl(contentType));
336 preDecode(packet); 287 preDecode(packet);
337 try { 288 try {
338 if(isMultipartRelated(contentType)) 289 if(isMultipartRelated(contentType))
339 // parse the multipart portion and then decide whether it's MTOM or SwA 290 // parse the multipart portion and then decide whether it's MTOM or SwA
340 super.decode(in, contentType, packet); 291 super.decode(in, contentType, packet);
389 340
390 @Override 341 @Override
391 protected void decode(MimeMultipartParser mpp, Packet packet) throws IOException { 342 protected void decode(MimeMultipartParser mpp, Packet packet) throws IOException {
392 // is this SwA or XOP? 343 // is this SwA or XOP?
393 final String rootContentType = mpp.getRootPart().getContentType(); 344 final String rootContentType = mpp.getRootPart().getContentType();
394 345 boolean isMTOM = isApplicationXopXml(rootContentType);
395 if(isApplicationXopXml(rootContentType)) { 346 packet.setMtomRequest(isMTOM);
396 isRequestMtomMessage = true; 347 if(isMTOM) {
397 xmlMtomCodec.decode(mpp,packet); 348 xmlMtomCodec.decode(mpp,packet);
398 } else if (isFastInfoset(rootContentType)) { 349 } else if (isFastInfoset(rootContentType)) {
399 if (packet.contentNegotiation == ContentNegotiation.none) 350 if (packet.contentNegotiation == ContentNegotiation.none)
400 throw noFastInfosetForDecoding(); 351 throw noFastInfosetForDecoding();
401 352
433 b.equalsIgnoreCase( 384 b.equalsIgnoreCase(
434 a.substring(0, 385 a.substring(0,
435 b.length())); 386 b.length()));
436 } 387 }
437 388
438 private boolean isFastInfosetAcceptable(String accept) { 389 // private boolean isFastInfosetAcceptable(String accept) {
439 if (accept == null || isFastInfosetDisabled) return false; 390 // if (accept == null || isFastInfosetDisabled) return false;
440 391 //
441 StringTokenizer st = new StringTokenizer(accept, ","); 392 // StringTokenizer st = new StringTokenizer(accept, ",");
442 while (st.hasMoreTokens()) { 393 // while (st.hasMoreTokens()) {
443 final String token = st.nextToken().trim(); 394 // final String token = st.nextToken().trim();
444 if (token.equalsIgnoreCase(fiMimeType)) { 395 // if (token.equalsIgnoreCase(fiMimeType)) {
445 return true; 396 // return true;
446 } 397 // }
447 } 398 // }
448 return false; 399 // return false;
449 } 400 // }
450 401
451 /* 402 /*
452 * Just check if the Accept header contains application/xop+xml, 403 * Just check if the Accept header contains application/xop+xml,
453 * no need to worry about q values. 404 * no need to worry about q values.
454 */ 405 */
455 private boolean isMtomAcceptable(String accept) { 406 // private boolean isMtomAcceptable(String accept) {
456 if (accept == null || isFastInfosetDisabled) return false; 407 // if (accept == null || isFastInfosetDisabled) return false;
457 408 // StringTokenizer st = new StringTokenizer(accept, ",");
458 StringTokenizer st = new StringTokenizer(accept, ","); 409 // while (st.hasMoreTokens()) {
459 while (st.hasMoreTokens()) { 410 // final String token = st.nextToken().trim();
460 final String token = st.nextToken().trim(); 411 // if (token.toLowerCase().contains(MtomCodec.XOP_XML_MIME_TYPE)) {
461 if (token.toLowerCase().contains(MtomCodec.XOP_XML_MIME_TYPE)) { 412 // return true;
462 return true; 413 // }
463 } 414 // }
464 } 415 // return false;
465 return false; 416 // }
466 }
467 417
468 /** 418 /**
469 * Determines the encoding codec. 419 * Determines the encoding codec.
470 */ 420 */
471 private Codec getEncoder(Packet p) { 421 private Codec getEncoder(Packet p) {
493 return fiSoapCodec; 443 return fiSoapCodec;
494 else 444 else
495 return fiSwaCodec; 445 return fiSwaCodec;
496 } 446 }
497 447
498 if(features.isEnabled(MTOMFeature.class)) { 448 //If the packet does not have a binding, explicitly set the MTOMFeature
499 //On client, always use XOP encoding if MTOM is enabled 449 //on the packet so that it has a way to determine whether to use MTOM
500 // On Server, use XOP encoding if either request is XOP encoded or client accepts XOP encoding 450 if (p.getBinding() == null) {
501 if(!isServerSide() || isRequestMtomMessage || acceptMtomMessages) 451 if (features != null) {
502 return xmlMtomCodec; 452 p.setMtomFeature(features.get(MTOMFeature.class));
453 }
454 }
455
456 if (p.shouldUseMtom()) {
457 return xmlMtomCodec;
503 } 458 }
504 459
505 Message m = p.getMessage(); 460 Message m = p.getMessage();
506 if(m==null || m.getAttachments().isEmpty()) 461 if(m==null || m.getAttachments().isEmpty())
507 return xmlSoapCodec; 462 return xmlSoapCodec;

mercurial