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

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