Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
1 /*
2 * Copyright (c) 1997, 2011, 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 */
26 package com.sun.xml.internal.ws.server.sei;
28 import com.sun.xml.internal.ws.api.SOAPVersion;
29 import com.sun.xml.internal.ws.api.WSBinding;
30 import com.sun.xml.internal.ws.api.databinding.EndpointCallBridge;
31 import com.sun.xml.internal.ws.api.databinding.JavaCallInfo;
32 import com.sun.xml.internal.ws.api.message.Message;
33 import com.sun.xml.internal.ws.api.message.Packet;
34 import com.sun.xml.internal.ws.api.model.JavaMethod;
35 import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
36 import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
37 import com.sun.xml.internal.ws.model.JavaMethodImpl;
38 import com.sun.xml.internal.ws.model.ParameterImpl;
39 import com.sun.xml.internal.ws.model.WrapperParameter;
40 import com.sun.xml.internal.ws.wsdl.DispatchException;
42 import javax.jws.WebParam.Mode;
43 import javax.xml.bind.JAXBException;
44 import javax.xml.stream.XMLStreamException;
45 import javax.xml.ws.Holder;
46 import javax.xml.ws.ProtocolException;
47 import javax.xml.ws.WebServiceException;
48 import java.lang.reflect.InvocationTargetException;
49 import java.lang.reflect.Method;
50 import java.util.ArrayList;
51 import java.util.List;
52 import java.util.logging.Level;
53 import java.util.logging.Logger;
55 /**
56 *
57 * <p>
58 * This class mainly performs the following two tasks:
59 * <ol>
60 * <li>Takes a {@link Message] that represents a request,
61 * and extracts the arguments (and updates {@link Holder}s.)
62 * <li>Accepts return value and {@link Holder} arguments for a Java method,
63 * and creates {@link JAXBMessage} that represents a response message.
64 * </ol>
65 *
66 * <h2>Creating {@link JAXBMessage}</h2>
67 * <p>
68 * At the construction time, we prepare {@link EndpointArgumentsBuilder} that knows how to create endpoint {@link Method}
69 * invocation arguments.
70 * we also prepare {@link EndpointResponseMessageBuilder} and {@link MessageFiller}s
71 * that know how to move arguments into a {@link Message}.
72 * Some arguments go to the payload, some go to headers, still others go to attachments.
73 *
74 * @author Jitendra Kotamraju
75 * @author shih-chang.chen@oracle.com
76 * Refactored from EndpointMethodHandler
77 */
78 final public class TieHandler implements EndpointCallBridge {
80 private final SOAPVersion soapVersion;
81 private final Method method;
82 private final int noOfArgs;
83 private final JavaMethodImpl javaMethodModel;
85 private final Boolean isOneWay;
87 // Converts {@link Message} --> Object[]
88 private final EndpointArgumentsBuilder argumentsBuilder;
90 // these objects together create a response message from method parameters
91 private final EndpointResponseMessageBuilder bodyBuilder;
92 private final MessageFiller[] outFillers;
94 public TieHandler(JavaMethodImpl method, WSBinding binding) {
95 this.soapVersion = binding.getSOAPVersion();
96 this.method = method.getMethod();
97 this.javaMethodModel = method;
98 argumentsBuilder = createArgumentsBuilder();
99 List<MessageFiller> fillers = new ArrayList<MessageFiller>();
100 bodyBuilder = createResponseMessageBuilder(fillers);
101 this.outFillers = fillers.toArray(new MessageFiller[fillers.size()]);
102 this.isOneWay = method.getMEP().isOneWay();
103 this.noOfArgs = this.method.getParameterTypes().length;
104 }
106 /**
107 * It builds EndpointArgumentsBuilder which converts request {@link Message} to endpoint method's invocation
108 * arguments Object[]
109 *
110 * @return EndpointArgumentsBuilder
111 */
112 private EndpointArgumentsBuilder createArgumentsBuilder() {
113 EndpointArgumentsBuilder argsBuilder;
114 List<ParameterImpl> rp = javaMethodModel.getRequestParameters();
115 List<EndpointArgumentsBuilder> builders = new ArrayList<EndpointArgumentsBuilder>();
117 for( ParameterImpl param : rp ) {
118 EndpointValueSetter setter = EndpointValueSetter.get(param);
119 switch(param.getInBinding().kind) {
120 case BODY:
121 if(param.isWrapperStyle()) {
122 if(param.getParent().getBinding().isRpcLit())
123 builders.add(new EndpointArgumentsBuilder.RpcLit((WrapperParameter)param));
124 else
125 builders.add(new EndpointArgumentsBuilder.DocLit((WrapperParameter)param, Mode.OUT));
126 } else {
127 builders.add(new EndpointArgumentsBuilder.Body(param.getXMLBridge(),setter));
128 }
129 break;
130 case HEADER:
131 builders.add(new EndpointArgumentsBuilder.Header(soapVersion, param, setter));
132 break;
133 case ATTACHMENT:
134 builders.add(EndpointArgumentsBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter));
135 break;
136 case UNBOUND:
137 builders.add(new EndpointArgumentsBuilder.NullSetter(setter,
138 EndpointArgumentsBuilder.getVMUninitializedValue(param.getTypeInfo().type)));
139 break;
140 default:
141 throw new AssertionError();
142 }
143 }
145 // creates {@link Holder} arguments for OUT parameters
146 List<ParameterImpl> resp = javaMethodModel.getResponseParameters();
147 for( ParameterImpl param : resp ) {
148 if (param.isWrapperStyle()) {
149 WrapperParameter wp = (WrapperParameter)param;
150 List<ParameterImpl> children = wp.getWrapperChildren();
151 for (ParameterImpl p : children) {
152 if (p.isOUT() && p.getIndex() != -1) {
153 EndpointValueSetter setter = EndpointValueSetter.get(p);
154 builders.add(new EndpointArgumentsBuilder.NullSetter(setter, null));
155 }
156 }
157 } else if (param.isOUT() && param.getIndex() != -1) {
158 EndpointValueSetter setter = EndpointValueSetter.get(param);
159 builders.add(new EndpointArgumentsBuilder.NullSetter(setter, null));
160 }
161 }
163 switch(builders.size()) {
164 case 0:
165 argsBuilder = EndpointArgumentsBuilder.NONE;
166 break;
167 case 1:
168 argsBuilder = builders.get(0);
169 break;
170 default:
171 argsBuilder = new EndpointArgumentsBuilder.Composite(builders);
172 }
173 return argsBuilder;
174 }
176 /**
177 * prepare objects for creating response {@link Message}
178 */
179 private EndpointResponseMessageBuilder createResponseMessageBuilder(List<MessageFiller> fillers) {
181 EndpointResponseMessageBuilder bodyBuilder = null;
182 List<ParameterImpl> rp = javaMethodModel.getResponseParameters();
184 for (ParameterImpl param : rp) {
185 ValueGetter getter = ValueGetter.get(param);
187 switch(param.getOutBinding().kind) {
188 case BODY:
189 if(param.isWrapperStyle()) {
190 if(param.getParent().getBinding().isRpcLit()) {
191 bodyBuilder = new EndpointResponseMessageBuilder.RpcLit((WrapperParameter)param,
192 soapVersion);
193 } else {
194 bodyBuilder = new EndpointResponseMessageBuilder.DocLit((WrapperParameter)param,
195 soapVersion);
196 }
197 } else {
198 bodyBuilder = new EndpointResponseMessageBuilder.Bare(param, soapVersion);
199 }
200 break;
201 case HEADER:
202 fillers.add(new MessageFiller.Header(param.getIndex(), param.getXMLBridge(), getter ));
203 break;
204 case ATTACHMENT:
205 fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter));
206 break;
207 case UNBOUND:
208 break;
209 default:
210 throw new AssertionError(); // impossible
211 }
212 }
214 if (bodyBuilder == null) {
215 // no parameter binds to body. we create an empty message
216 switch(soapVersion) {
217 case SOAP_11:
218 bodyBuilder = EndpointResponseMessageBuilder.EMPTY_SOAP11;
219 break;
220 case SOAP_12:
221 bodyBuilder = EndpointResponseMessageBuilder.EMPTY_SOAP12;
222 break;
223 default:
224 throw new AssertionError();
225 }
226 }
227 return bodyBuilder;
228 }
230 public Object[] readRequest(Message reqMsg) {
231 Object[] args = new Object[noOfArgs];
232 try {
233 argumentsBuilder.readRequest(reqMsg,args);
234 } catch (JAXBException e) {
235 throw new WebServiceException(e);
236 } catch (XMLStreamException e) {
237 throw new WebServiceException(e);
238 }
239 return args;
240 }
242 public Message createResponse(JavaCallInfo call) {
243 Message responseMessage;
244 Object ret = call.getReturnValue();
245 if (call.getException() == null) {
246 responseMessage = isOneWay ? null : createResponseMessage(call.getParameters(), call.getReturnValue());
247 } else {
248 Throwable e = call.getException();
249 Throwable serviceException = getServiceException(e);
250 if (e instanceof InvocationTargetException || serviceException != null) {
251 // Throwable cause = e.getCause();
252 //if (!(cause instanceof RuntimeException) && cause instanceof Exception) {
253 if (serviceException != null) {
254 // Service specific exception
255 LOGGER.log(Level.FINE, serviceException.getMessage(), serviceException);
256 responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion,
257 javaMethodModel.getCheckedException(serviceException.getClass()), serviceException);
258 } else {
259 Throwable cause = e.getCause();
260 if (cause instanceof ProtocolException) {
261 // Application code may be throwing it intentionally
262 LOGGER.log(Level.FINE, cause.getMessage(), cause);
263 } else {
264 // Probably some bug in application code
265 LOGGER.log(Level.SEVERE, cause.getMessage(), cause);
266 }
267 responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, cause);
268 }
269 } else if (e instanceof DispatchException) {
270 responseMessage = ((DispatchException)e).fault;
271 } else {
272 LOGGER.log(Level.SEVERE, e.getMessage(), e);
273 responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, e);
274 }
275 }
276 // return req.createServerResponse(responseMessage, req.endpoint.getPort(), javaMethodModel.getOwner(), req.endpoint.getBinding());
278 return responseMessage;
279 }
281 Throwable getServiceException(Throwable throwable) {
282 if (javaMethodModel.getCheckedException(throwable.getClass()) != null) return throwable;
283 if (throwable.getCause() != null) {
284 Throwable cause = throwable.getCause();
285 // if (!(cause instanceof RuntimeException) && cause instanceof Exception) {
286 if (javaMethodModel.getCheckedException(cause.getClass()) != null) return cause;
287 // }
288 // if (javaMethodModel.getCheckedException(cause.getClass()) != null) return cause;
289 }
290 return null;
291 }
293 /**
294 * Creates a response {@link JAXBMessage} from method arguments, return value
295 *
296 * @return response message
297 */
298 private Message createResponseMessage(Object[] args, Object returnValue) {
299 Message msg = bodyBuilder.createMessage(args, returnValue);
301 for (MessageFiller filler : outFillers)
302 filler.fillIn(args, returnValue, msg);
304 return msg;
305 }
307 public Method getMethod() {
308 return method;
309 }
311 private static final Logger LOGGER = Logger.getLogger(TieHandler.class.getName());
313 public JavaCallInfo deserializeRequest(Packet req) {
314 JavaCallInfo call = new JavaCallInfo();
315 call.setMethod(this.getMethod());
316 Object[] args = this.readRequest(req.getMessage());
317 call.setParameters(args);
318 return call;
319 }
321 public Packet serializeResponse(JavaCallInfo call) {
322 Message msg = this.createResponse(call);
323 Packet response = new Packet();
324 response.setMessage(msg);
325 return response;
326 }
328 public JavaMethod getOperationModel() {
329 return javaMethodModel;
330 }
331 }