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.server.sei; 27 28import com.sun.xml.internal.ws.api.SOAPVersion; 29import com.sun.xml.internal.ws.api.message.Attachment; 30import com.sun.xml.internal.ws.api.message.AttachmentSet; 31import com.sun.xml.internal.ws.api.message.Message; 32import com.sun.xml.internal.ws.api.model.ParameterBinding; 33import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory; 34import com.sun.xml.internal.ws.message.AttachmentUnmarshallerImpl; 35import com.sun.xml.internal.ws.model.ParameterImpl; 36import com.sun.xml.internal.ws.model.WrapperParameter; 37import com.sun.xml.internal.ws.resources.ServerMessages; 38import com.sun.xml.internal.ws.spi.db.RepeatedElementBridge; 39import com.sun.xml.internal.ws.spi.db.XMLBridge; 40import com.sun.xml.internal.ws.spi.db.DatabindingException; 41import com.sun.xml.internal.ws.spi.db.PropertyAccessor; 42import com.sun.xml.internal.ws.spi.db.WrapperComposite; 43import com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; 44import com.sun.xml.internal.ws.encoding.StringDataContentHandler; 45import com.sun.xml.internal.ws.encoding.DataHandlerDataSource; 46 47import javax.activation.DataHandler; 48import javax.imageio.ImageIO; 49import javax.jws.WebParam.Mode; 50import javax.xml.bind.JAXBException; 51import javax.xml.namespace.QName; 52import javax.xml.soap.SOAPException; 53import javax.xml.soap.SOAPFault; 54import javax.xml.stream.XMLStreamException; 55import javax.xml.stream.XMLStreamReader; 56import javax.xml.transform.Source; 57import javax.xml.ws.Holder; 58import javax.xml.ws.WebServiceException; 59import javax.xml.ws.soap.SOAPFaultException; 60import java.awt.Image; 61import java.io.IOException; 62import java.io.InputStream; 63import java.io.UnsupportedEncodingException; 64import java.lang.reflect.Type; 65import java.util.ArrayList; 66import java.util.Collection; 67import java.util.HashMap; 68import java.util.Iterator; 69import java.util.List; 70import java.util.Map; 71 72/** 73 * Reads a request {@link Message}, disassembles it, and moves obtained Java values 74 * to the expected places. 75 * 76 * @author Jitendra Kotamraju 77 */ 78public abstract class EndpointArgumentsBuilder { 79 /** 80 * Reads a request {@link Message}, disassembles it, and moves obtained 81 * Java values to the expected places. 82 * 83 * @param request 84 * The request {@link Message} to be de-composed. 85 * @param args 86 * The Java arguments given to the SEI method invocation. 87 * Some parts of the reply message may be set to {@link Holder}s in the arguments. 88 * @throws JAXBException 89 * if there's an error during unmarshalling the request message. 90 * @throws XMLStreamException 91 * if there's an error during unmarshalling the request message. 92 */ 93 public abstract void readRequest(Message request, Object[] args) 94 throws JAXBException, XMLStreamException; 95 96 static final class None extends EndpointArgumentsBuilder { 97 private None(){ 98 } 99 @Override 100 public void readRequest(Message msg, Object[] args) { 101 msg.consume(); 102 } 103 } 104 105 /** 106 * The singleton instance that produces null return value. 107 * Used for operations that doesn't have any output. 108 */ 109 public final static EndpointArgumentsBuilder NONE = new None(); 110 111 /** 112 * Returns the 'uninitialized' value for the given type. 113 * 114 * <p> 115 * For primitive types, it's '0', and for reference types, it's null. 116 */ 117 @SuppressWarnings("element-type-mismatch") 118 public static Object getVMUninitializedValue(Type type) { 119 // if this map returns null, that means the 'type' is a reference type, 120 // in which case 'null' is the correct null value, so this code is correct. 121 return primitiveUninitializedValues.get(type); 122 } 123 124 private static final Map<Class,Object> primitiveUninitializedValues = new HashMap<Class, Object>(); 125 126 static { 127 Map<Class, Object> m = primitiveUninitializedValues; 128 m.put(int.class,(int)0); 129 m.put(char.class,(char)0); 130 m.put(byte.class,(byte)0); 131 m.put(short.class,(short)0); 132 m.put(long.class,(long)0); 133 m.put(float.class,(float)0); 134 m.put(double.class,(double)0); 135 } 136 137 protected QName wrapperName; 138 139 static final class WrappedPartBuilder { 140 private final XMLBridge bridge; 141 private final EndpointValueSetter setter; 142 143 /** 144 * @param bridge 145 * specifies how the part is unmarshalled. 146 * @param setter 147 * specifies how the obtained value is returned to the endpoint. 148 */ 149 public WrappedPartBuilder(XMLBridge bridge, EndpointValueSetter setter) { 150 this.bridge = bridge; 151 this.setter = setter; 152 } 153 154 void readRequest( Object[] args, XMLStreamReader r, AttachmentSet att) throws JAXBException { 155 Object obj = null; 156 AttachmentUnmarshallerImpl au = (att != null)?new AttachmentUnmarshallerImpl(att):null; 157 if (bridge instanceof RepeatedElementBridge) { 158 RepeatedElementBridge rbridge = (RepeatedElementBridge)bridge; 159 ArrayList list = new ArrayList(); 160 QName name = r.getName(); 161 while (r.getEventType()==XMLStreamReader.START_ELEMENT && name.equals(r.getName())) { 162 list.add(rbridge.unmarshal(r, au)); 163 XMLStreamReaderUtil.toNextTag(r, name); 164 } 165 obj = rbridge.collectionHandler().convert(list); 166 } else { 167 obj = bridge.unmarshal(r, au); 168 } 169 setter.put(obj,args); 170 } 171 } 172 173 protected Map<QName,WrappedPartBuilder> wrappedParts = null; 174 175 protected void readWrappedRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException { 176 if (!msg.hasPayload()) { 177 throw new WebServiceException("No payload. Expecting payload with "+wrapperName+" element"); 178 } 179 XMLStreamReader reader = msg.readPayload(); 180 XMLStreamReaderUtil.verifyTag(reader,wrapperName); 181 reader.nextTag(); 182 while(reader.getEventType()==XMLStreamReader.START_ELEMENT) { 183 // TODO: QName has a performance issue 184 QName name = reader.getName(); 185 WrappedPartBuilder part = wrappedParts.get(name); 186 if(part==null) { 187 // no corresponding part found. ignore 188 XMLStreamReaderUtil.skipElement(reader); 189 reader.nextTag(); 190 } else { 191 part.readRequest(args,reader, msg.getAttachments()); 192 } 193 XMLStreamReaderUtil.toNextTag(reader, name); 194 } 195 196 // we are done with the body 197 reader.close(); 198 XMLStreamReaderFactory.recycle(reader); 199 } 200 201 /** 202 * {@link EndpointArgumentsBuilder} that sets the VM uninitialized value to the type. 203 */ 204 public static final class NullSetter extends EndpointArgumentsBuilder { 205 private final EndpointValueSetter setter; 206 private final Object nullValue; 207 208 public NullSetter(EndpointValueSetter setter, Object nullValue){ 209 assert setter!=null; 210 this.nullValue = nullValue; 211 this.setter = setter; 212 } 213 public void readRequest(Message msg, Object[] args) { 214 setter.put(nullValue, args); 215 } 216 } 217 218 /** 219 * {@link EndpointArgumentsBuilder} that is a composition of multiple 220 * {@link EndpointArgumentsBuilder}s. 221 * 222 * <p> 223 * Sometimes we need to look at multiple parts of the reply message 224 * (say, two header params, one body param, and three attachments, etc.) 225 * and that's when this object is used to combine multiple {@link EndpointArgumentsBuilder}s 226 * (that each responsible for handling one part). 227 * 228 * <p> 229 * The model guarantees that only at most one {@link EndpointArgumentsBuilder} will 230 * return a value as a return value (and everything else has to go to 231 * {@link Holder}s.) 232 */ 233 public static final class Composite extends EndpointArgumentsBuilder { 234 private final EndpointArgumentsBuilder[] builders; 235 236 public Composite(EndpointArgumentsBuilder... builders) { 237 this.builders = builders; 238 } 239 240 public Composite(Collection<? extends EndpointArgumentsBuilder> builders) { 241 this(builders.toArray(new EndpointArgumentsBuilder[builders.size()])); 242 } 243 244 public void readRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException { 245 for (EndpointArgumentsBuilder builder : builders) { 246 builder.readRequest(msg,args); 247 } 248 } 249 } 250 251 252 /** 253 * Reads an Attachment into a Java parameter. 254 */ 255 public static abstract class AttachmentBuilder extends EndpointArgumentsBuilder { 256 protected final EndpointValueSetter setter; 257 protected final ParameterImpl param; 258 protected final String pname; 259 protected final String pname1; 260 261 AttachmentBuilder(ParameterImpl param, EndpointValueSetter setter) { 262 this.setter = setter; 263 this.param = param; 264 this.pname = param.getPartName(); 265 this.pname1 = "<"+pname; 266 } 267 268 /** 269 * Creates an AttachmentBuilder based on the parameter type 270 * 271 * @param param 272 * runtime Parameter that abstracts the annotated java parameter 273 * @param setter 274 * specifies how the obtained value is set into the argument. Takes 275 * care of Holder arguments. 276 */ 277 public static EndpointArgumentsBuilder createAttachmentBuilder(ParameterImpl param, EndpointValueSetter setter) { 278 Class type = (Class)param.getTypeInfo().type; 279 if (DataHandler.class.isAssignableFrom(type)) { 280 return new DataHandlerBuilder(param, setter); 281 } else if (byte[].class==type) { 282 return new ByteArrayBuilder(param, setter); 283 } else if(Source.class.isAssignableFrom(type)) { 284 return new SourceBuilder(param, setter); 285 } else if(Image.class.isAssignableFrom(type)) { 286 return new ImageBuilder(param, setter); 287 } else if(InputStream.class==type) { 288 return new InputStreamBuilder(param, setter); 289 } else if(isXMLMimeType(param.getBinding().getMimeType())) { 290 return new JAXBBuilder(param, setter); 291 } else if(String.class.isAssignableFrom(type)) { 292 return new StringBuilder(param, setter); 293 } else { 294 throw new UnsupportedOperationException("Unknown Type="+type+" Attachment is not mapped."); 295 } 296 } 297 298 public void readRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException { 299 boolean foundAttachment = false; 300 // TODO not to loop 301 for (Attachment att : msg.getAttachments()) { 302 String part = getWSDLPartName(att); 303 if (part == null) { 304 continue; 305 } 306 if(part.equals(pname) || part.equals(pname1)){ 307 foundAttachment = true; 308 mapAttachment(att, args); 309 break; 310 } 311 } 312 if (!foundAttachment) { 313 throw new WebServiceException("Missing Attachment for "+pname); 314 } 315 } 316 317 abstract void mapAttachment(Attachment att, Object[] args) throws JAXBException; 318 } 319 320 private static final class DataHandlerBuilder extends AttachmentBuilder { 321 DataHandlerBuilder(ParameterImpl param, EndpointValueSetter setter) { 322 super(param, setter); 323 } 324 325 void mapAttachment(Attachment att, Object[] args) { 326 setter.put(att.asDataHandler(), args); 327 } 328 } 329 330 private static final class ByteArrayBuilder extends AttachmentBuilder { 331 ByteArrayBuilder(ParameterImpl param, EndpointValueSetter setter) { 332 super(param, setter); 333 } 334 335 void mapAttachment(Attachment att, Object[] args) { 336 setter.put(att.asByteArray(), args); 337 } 338 } 339 340 private static final class SourceBuilder extends AttachmentBuilder { 341 SourceBuilder(ParameterImpl param, EndpointValueSetter setter) { 342 super(param, setter); 343 } 344 345 void mapAttachment(Attachment att, Object[] args) { 346 setter.put(att.asSource(), args); 347 } 348 } 349 350 private static final class ImageBuilder extends AttachmentBuilder { 351 ImageBuilder(ParameterImpl param, EndpointValueSetter setter) { 352 super(param, setter); 353 } 354 355 void mapAttachment(Attachment att, Object[] args) { 356 Image image; 357 InputStream is = null; 358 try { 359 is = att.asInputStream(); 360 image = ImageIO.read(is); 361 } catch(IOException ioe) { 362 throw new WebServiceException(ioe); 363 } finally { 364 if (is != null) { 365 try { 366 is.close(); 367 } catch(IOException ioe) { 368 throw new WebServiceException(ioe); 369 } 370 } 371 } 372 setter.put(image, args); 373 } 374 } 375 376 private static final class InputStreamBuilder extends AttachmentBuilder { 377 InputStreamBuilder(ParameterImpl param, EndpointValueSetter setter) { 378 super(param, setter); 379 } 380 381 void mapAttachment(Attachment att, Object[] args) { 382 setter.put(att.asInputStream(), args); 383 } 384 } 385 386 private static final class JAXBBuilder extends AttachmentBuilder { 387 JAXBBuilder(ParameterImpl param, EndpointValueSetter setter) { 388 super(param, setter); 389 } 390 391 void mapAttachment(Attachment att, Object[] args) throws JAXBException { 392 Object obj = param.getXMLBridge().unmarshal(att.asInputStream()); 393 setter.put(obj, args); 394 } 395 } 396 397 private static final class StringBuilder extends AttachmentBuilder { 398 StringBuilder(ParameterImpl param, EndpointValueSetter setter) { 399 super(param, setter); 400 } 401 402 void mapAttachment(Attachment att, Object[] args) { 403 att.getContentType(); 404 StringDataContentHandler sdh = new StringDataContentHandler(); 405 try { 406 String str = (String)sdh.getContent(new DataHandlerDataSource(att.asDataHandler())); 407 setter.put(str, args); 408 } catch(Exception e) { 409 throw new WebServiceException(e); 410 } 411 } 412 } 413 414 /** 415 * Gets the WSDL part name of this attachment. 416 * 417 * <p> 418 * According to WSI AP 1.0 419 * <PRE> 420 * 3.8 Value-space of Content-Id Header 421 * Definition: content-id part encoding 422 * The "content-id part encoding" consists of the concatenation of: 423 * The value of the name attribute of the wsdl:part element referenced by the mime:content, in which characters disallowed in content-id headers (non-ASCII characters as represented by code points above 0x7F) are escaped as follows: 424 * o Each disallowed character is converted to UTF-8 as one or more bytes. 425 * o Any bytes corresponding to a disallowed character are escaped with the URI escaping mechanism (that is, converted to %HH, where HH is the hexadecimal notation of the byte value). 426 * o The original character is replaced by the resulting character sequence. 427 * The character '=' (0x3D). 428 * A globally unique value such as a UUID. 429 * The character '@' (0x40). 430 * A valid domain name under the authority of the entity constructing the message. 431 * </PRE> 432 * 433 * So a wsdl:part fooPart will be encoded as: 434 * <fooPart=somereallybignumberlikeauuid@example.com> 435 * 436 * @return null 437 * if the parsing fails. 438 */ 439 public static final String getWSDLPartName(com.sun.xml.internal.ws.api.message.Attachment att){ 440 String cId = att.getContentId(); 441 442 int index = cId.lastIndexOf('@', cId.length()); 443 if(index == -1){ 444 return null; 445 } 446 String localPart = cId.substring(0, index); 447 index = localPart.lastIndexOf('=', localPart.length()); 448 if(index == -1){ 449 return null; 450 } 451 try { 452 return java.net.URLDecoder.decode(localPart.substring(0, index), "UTF-8"); 453 } catch (UnsupportedEncodingException e) { 454 throw new WebServiceException(e); 455 } 456 } 457 458 459 460 461 /** 462 * Reads a header into a JAXB object. 463 */ 464 public static final class Header extends EndpointArgumentsBuilder { 465 private final XMLBridge<?> bridge; 466 private final EndpointValueSetter setter; 467 private final QName headerName; 468 private final SOAPVersion soapVersion; 469 470 /** 471 * @param name 472 * The name of the header element. 473 * @param bridge 474 * specifies how to unmarshal a header into a JAXB object. 475 * @param setter 476 * specifies how the obtained value is returned to the client. 477 */ 478 public Header(SOAPVersion soapVersion, QName name, XMLBridge<?> bridge, EndpointValueSetter setter) { 479 this.soapVersion = soapVersion; 480 this.headerName = name; 481 this.bridge = bridge; 482 this.setter = setter; 483 } 484 485 public Header(SOAPVersion soapVersion, ParameterImpl param, EndpointValueSetter setter) { 486 this( 487 soapVersion, 488 param.getTypeInfo().tagName, 489 param.getXMLBridge(), 490 setter); 491 assert param.getOutBinding()== ParameterBinding.HEADER; 492 } 493 494 private SOAPFaultException createDuplicateHeaderException() { 495 try { 496 SOAPFault fault = soapVersion.getSOAPFactory().createFault(); 497 fault.setFaultCode(soapVersion.faultCodeClient); 498 fault.setFaultString(ServerMessages.DUPLICATE_PORT_KNOWN_HEADER(headerName)); 499 return new SOAPFaultException(fault); 500 } catch(SOAPException e) { 501 throw new WebServiceException(e); 502 } 503 } 504 505 public void readRequest(Message msg, Object[] args) throws JAXBException { 506 com.sun.xml.internal.ws.api.message.Header header = null; 507 Iterator<com.sun.xml.internal.ws.api.message.Header> it = 508 msg.getHeaders().getHeaders(headerName,true); 509 if (it.hasNext()) { 510 header = it.next(); 511 if (it.hasNext()) { 512 throw createDuplicateHeaderException(); 513 } 514 } 515 516 if(header!=null) { 517 setter.put( header.readAsJAXB(bridge), args ); 518 } else { 519 // header not found. 520 } 521 } 522 } 523 524 /** 525 * Reads the whole payload into a single JAXB bean. 526 */ 527 public static final class Body extends EndpointArgumentsBuilder { 528 private final XMLBridge<?> bridge; 529 private final EndpointValueSetter setter; 530 531 /** 532 * @param bridge 533 * specifies how to unmarshal the payload into a JAXB object. 534 * @param setter 535 * specifies how the obtained value is returned to the client. 536 */ 537 public Body(XMLBridge<?> bridge, EndpointValueSetter setter) { 538 this.bridge = bridge; 539 this.setter = setter; 540 } 541 542 public void readRequest(Message msg, Object[] args) throws JAXBException { 543 setter.put( msg.readPayloadAsJAXB(bridge), args ); 544 } 545 } 546 547 /** 548 * Treats a payload as multiple parts wrapped into one element, 549 * and processes all such wrapped parts. 550 */ 551 public static final class DocLit extends EndpointArgumentsBuilder { 552 /** 553 * {@link PartBuilder} keyed by the element name (inside the wrapper element.) 554 */ 555 private final PartBuilder[] parts; 556 557 private final XMLBridge wrapper; 558 private boolean dynamicWrapper; 559 560 public DocLit(WrapperParameter wp, Mode skipMode) { 561 wrapperName = wp.getName(); 562 wrapper = wp.getXMLBridge(); 563 Class wrapperType = (Class) wrapper.getTypeInfo().type; 564 dynamicWrapper = WrapperComposite.class.equals(wrapperType); 565 List<PartBuilder> parts = new ArrayList<PartBuilder>(); 566 List<ParameterImpl> children = wp.getWrapperChildren(); 567 for (ParameterImpl p : children) { 568 if (p.getMode() == skipMode) { 569 continue; 570 } 571 /* 572 if(p.isIN()) 573 continue; 574 */ 575 QName name = p.getName(); 576 try { 577 if (dynamicWrapper) { 578 if (wrappedParts == null) wrappedParts = new HashMap<QName,WrappedPartBuilder>(); 579 XMLBridge xmlBridge = p.getInlinedRepeatedElementBridge(); 580 if (xmlBridge == null) xmlBridge = p.getXMLBridge(); 581 wrappedParts.put( p.getName(), new WrappedPartBuilder(xmlBridge, EndpointValueSetter.get(p))); 582 } else { 583 parts.add( new PartBuilder( 584 wp.getOwner().getBindingContext().getElementPropertyAccessor( 585 wrapperType, 586 name.getNamespaceURI(), 587 p.getName().getLocalPart()), 588 EndpointValueSetter.get(p) 589 ) ); 590 // wrapper parameter itself always bind to body, and 591 // so do all its children 592 assert p.getBinding()== ParameterBinding.BODY; 593 } 594 } catch (JAXBException e) { 595 throw new WebServiceException( // TODO: i18n 596 wrapperType+" do not have a property of the name "+name,e); 597 } 598 } 599 600 this.parts = parts.toArray(new PartBuilder[parts.size()]); 601 } 602 603 public void readRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException { 604 if (dynamicWrapper) { 605 readWrappedRequest(msg, args); 606 } else { 607 if (parts.length>0) { 608 if (!msg.hasPayload()) { 609 throw new WebServiceException("No payload. Expecting payload with "+wrapperName+" element"); 610 } 611 XMLStreamReader reader = msg.readPayload(); 612 XMLStreamReaderUtil.verifyTag(reader, wrapperName); 613 Object wrapperBean = wrapper.unmarshal(reader, (msg.getAttachments() != null) ? 614 new AttachmentUnmarshallerImpl(msg.getAttachments()): null); 615 616 try { 617 for (PartBuilder part : parts) { 618 part.readRequest(args,wrapperBean); 619 } 620 } catch (DatabindingException e) { 621 // this can happen when the set method throw a checked exception or something like that 622 throw new WebServiceException(e); // TODO:i18n 623 } 624 625 // we are done with the body 626 reader.close(); 627 XMLStreamReaderFactory.recycle(reader); 628 } else { 629 msg.consume(); 630 } 631 } 632 } 633 634 /** 635 * Unmarshals each wrapped part into a JAXB object and moves it 636 * to the expected place. 637 */ 638 static final class PartBuilder { 639 private final PropertyAccessor accessor; 640 private final EndpointValueSetter setter; 641 642 /** 643 * @param accessor 644 * specifies which portion of the wrapper bean to obtain the value from. 645 * @param setter 646 * specifies how the obtained value is returned to the client. 647 */ 648 public PartBuilder(PropertyAccessor accessor, EndpointValueSetter setter) { 649 this.accessor = accessor; 650 this.setter = setter; 651 assert accessor!=null && setter!=null; 652 } 653 654 final void readRequest( Object[] args, Object wrapperBean ) { 655 Object obj = accessor.get(wrapperBean); 656 setter.put(obj,args); 657 } 658 659 660 } 661 } 662 663 /** 664 * Treats a payload as multiple parts wrapped into one element, 665 * and processes all such wrapped parts. 666 */ 667 public static final class RpcLit extends EndpointArgumentsBuilder { 668 public RpcLit(WrapperParameter wp) { 669 assert wp.getTypeInfo().type== WrapperComposite.class; 670 671 wrapperName = wp.getName(); 672 wrappedParts = new HashMap<QName,WrappedPartBuilder>(); 673 List<ParameterImpl> children = wp.getWrapperChildren(); 674 for (ParameterImpl p : children) { 675 wrappedParts.put( p.getName(), new WrappedPartBuilder( 676 p.getXMLBridge(), EndpointValueSetter.get(p) 677 )); 678 // wrapper parameter itself always bind to body, and 679 // so do all its children 680 assert p.getBinding()== ParameterBinding.BODY; 681 } 682 } 683 684 public void readRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException { 685 readWrappedRequest(msg, args); 686 } 687 } 688 689 private static boolean isXMLMimeType(String mimeType){ 690 return mimeType.equals("text/xml") || mimeType.equals("application/xml"); 691 } 692} 693