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

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