SEIMethodHandler.java revision 524:dcaa586ab756
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.message.Message; 29import com.sun.xml.internal.ws.model.CheckedExceptionImpl; 30import com.sun.xml.internal.ws.model.JavaMethodImpl; 31import com.sun.xml.internal.ws.model.ParameterImpl; 32import com.sun.xml.internal.ws.model.WrapperParameter; 33 34import javax.xml.namespace.QName; 35import java.util.ArrayList; 36import java.util.HashMap; 37import java.util.List; 38import java.util.Map; 39 40/** 41 * {@link com.sun.xml.internal.ws.client.sei.MethodHandler} that handles synchronous method invocations. 42 * 43 * <p> 44 * This class mainly performs the following two tasks: 45 * <ol> 46 * <li>Accepts Object[] that represents arguments for a Java method, 47 * and creates {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} that represents a request message. 48 * <li>Takes a {@link com.sun.xml.internal.ws.api.message.Message] that represents a response, 49 * and extracts the return value (and updates {@link javax.xml.ws.Holder }s.) 50 * </ol> 51 * 52 * <h2>Creating {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage }</h2> 53 * <p> 54 * At the construction time, we prepare {@link com.sun.xml.internal.ws.client.sei.BodyBuilder} and {@link com.sun.xml.internal.ws.client.sei.MessageFiller}s 55 * that know how to move arguments into a {@link com.sun.xml.internal.ws.api.message.Message }. 56 * Some arguments go to the payload, some go to headers, still others go to attachments. 57 * 58 * @author Kohsuke Kawaguchi 59 * @author Jitendra Kotamraju 60 */ 61abstract class SEIMethodHandler extends MethodHandler { 62 63 // these objects together create a message from method parameters 64 private BodyBuilder bodyBuilder; 65 private MessageFiller[] inFillers; 66 67 protected String soapAction; 68 69 protected boolean isOneWay; 70 71 protected JavaMethodImpl javaMethod; 72 73 protected Map<QName, CheckedExceptionImpl> checkedExceptions; 74 75 SEIMethodHandler(SEIStub owner) { 76 super(owner, null); 77 } 78 79 SEIMethodHandler(SEIStub owner, JavaMethodImpl method) { 80 super(owner, null); 81 82 //keep all the CheckedException model for the detail qname 83 this.checkedExceptions = new HashMap<QName, CheckedExceptionImpl>(); 84 for(CheckedExceptionImpl ce : method.getCheckedExceptions()){ 85 checkedExceptions.put(ce.getBond().getTypeInfo().tagName, ce); 86 } 87 //If a non-"" soapAction is specified, wsa:action the SOAPAction 88 if(method.getInputAction() != null && !method.getBinding().getSOAPAction().equals("") ) { 89 this.soapAction = method.getInputAction(); 90 } else { 91 this.soapAction = method.getBinding().getSOAPAction(); 92 } 93 this.javaMethod = method; 94 95 {// prepare objects for creating messages 96 List<ParameterImpl> rp = method.getRequestParameters(); 97 98 BodyBuilder tmpBodyBuilder = null; 99 List<MessageFiller> fillers = new ArrayList<MessageFiller>(); 100 101 for (ParameterImpl param : rp) { 102 ValueGetter getter = getValueGetterFactory().get(param); 103 104 switch(param.getInBinding().kind) { 105 case BODY: 106 if(param.isWrapperStyle()) { 107 if(param.getParent().getBinding().isRpcLit()) 108 tmpBodyBuilder = new BodyBuilder.RpcLit((WrapperParameter)param, owner.soapVersion, getValueGetterFactory()); 109 else 110 tmpBodyBuilder = new BodyBuilder.DocLit((WrapperParameter)param, owner.soapVersion, getValueGetterFactory()); 111 } else { 112 tmpBodyBuilder = new BodyBuilder.Bare(param, owner.soapVersion, getter); 113 } 114 break; 115 case HEADER: 116 fillers.add(new MessageFiller.Header( 117 param.getIndex(), 118 param.getXMLBridge(), 119 getter )); 120 break; 121 case ATTACHMENT: 122 fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter)); 123 break; 124 case UNBOUND: 125 break; 126 default: 127 throw new AssertionError(); // impossible 128 } 129 } 130 131 if(tmpBodyBuilder==null) { 132 // no parameter binds to body. we create an empty message 133 switch(owner.soapVersion) { 134 case SOAP_11: 135 tmpBodyBuilder = BodyBuilder.EMPTY_SOAP11; 136 break; 137 case SOAP_12: 138 tmpBodyBuilder = BodyBuilder.EMPTY_SOAP12; 139 break; 140 default: 141 throw new AssertionError(); 142 } 143 } 144 145 this.bodyBuilder = tmpBodyBuilder; 146 this.inFillers = fillers.toArray(new MessageFiller[fillers.size()]); 147 } 148 149 this.isOneWay = method.getMEP().isOneWay(); 150 } 151 152 ResponseBuilder buildResponseBuilder(JavaMethodImpl method, ValueSetterFactory setterFactory) { 153 // prepare objects for processing response 154 List<ParameterImpl> rp = method.getResponseParameters(); 155 List<ResponseBuilder> builders = new ArrayList<ResponseBuilder>(); 156 157 for( ParameterImpl param : rp ) { 158 ValueSetter setter; 159 switch(param.getOutBinding().kind) { 160 case BODY: 161 if(param.isWrapperStyle()) { 162 if(param.getParent().getBinding().isRpcLit()) 163 builders.add(new ResponseBuilder.RpcLit((WrapperParameter)param, setterFactory)); 164 else 165 builders.add(new ResponseBuilder.DocLit((WrapperParameter)param, setterFactory)); 166 } else { 167 setter = setterFactory.get(param); 168 builders.add(new ResponseBuilder.Body(param.getXMLBridge(),setter)); 169 } 170 break; 171 case HEADER: 172 setter = setterFactory.get(param); 173 builders.add(new ResponseBuilder.Header(owner.soapVersion, param, setter)); 174 break; 175 case ATTACHMENT: 176 setter = setterFactory.get(param); 177 builders.add(ResponseBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter)); 178 break; 179 case UNBOUND: 180 setter = setterFactory.get(param); 181 builders.add(new ResponseBuilder.NullSetter(setter, 182 ResponseBuilder.getVMUninitializedValue(param.getTypeInfo().type))); 183 break; 184 default: 185 throw new AssertionError(); 186 } 187 } 188 ResponseBuilder rb; 189 switch(builders.size()) { 190 case 0: 191 rb = ResponseBuilder.NONE; 192 break; 193 case 1: 194 rb = builders.get(0); 195 break; 196 default: 197 rb = new ResponseBuilder.Composite(builders); 198 } 199 return rb; 200 } 201 202 203 /** 204 * Creates a request {@link com.sun.xml.internal.ws.message.jaxb.JAXBMessage} from method arguments. 205 * @param args proxy invocation arguments 206 * @return Message for the arguments 207 */ 208 Message createRequestMessage(Object[] args) { 209 Message msg = bodyBuilder.createMessage(args); 210 211 for (MessageFiller filler : inFillers) 212 filler.fillIn(args,msg); 213 214 return msg; 215 } 216 217 abstract ValueGetterFactory getValueGetterFactory(); 218 219} 220