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