diff -r 88b85470e72c -r f50545b5e2f1 src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/TieHandler.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/server/sei/TieHandler.java Tue Mar 06 16:09:35 2012 -0800
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.xml.internal.ws.server.sei;
+
+import com.sun.xml.internal.ws.api.SOAPVersion;
+import com.sun.xml.internal.ws.api.WSBinding;
+import com.sun.xml.internal.ws.api.databinding.EndpointCallBridge;
+import com.sun.xml.internal.ws.api.databinding.JavaCallInfo;
+import com.sun.xml.internal.ws.api.message.Message;
+import com.sun.xml.internal.ws.api.message.Packet;
+import com.sun.xml.internal.ws.api.model.JavaMethod;
+import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
+import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
+import com.sun.xml.internal.ws.model.JavaMethodImpl;
+import com.sun.xml.internal.ws.model.ParameterImpl;
+import com.sun.xml.internal.ws.model.WrapperParameter;
+import com.sun.xml.internal.ws.wsdl.DispatchException;
+
+import javax.jws.WebParam.Mode;
+import javax.xml.bind.JAXBException;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.ws.Holder;
+import javax.xml.ws.ProtocolException;
+import javax.xml.ws.WebServiceException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ *
+ * This class mainly performs the following two tasks:
+ *
+ * - Takes a {@link Message] that represents a request,
+ * and extracts the arguments (and updates {@link Holder}s.)
+ *
- Accepts return value and {@link Holder} arguments for a Java method,
+ * and creates {@link JAXBMessage} that represents a response message.
+ *
+ *
+ * Creating {@link JAXBMessage}
+ *
+ * At the construction time, we prepare {@link EndpointArgumentsBuilder} that knows how to create endpoint {@link Method}
+ * invocation arguments.
+ * we also prepare {@link EndpointResponseMessageBuilder} and {@link MessageFiller}s
+ * that know how to move arguments into a {@link Message}.
+ * Some arguments go to the payload, some go to headers, still others go to attachments.
+ *
+ * @author Jitendra Kotamraju
+ * @author shih-chang.chen@oracle.com
+ * Refactored from EndpointMethodHandler
+ */
+final public class TieHandler implements EndpointCallBridge {
+
+ private final SOAPVersion soapVersion;
+ private final Method method;
+ private final int noOfArgs;
+ private final JavaMethodImpl javaMethodModel;
+
+ private final Boolean isOneWay;
+
+ // Converts {@link Message} --> Object[]
+ private final EndpointArgumentsBuilder argumentsBuilder;
+
+ // these objects together create a response message from method parameters
+ private final EndpointResponseMessageBuilder bodyBuilder;
+ private final MessageFiller[] outFillers;
+
+ public TieHandler(JavaMethodImpl method, WSBinding binding) {
+ this.soapVersion = binding.getSOAPVersion();
+ this.method = method.getMethod();
+ this.javaMethodModel = method;
+ argumentsBuilder = createArgumentsBuilder();
+ List fillers = new ArrayList();
+ bodyBuilder = createResponseMessageBuilder(fillers);
+ this.outFillers = fillers.toArray(new MessageFiller[fillers.size()]);
+ this.isOneWay = method.getMEP().isOneWay();
+ this.noOfArgs = this.method.getParameterTypes().length;
+ }
+
+ /**
+ * It builds EndpointArgumentsBuilder which converts request {@link Message} to endpoint method's invocation
+ * arguments Object[]
+ *
+ * @return EndpointArgumentsBuilder
+ */
+ private EndpointArgumentsBuilder createArgumentsBuilder() {
+ EndpointArgumentsBuilder argsBuilder;
+ List rp = javaMethodModel.getRequestParameters();
+ List builders = new ArrayList();
+
+ for( ParameterImpl param : rp ) {
+ EndpointValueSetter setter = EndpointValueSetter.get(param);
+ switch(param.getInBinding().kind) {
+ case BODY:
+ if(param.isWrapperStyle()) {
+ if(param.getParent().getBinding().isRpcLit())
+ builders.add(new EndpointArgumentsBuilder.RpcLit((WrapperParameter)param));
+ else
+ builders.add(new EndpointArgumentsBuilder.DocLit((WrapperParameter)param, Mode.OUT));
+ } else {
+ builders.add(new EndpointArgumentsBuilder.Body(param.getXMLBridge(),setter));
+ }
+ break;
+ case HEADER:
+ builders.add(new EndpointArgumentsBuilder.Header(soapVersion, param, setter));
+ break;
+ case ATTACHMENT:
+ builders.add(EndpointArgumentsBuilder.AttachmentBuilder.createAttachmentBuilder(param, setter));
+ break;
+ case UNBOUND:
+ builders.add(new EndpointArgumentsBuilder.NullSetter(setter,
+ EndpointArgumentsBuilder.getVMUninitializedValue(param.getTypeInfo().type)));
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ // creates {@link Holder} arguments for OUT parameters
+ List resp = javaMethodModel.getResponseParameters();
+ for( ParameterImpl param : resp ) {
+ if (param.isWrapperStyle()) {
+ WrapperParameter wp = (WrapperParameter)param;
+ List children = wp.getWrapperChildren();
+ for (ParameterImpl p : children) {
+ if (p.isOUT() && p.getIndex() != -1) {
+ EndpointValueSetter setter = EndpointValueSetter.get(p);
+ builders.add(new EndpointArgumentsBuilder.NullSetter(setter, null));
+ }
+ }
+ } else if (param.isOUT() && param.getIndex() != -1) {
+ EndpointValueSetter setter = EndpointValueSetter.get(param);
+ builders.add(new EndpointArgumentsBuilder.NullSetter(setter, null));
+ }
+ }
+
+ switch(builders.size()) {
+ case 0:
+ argsBuilder = EndpointArgumentsBuilder.NONE;
+ break;
+ case 1:
+ argsBuilder = builders.get(0);
+ break;
+ default:
+ argsBuilder = new EndpointArgumentsBuilder.Composite(builders);
+ }
+ return argsBuilder;
+ }
+
+ /**
+ * prepare objects for creating response {@link Message}
+ */
+ private EndpointResponseMessageBuilder createResponseMessageBuilder(List fillers) {
+
+ EndpointResponseMessageBuilder bodyBuilder = null;
+ List rp = javaMethodModel.getResponseParameters();
+
+ for (ParameterImpl param : rp) {
+ ValueGetter getter = ValueGetter.get(param);
+
+ switch(param.getOutBinding().kind) {
+ case BODY:
+ if(param.isWrapperStyle()) {
+ if(param.getParent().getBinding().isRpcLit()) {
+ bodyBuilder = new EndpointResponseMessageBuilder.RpcLit((WrapperParameter)param,
+ soapVersion);
+ } else {
+ bodyBuilder = new EndpointResponseMessageBuilder.DocLit((WrapperParameter)param,
+ soapVersion);
+ }
+ } else {
+ bodyBuilder = new EndpointResponseMessageBuilder.Bare(param, soapVersion);
+ }
+ break;
+ case HEADER:
+ fillers.add(new MessageFiller.Header(param.getIndex(), param.getXMLBridge(), getter ));
+ break;
+ case ATTACHMENT:
+ fillers.add(MessageFiller.AttachmentFiller.createAttachmentFiller(param, getter));
+ break;
+ case UNBOUND:
+ break;
+ default:
+ throw new AssertionError(); // impossible
+ }
+ }
+
+ if (bodyBuilder == null) {
+ // no parameter binds to body. we create an empty message
+ switch(soapVersion) {
+ case SOAP_11:
+ bodyBuilder = EndpointResponseMessageBuilder.EMPTY_SOAP11;
+ break;
+ case SOAP_12:
+ bodyBuilder = EndpointResponseMessageBuilder.EMPTY_SOAP12;
+ break;
+ default:
+ throw new AssertionError();
+ }
+ }
+ return bodyBuilder;
+ }
+
+ public Object[] readRequest(Message reqMsg) {
+ Object[] args = new Object[noOfArgs];
+ try {
+ argumentsBuilder.readRequest(reqMsg,args);
+ } catch (JAXBException e) {
+ throw new WebServiceException(e);
+ } catch (XMLStreamException e) {
+ throw new WebServiceException(e);
+ }
+ return args;
+ }
+
+ public Message createResponse(JavaCallInfo call) {
+ Message responseMessage;
+ Object ret = call.getReturnValue();
+ if (call.getException() == null) {
+ responseMessage = isOneWay ? null : createResponseMessage(call.getParameters(), call.getReturnValue());
+ } else {
+ Throwable e = call.getException();
+ Throwable serviceException = getServiceException(e);
+ if (e instanceof InvocationTargetException || serviceException != null) {
+// Throwable cause = e.getCause();
+ //if (!(cause instanceof RuntimeException) && cause instanceof Exception) {
+ if (serviceException != null) {
+ // Service specific exception
+ LOGGER.log(Level.FINE, serviceException.getMessage(), serviceException);
+ responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion,
+ javaMethodModel.getCheckedException(serviceException.getClass()), serviceException);
+ } else {
+ Throwable cause = e.getCause();
+ if (cause instanceof ProtocolException) {
+ // Application code may be throwing it intentionally
+ LOGGER.log(Level.FINE, cause.getMessage(), cause);
+ } else {
+ // Probably some bug in application code
+ LOGGER.log(Level.SEVERE, cause.getMessage(), cause);
+ }
+ responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, cause);
+ }
+ } else if (e instanceof DispatchException) {
+ responseMessage = ((DispatchException)e).fault;
+ } else {
+ LOGGER.log(Level.SEVERE, e.getMessage(), e);
+ responseMessage = SOAPFaultBuilder.createSOAPFaultMessage(soapVersion, null, e);
+ }
+ }
+// return req.createServerResponse(responseMessage, req.endpoint.getPort(), javaMethodModel.getOwner(), req.endpoint.getBinding());
+
+ return responseMessage;
+ }
+
+ Throwable getServiceException(Throwable throwable) {
+ if (javaMethodModel.getCheckedException(throwable.getClass()) != null) return throwable;
+ if (throwable.getCause() != null) {
+ Throwable cause = throwable.getCause();
+// if (!(cause instanceof RuntimeException) && cause instanceof Exception) {
+ if (javaMethodModel.getCheckedException(cause.getClass()) != null) return cause;
+// }
+// if (javaMethodModel.getCheckedException(cause.getClass()) != null) return cause;
+ }
+ return null;
+ }
+
+ /**
+ * Creates a response {@link JAXBMessage} from method arguments, return value
+ *
+ * @return response message
+ */
+ private Message createResponseMessage(Object[] args, Object returnValue) {
+ Message msg = bodyBuilder.createMessage(args, returnValue);
+
+ for (MessageFiller filler : outFillers)
+ filler.fillIn(args, returnValue, msg);
+
+ return msg;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ private static final Logger LOGGER = Logger.getLogger(TieHandler.class.getName());
+
+ public JavaCallInfo deserializeRequest(Packet req) {
+ JavaCallInfo call = new JavaCallInfo();
+ call.setMethod(this.getMethod());
+ Object[] args = this.readRequest(req.getMessage());
+ call.setParameters(args);
+ return call;
+ }
+
+ public Packet serializeResponse(JavaCallInfo call) {
+ Message msg = this.createResponse(call);
+ Packet response = new Packet();
+ response.setMessage(msg);
+ return response;
+ }
+
+ public JavaMethod getOperationModel() {
+ return javaMethodModel;
+ }
+}