diff -r 000000000000 -r 373ffda63c9a src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/BodyBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/client/sei/BodyBuilder.java Wed Apr 27 01:27:09 2016 +0800 @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.ws.client.sei; + +import com.sun.xml.internal.ws.api.SOAPVersion; +import com.sun.xml.internal.ws.api.message.Message; +import com.sun.xml.internal.ws.api.message.Messages; +import com.sun.xml.internal.ws.message.jaxb.JAXBMessage; +import com.sun.xml.internal.ws.model.ParameterImpl; +import com.sun.xml.internal.ws.model.WrapperParameter; +import com.sun.xml.internal.ws.spi.db.BindingContext; +import com.sun.xml.internal.ws.spi.db.XMLBridge; +import com.sun.xml.internal.ws.spi.db.PropertyAccessor; +import com.sun.xml.internal.ws.spi.db.WrapperComposite; + +import javax.xml.bind.JAXBException; +import javax.xml.namespace.QName; +import javax.xml.ws.Holder; +import javax.xml.ws.WebServiceException; +import java.util.List; + +/** + * Builds a JAXB object that represents the payload. + * + * @see MessageFiller + * @author Kohsuke Kawaguchi + */ +abstract class BodyBuilder { + abstract Message createMessage(Object[] methodArgs); + + static final BodyBuilder EMPTY_SOAP11 = new Empty(SOAPVersion.SOAP_11); + static final BodyBuilder EMPTY_SOAP12 = new Empty(SOAPVersion.SOAP_12); + + private static final class Empty extends BodyBuilder { + private final SOAPVersion soapVersion; + + public Empty(SOAPVersion soapVersion) { + this.soapVersion = soapVersion; + } + + Message createMessage(Object[] methodArgs) { + return Messages.createEmpty(soapVersion); + } + } + + /** + * Base class for those {@link BodyBuilder}s that build a {@link Message} + * from JAXB objects. + */ + private static abstract class JAXB extends BodyBuilder { + /** + * This object determines the binding of the object returned + * from {@link #build(Object[])}. + */ + private final XMLBridge bridge; + private final SOAPVersion soapVersion; + + protected JAXB(XMLBridge bridge, SOAPVersion soapVersion) { + assert bridge!=null; + this.bridge = bridge; + this.soapVersion = soapVersion; + } + + final Message createMessage(Object[] methodArgs) { + return JAXBMessage.create( bridge, build(methodArgs), soapVersion ); + } + + /** + * Builds a JAXB object that becomes the payload. + */ + abstract Object build(Object[] methodArgs); + } + + /** + * Used to create a payload JAXB object just by taking + * one of the parameters. + */ + final static class Bare extends JAXB { + /** + * The index of the method invocation parameters that goes into the payload. + */ + private final int methodPos; + + private final ValueGetter getter; + + /** + * Creates a {@link BodyBuilder} from a bare parameter. + */ + Bare(ParameterImpl p, SOAPVersion soapVersion, ValueGetter getter) { + super(p.getXMLBridge(), soapVersion); + this.methodPos = p.getIndex(); + this.getter = getter; + } + + /** + * Picks up an object from the method arguments and uses it. + */ + Object build(Object[] methodArgs) { + return getter.get(methodArgs[methodPos]); + } + } + + + /** + * Used to handle a 'wrapper' style request. + * Common part of rpc/lit and doc/lit. + */ + abstract static class Wrapped extends JAXB { + + /** + * Where in the method argument list do they come from? + */ + protected final int[] indices; + + /** + * Abstracts away the {@link Holder} handling when touching method arguments. + */ + protected final ValueGetter[] getters; + + /** + * How does each wrapped parameter binds to XML? + */ + protected XMLBridge[] parameterBridges; + + /** + * List of Parameters packed in the body. + * Only used for error diagnostics. + */ + protected List children; + + protected Wrapped(WrapperParameter wp, SOAPVersion soapVersion, ValueGetterFactory getter) { + super(wp.getXMLBridge(), soapVersion); + children = wp.getWrapperChildren(); + indices = new int[children.size()]; + getters = new ValueGetter[children.size()]; + for( int i=0; i=0; i-- ) { + Object arg = getters[i].get(methodArgs[indices[i]]); + if(arg==null) { + throw new WebServiceException("Method Parameter: "+ + children.get(i).getName()+" cannot be null. This is BP 1.1 R2211 violation."); + } + cs.values[i] = arg; + } + + return cs; + } + } + + /** + * Used to create a payload JAXB object by wrapping + * multiple parameters into one "wrapper bean". + */ + final static class DocLit extends Wrapped { + /** + * How does each wrapped parameter binds to XML? + */ + private final PropertyAccessor[] accessors; + + /** + * Wrapper bean. + */ + private final Class wrapper; + + /** + * Needed to get wrapper instantiation method. + */ + private BindingContext bindingContext; + private boolean dynamicWrapper; + + /** + * Creates a {@link BodyBuilder} from a {@link WrapperParameter}. + */ + DocLit(WrapperParameter wp, SOAPVersion soapVersion, ValueGetterFactory getter) { + super(wp, soapVersion, getter); + bindingContext = wp.getOwner().getBindingContext(); + wrapper = (Class)wp.getXMLBridge().getTypeInfo().type; + dynamicWrapper = WrapperComposite.class.equals(wrapper); + parameterBridges = new XMLBridge[children.size()]; + accessors = new PropertyAccessor[children.size()]; + for( int i=0; i=0; i-- ) { + accessors[i].set(bean,getters[i].get(methodArgs[indices[i]])); + } + + return bean; + } catch (InstantiationException e) { + // this is irrecoverable + Error x = new InstantiationError(e.getMessage()); + x.initCause(e); + throw x; + } catch (IllegalAccessException e) { + // this is irrecoverable + Error x = new IllegalAccessError(e.getMessage()); + x.initCause(e); + throw x; + } catch (com.sun.xml.internal.ws.spi.db.DatabindingException e) { + // this can happen when the set method throw a checked exception or something like that + throw new WebServiceException(e); // TODO:i18n + } + } + } + + + /** + * Used to create a payload JAXB object by wrapping + * multiple parameters into a {@link WrapperComposite}. + * + *

+ * This is used for rpc/lit, as we don't have a wrapper bean for it. + * (TODO: Why don't we have a wrapper bean for this, when doc/lit does!?) + */ + final static class RpcLit extends Wrapped { + + /** + * Creates a {@link BodyBuilder} from a {@link WrapperParameter}. + */ + RpcLit(WrapperParameter wp, SOAPVersion soapVersion, ValueGetterFactory getter) { + super(wp, soapVersion, getter); + // we'll use CompositeStructure to pack requests + assert wp.getTypeInfo().type==WrapperComposite.class; + + parameterBridges = new XMLBridge[children.size()]; + for( int i=0; i