View Javadoc
1   /*
2    * Copyright (c) 1997, 2012, 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  
26  package com.sun.xml.internal.ws.client.sei;
27  
28  import com.sun.xml.internal.ws.api.message.Message;
29  import com.sun.xml.internal.ws.model.CheckedExceptionImpl;
30  import com.sun.xml.internal.ws.model.JavaMethodImpl;
31  import com.sun.xml.internal.ws.model.ParameterImpl;
32  import com.sun.xml.internal.ws.model.WrapperParameter;
33  
34  import javax.xml.namespace.QName;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import 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   */
61  abstract 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 }