src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/EndpointArgumentsBuilder.java

Wed, 27 Apr 2016 01:27:09 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:27:09 +0800
changeset 0
373ffda63c9a
child 637
9c07ef4934dd
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/jaxws/
changeset: 657:d47a47f961ee
tag: jdk8u25-b17

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

mercurial