1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/TieHandler.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,336 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.server.sei; 1.30 + 1.31 +import com.oracle.webservices.internal.api.databinding.JavaCallInfo; 1.32 +import com.sun.xml.internal.ws.api.SOAPVersion; 1.33 +import com.sun.xml.internal.ws.api.WSBinding; 1.34 +import com.sun.xml.internal.ws.api.databinding.EndpointCallBridge; 1.35 +import com.sun.xml.internal.ws.api.message.Message; 1.36 +import com.sun.xml.internal.ws.api.message.MessageContextFactory; 1.37 +import com.sun.xml.internal.ws.api.message.Packet; 1.38 +import com.sun.xml.internal.ws.api.model.JavaMethod; 1.39 +import com.sun.xml.internal.ws.fault.SOAPFaultBuilder; 1.40 +import com.sun.xml.internal.ws.message.jaxb.JAXBMessage; 1.41 +import com.sun.xml.internal.ws.model.JavaMethodImpl; 1.42 +import com.sun.xml.internal.ws.model.ParameterImpl; 1.43 +import com.sun.xml.internal.ws.model.WrapperParameter; 1.44 +import com.sun.xml.internal.ws.wsdl.DispatchException; 1.45 + 1.46 +import javax.jws.WebParam.Mode; 1.47 +import javax.xml.bind.JAXBException; 1.48 +import javax.xml.stream.XMLStreamException; 1.49 +import javax.xml.ws.Holder; 1.50 +import javax.xml.ws.ProtocolException; 1.51 +import javax.xml.ws.WebServiceException; 1.52 +import java.lang.reflect.InvocationTargetException; 1.53 +import java.lang.reflect.Method; 1.54 +import java.util.ArrayList; 1.55 +import java.util.List; 1.56 +import java.util.logging.Level; 1.57 +import java.util.logging.Logger; 1.58 + 1.59 +/** 1.60 + * 1.61 + * <p> 1.62 + * This class mainly performs the following two tasks: 1.63 + * <ol> 1.64 + * <li>Takes a {@link Message} that represents a request, 1.65 + * and extracts the arguments (and updates {@link Holder}s.) 1.66 + * <li>Accepts return value and {@link Holder} arguments for a Java method, 1.67 + * and creates {@link JAXBMessage} that represents a response message. 1.68 + * </ol> 1.69 + * 1.70 + * <h2>Creating {@link JAXBMessage}</h2> 1.71 + * <p> 1.72 + * At the construction time, we prepare {@link EndpointArgumentsBuilder} that knows how to create endpoint {@link Method} 1.73 + * invocation arguments. 1.74 + * we also prepare {@link EndpointResponseMessageBuilder} and {@link MessageFiller}s 1.75 + * that know how to move arguments into a {@link Message}. 1.76 + * Some arguments go to the payload, some go to headers, still others go to attachments. 1.77 + * 1.78 + * @author Jitendra Kotamraju 1.79 + * @author shih-chang.chen@oracle.com 1.80 + * Refactored from EndpointMethodHandler 1.81 + */ 1.82 +final public class TieHandler implements EndpointCallBridge { 1.83 + 1.84 + private final SOAPVersion soapVersion; 1.85 + private final Method method; 1.86 + private final int noOfArgs; 1.87 + private final JavaMethodImpl javaMethodModel; 1.88 + 1.89 + private final Boolean isOneWay; 1.90 + 1.91 + // Converts {@link Message} --> Object[] 1.92 + private final EndpointArgumentsBuilder argumentsBuilder; 1.93 + 1.94 + // these objects together create a response message from method parameters 1.95 + private final EndpointResponseMessageBuilder bodyBuilder; 1.96 + private final MessageFiller[] outFillers; 1.97 + protected MessageContextFactory packetFactory; 1.98 + 1.99 + public TieHandler(JavaMethodImpl method, WSBinding binding, MessageContextFactory mcf) { 1.100 + this.soapVersion = binding.getSOAPVersion(); 1.101 + this.method = method.getMethod(); 1.102 + this.javaMethodModel = method; 1.103 + argumentsBuilder = createArgumentsBuilder(); 1.104 + List<MessageFiller> fillers = new ArrayList<MessageFiller>(); 1.105 + bodyBuilder = createResponseMessageBuilder(fillers); 1.106 + this.outFillers = fillers.toArray(new MessageFiller[fillers.size()]); 1.107 + this.isOneWay = method.getMEP().isOneWay(); 1.108 + this.noOfArgs = this.method.getParameterTypes().length; 1.109 + packetFactory = mcf; 1.110 + } 1.111 + 1.112 + /** 1.113 + * It builds EndpointArgumentsBuilder which converts request {@link Message} to endpoint method's invocation 1.114 + * arguments Object[] 1.115 + * 1.116 + * @return EndpointArgumentsBuilder 1.117 + */ 1.118 + private EndpointArgumentsBuilder createArgumentsBuilder() { 1.119 + EndpointArgumentsBuilder argsBuilder; 1.120 + List<ParameterImpl> rp = javaMethodModel.getRequestParameters(); 1.121 + List<EndpointArgumentsBuilder> builders = new ArrayList<EndpointArgumentsBuilder>(); 1.122 + 1.123 + for( ParameterImpl param : rp ) { 1.124 + EndpointValueSetter setter = EndpointValueSetter.get(param); 1.125 + switch(param.getInBinding().kind) { 1.126 + case BODY: 1.127 + if(param.isWrapperStyle()) { 1.128 + if(param.getParent().getBinding().isRpcLit()) 1.129 + builders.add(new EndpointArgumentsBuilder.RpcLit((WrapperParameter)param)); 1.130 + else 1.131 + builders.add(new EndpointArgumentsBuilder.DocLit((WrapperParameter)param, Mode.OUT)); 1.132 + } else { 1.133 + builders.add(new EndpointArgumentsBuilder.Body(param.getXMLBridge(),setter)); 1.134 + } 1.135 + break; 1.136 + case HEADER: 1.137 + builders.add(new EndpointArgumentsBuilder.Header(soapVersion, param, setter)); 1.138 + break; 1.139 + case ATTACHMENT: 1.140 + builders.add(EndpointArgumentsBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter)); 1.141 + break; 1.142 + case UNBOUND: 1.143 + builders.add(new EndpointArgumentsBuilder.NullSetter(setter, 1.144 + EndpointArgumentsBuilder.getVMUninitializedValue(param.getTypeInfo().type))); 1.145 + break; 1.146 + default: 1.147 + throw new AssertionError(); 1.148 + } 1.149 + } 1.150 + 1.151 + // creates {@link Holder} arguments for OUT parameters 1.152 + List<ParameterImpl> resp = javaMethodModel.getResponseParameters(); 1.153 + for( ParameterImpl param : resp ) { 1.154 + if (param.isWrapperStyle()) { 1.155 + WrapperParameter wp = (WrapperParameter)param; 1.156 + List<ParameterImpl> children = wp.getWrapperChildren(); 1.157 + for (ParameterImpl p : children) { 1.158 + if (p.isOUT() && p.getIndex() != -1) { 1.159 + EndpointValueSetter setter = EndpointValueSetter.get(p); 1.160 + builders.add(new EndpointArgumentsBuilder.NullSetter(setter, null)); 1.161 + } 1.162 + } 1.163 + } else if (param.isOUT() && param.getIndex() != -1) { 1.164 + EndpointValueSetter setter = EndpointValueSetter.get(param); 1.165 + builders.add(new EndpointArgumentsBuilder.NullSetter(setter, null)); 1.166 + } 1.167 + } 1.168 + 1.169 + switch(builders.size()) { 1.170 + case 0: 1.171 + argsBuilder = EndpointArgumentsBuilder.NONE; 1.172 + break; 1.173 + case 1: 1.174 + argsBuilder = builders.get(0); 1.175 + break; 1.176 + default: 1.177 + argsBuilder = new EndpointArgumentsBuilder.Composite(builders); 1.178 + } 1.179 + return argsBuilder; 1.180 + } 1.181 + 1.182 + /** 1.183 + * prepare objects for creating response {@link Message} 1.184 + */ 1.185 + private EndpointResponseMessageBuilder createResponseMessageBuilder(List<MessageFiller> fillers) { 1.186 + 1.187 + EndpointResponseMessageBuilder tmpBodyBuilder = null; 1.188 + List<ParameterImpl> rp = javaMethodModel.getResponseParameters(); 1.189 + 1.190 + for (ParameterImpl param : rp) { 1.191 + ValueGetter getter = ValueGetter.get(param); 1.192 + 1.193 + switch(param.getOutBinding().kind) { 1.194 + case BODY: 1.195 + if(param.isWrapperStyle()) { 1.196 + if(param.getParent().getBinding().isRpcLit()) { 1.197 + tmpBodyBuilder = new EndpointResponseMessageBuilder.RpcLit((WrapperParameter)param, 1.198 + soapVersion); 1.199 + } else { 1.200 + tmpBodyBuilder = new EndpointResponseMessageBuilder.DocLit((WrapperParameter)param, 1.201 + soapVersion); 1.202 + } 1.203 + } else { 1.204 + tmpBodyBuilder = new EndpointResponseMessageBuilder.Bare(param, soapVersion); 1.205 + } 1.206 + break; 1.207 + case HEADER: 1.208 + fillers.add(new MessageFiller.Header(param.getIndex(), param.getXMLBridge(), getter )); 1.209 + break; 1.210 + case ATTACHMENT: 1.211 + fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter)); 1.212 + break; 1.213 + case UNBOUND: 1.214 + break; 1.215 + default: 1.216 + throw new AssertionError(); // impossible 1.217 + } 1.218 + } 1.219 + 1.220 + if (tmpBodyBuilder == null) { 1.221 + // no parameter binds to body. we create an empty message 1.222 + switch(soapVersion) { 1.223 + case SOAP_11: 1.224 + tmpBodyBuilder = EndpointResponseMessageBuilder.EMPTY_SOAP11; 1.225 + break; 1.226 + case SOAP_12: 1.227 + tmpBodyBuilder = EndpointResponseMessageBuilder.EMPTY_SOAP12; 1.228 + break; 1.229 + default: 1.230 + throw new AssertionError(); 1.231 + } 1.232 + } 1.233 + return tmpBodyBuilder; 1.234 + } 1.235 + 1.236 + public Object[] readRequest(Message reqMsg) { 1.237 + Object[] args = new Object[noOfArgs]; 1.238 + try { 1.239 + argumentsBuilder.readRequest(reqMsg,args); 1.240 + } catch (JAXBException e) { 1.241 + throw new WebServiceException(e); 1.242 + } catch (XMLStreamException e) { 1.243 + throw new WebServiceException(e); 1.244 + } 1.245 + return args; 1.246 + } 1.247 + 1.248 + public Message createResponse(JavaCallInfo call) { 1.249 + Message responseMessage; 1.250 + if (call.getException() == null) { 1.251 + responseMessage = isOneWay ? null : createResponseMessage(call.getParameters(), call.getReturnValue()); 1.252 + } else { 1.253 + Throwable e = call.getException(); 1.254 + Throwable serviceException = getServiceException(e); 1.255 + if (e instanceof InvocationTargetException || serviceException != null) { 1.256 +// Throwable cause = e.getCause(); 1.257 + //if (!(cause instanceof RuntimeException) && cause instanceof Exception) { 1.258 + if (serviceException != null) { 1.259 + // Service specific exception 1.260 + LOGGER.log(Level.FINE, serviceException.getMessage(), serviceException); 1.261 + responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, 1.262 + javaMethodModel.getCheckedException(serviceException.getClass()), serviceException); 1.263 + } else { 1.264 + Throwable cause = e.getCause(); 1.265 + if (cause instanceof ProtocolException) { 1.266 + // Application code may be throwing it intentionally 1.267 + LOGGER.log(Level.FINE, cause.getMessage(), cause); 1.268 + } else { 1.269 + // Probably some bug in application code 1.270 + LOGGER.log(Level.SEVERE, cause.getMessage(), cause); 1.271 + } 1.272 + responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, cause); 1.273 + } 1.274 + } else if (e instanceof DispatchException) { 1.275 + responseMessage = ((DispatchException)e).fault; 1.276 + } else { 1.277 + LOGGER.log(Level.SEVERE, e.getMessage(), e); 1.278 + responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, e); 1.279 + } 1.280 + } 1.281 +// return req.createServerResponse(responseMessage, req.endpoint.getPort(), javaMethodModel.getOwner(), req.endpoint.getBinding()); 1.282 + 1.283 + return responseMessage; 1.284 + } 1.285 + 1.286 + Throwable getServiceException(Throwable throwable) { 1.287 + if (javaMethodModel.getCheckedException(throwable.getClass()) != null) return throwable; 1.288 + if (throwable.getCause() != null) { 1.289 + Throwable cause = throwable.getCause(); 1.290 +// if (!(cause instanceof RuntimeException) && cause instanceof Exception) { 1.291 + if (javaMethodModel.getCheckedException(cause.getClass()) != null) return cause; 1.292 +// } 1.293 +// if (javaMethodModel.getCheckedException(cause.getClass()) != null) return cause; 1.294 + } 1.295 + return null; 1.296 + } 1.297 + 1.298 + /** 1.299 + * Creates a response {@link JAXBMessage} from method arguments, return value 1.300 + * 1.301 + * @return response message 1.302 + */ 1.303 + private Message createResponseMessage(Object[] args, Object returnValue) { 1.304 + Message msg = bodyBuilder.createMessage(args, returnValue); 1.305 + 1.306 + for (MessageFiller filler : outFillers) 1.307 + filler.fillIn(args, returnValue, msg); 1.308 + 1.309 + return msg; 1.310 + } 1.311 + 1.312 + public Method getMethod() { 1.313 + return method; 1.314 + } 1.315 + 1.316 + private static final Logger LOGGER = Logger.getLogger(TieHandler.class.getName()); 1.317 + 1.318 + @Override 1.319 + public JavaCallInfo deserializeRequest(Packet req) { 1.320 + com.sun.xml.internal.ws.api.databinding.JavaCallInfo call = new com.sun.xml.internal.ws.api.databinding.JavaCallInfo(); 1.321 + call.setMethod(this.getMethod()); 1.322 + Object[] args = this.readRequest(req.getMessage()); 1.323 + call.setParameters(args); 1.324 + return call; 1.325 + } 1.326 + 1.327 + @Override 1.328 + public Packet serializeResponse(JavaCallInfo call) { 1.329 + Message msg = this.createResponse(call); 1.330 + Packet p = (msg == null) ? (Packet)packetFactory.createContext() : (Packet)packetFactory.createContext(msg); 1.331 + p.setState(Packet.State.ServerResponse); 1.332 + return p; 1.333 + } 1.334 + 1.335 + @Override 1.336 + public JavaMethod getOperationModel() { 1.337 + return javaMethodModel; 1.338 + } 1.339 +}