src/share/jaxws_classes/com/sun/xml/internal/ws/client/dispatch/DispatchImpl.java

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 384
8f2986ff0235
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     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  */
    26 package com.sun.xml.internal.ws.client.dispatch;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.istack.internal.Nullable;
    30 import com.sun.xml.internal.ws.api.BindingID;
    31 import com.sun.xml.internal.ws.api.SOAPVersion;
    32 import com.sun.xml.internal.ws.api.WSBinding;
    33 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
    34 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
    35 import com.sun.xml.internal.ws.api.client.WSPortInfo;
    36 import com.sun.xml.internal.ws.api.message.AddressingUtils;
    37 import com.sun.xml.internal.ws.api.message.Attachment;
    38 import com.sun.xml.internal.ws.api.message.AttachmentSet;
    39 import com.sun.xml.internal.ws.api.message.Message;
    40 import com.sun.xml.internal.ws.api.message.Packet;
    41 import com.sun.xml.internal.ws.api.pipe.Fiber;
    42 import com.sun.xml.internal.ws.api.pipe.Tube;
    43 import com.sun.xml.internal.ws.api.server.Container;
    44 import com.sun.xml.internal.ws.api.server.ContainerResolver;
    45 import com.sun.xml.internal.ws.binding.BindingImpl;
    46 import com.sun.xml.internal.ws.client.*;
    47 import com.sun.xml.internal.ws.encoding.soap.DeserializationException;
    48 import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
    49 import com.sun.xml.internal.ws.message.AttachmentSetImpl;
    50 import com.sun.xml.internal.ws.message.DataHandlerAttachment;
    51 import com.sun.xml.internal.ws.resources.DispatchMessages;
    53 import javax.activation.DataHandler;
    54 import javax.xml.bind.JAXBException;
    55 import javax.xml.namespace.QName;
    56 import javax.xml.transform.Source;
    57 import javax.xml.ws.AsyncHandler;
    58 import javax.xml.ws.BindingProvider;
    59 import javax.xml.ws.Dispatch;
    60 import javax.xml.ws.Response;
    61 import javax.xml.ws.Service;
    62 import javax.xml.ws.Service.Mode;
    63 import javax.xml.ws.WebServiceException;
    64 import javax.xml.ws.handler.MessageContext;
    65 import javax.xml.ws.http.HTTPBinding;
    66 import javax.xml.ws.soap.SOAPBinding;
    67 import javax.xml.ws.soap.SOAPFaultException;
    68 import java.net.MalformedURLException;
    69 import java.net.URI;
    70 import java.net.URISyntaxException;
    71 import java.net.URL;
    72 import java.util.ArrayList;
    73 import java.util.HashMap;
    74 import java.util.List;
    75 import java.util.Map;
    76 import java.util.concurrent.Callable;
    77 import java.util.concurrent.Future;
    78 import java.util.logging.Level;
    79 import java.util.logging.Logger;
    82 /**
    83  * The <code>DispatchImpl</code> abstract class provides support
    84  * for the dynamic invocation of a service endpoint operation using XML
    85  * constructs, JAXB objects or <code>SOAPMessage</code>. The <code>javax.xml.ws.Service</code>
    86  * interface acts as a factory for the creation of <code>DispatchImpl</code>
    87  * instances.
    88  *
    89  * @author WS Development Team
    90  * @version 1.0
    91  */
    92 public abstract class DispatchImpl<T> extends Stub implements Dispatch<T> {
    94     private static final Logger LOGGER = Logger.getLogger(DispatchImpl.class.getName());
    96     final Service.Mode mode;
    97     final SOAPVersion soapVersion;
    98     final boolean allowFaultResponseMsg;
    99     static final long AWAIT_TERMINATION_TIME = 800L;
   101     /**
   102      *
   103      * @param port    dispatch instance is associated with this wsdl port qName
   104      * @param mode    Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
   105      * @param owner   Service that created the Dispatch
   106      * @param pipe    Master pipe for the pipeline
   107      * @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
   108      */
   109     @Deprecated
   110     protected DispatchImpl(QName port, Service.Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr) {
   111         super(port, owner, pipe, binding, (owner.getWsdlService() != null)? owner.getWsdlService().get(port) : null , owner.getEndpointAddress(port), epr);
   112         this.mode = mode;
   113         this.soapVersion = binding.getSOAPVersion();
   114         this.allowFaultResponseMsg = false;
   115     }
   117     /**
   118      * @param portInfo dispatch instance is associated with this portInfo
   119      * @param mode     Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
   120      * @param binding  Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
   121      */
   122     protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, @Nullable WSEndpointReference epr) {
   123         this(portInfo, mode, binding, epr, false);
   124     }
   126     /**
   127      * @param portInfo dispatch instance is associated with this portInfo
   128      * @param mode     Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
   129      * @param binding  Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
   130      * @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
   131      */
   132     protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
   133         this(portInfo, mode, binding, null, epr, allowFaultResponseMsg);
   134     }
   136     /**
   137      * @param portInfo dispatch instance is associated with this portInfo
   138      * @param mode     Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
   139      * @param binding  Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
   140      * @param pipe    Master pipe for the pipeline
   141      * @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
   142      */
   143     protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, BindingImpl binding, Tube pipe, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
   144         super(portInfo, binding, pipe, portInfo.getEndpointAddress(), epr);
   145         this.mode = mode;
   146         this.soapVersion = binding.getSOAPVersion();
   147         this.allowFaultResponseMsg = allowFaultResponseMsg;
   148     }
   149     /**
   150      *
   151      * @param portportInfo dispatch instance is associated with this wsdl port qName
   152      * @param mode    Service.mode associated with this Dispatch instance - Service.mode.MESSAGE or Service.mode.PAYLOAD
   153      * @param pipe    Master pipe for the pipeline
   154      * @param binding Binding of this Dispatch instance, current one of SOAP/HTTP or XML/HTTP
   155      * @param allowFaultResponseMsg A packet containing a SOAP fault message is allowed as the response to a request on this dispatch instance.
   156      */
   157     protected DispatchImpl(WSPortInfo portInfo, Service.Mode mode, Tube pipe, BindingImpl binding, @Nullable WSEndpointReference epr, boolean allowFaultResponseMsg) {
   158         super(portInfo, binding, pipe, portInfo.getEndpointAddress(), epr);
   159         this.mode = mode;
   160         this.soapVersion = binding.getSOAPVersion();
   161         this.allowFaultResponseMsg = allowFaultResponseMsg;
   162     }
   164     /**
   165      * Abstract method that is implemented by each concrete Dispatch class
   166      * @param msg  message passed in from the client program on the invocation
   167      * @return  The Message created returned as the Interface in actuallity a
   168      *          concrete Message Type
   169      */
   170     abstract Packet createPacket(T msg);
   172     /**
   173      * Obtains the value to return from the response message.
   174      */
   175     abstract T toReturnValue(Packet response);
   177     public final Response<T> invokeAsync(T param) {
   178         Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
   179         try {
   180             if (LOGGER.isLoggable(Level.FINE)) {
   181               dumpParam(param, "invokeAsync(T)");
   182             }
   183             AsyncInvoker invoker = new DispatchAsyncInvoker(param);
   184             AsyncResponseImpl<T> ft = new AsyncResponseImpl<T>(invoker,null);
   185             invoker.setReceiver(ft);
   186             ft.run();
   187             return ft;
   188         } finally {
   189             ContainerResolver.getDefault().exitContainer(old);
   190         }
   191     }
   193     private void dumpParam(T param, String method) {
   194       if (param instanceof Packet) {
   195         Packet message = (Packet)param;
   197         String action;
   198         String msgId;
   199         if (LOGGER.isLoggable(Level.FINE)) {
   200           AddressingVersion av = DispatchImpl.this.getBinding().getAddressingVersion();
   201           SOAPVersion sv = DispatchImpl.this.getBinding().getSOAPVersion();
   202           action =
   203             av != null && message.getMessage() != null ?
   204               AddressingUtils.getAction(message.getMessage().getHeaders(), av, sv) : null;
   205           msgId =
   206             av != null && message.getMessage() != null ?
   207               AddressingUtils.getMessageID(message.getMessage().getHeaders(), av, sv) : null;
   208           LOGGER.fine("In DispatchImpl." + method + " for message with action: " + action + " and msg ID: " + msgId + " msg: " + message.getMessage());
   210           if (message.getMessage() == null) {
   211             LOGGER.fine("Dispatching null message for action: " + action + " and msg ID: " + msgId);
   212           }
   213         }
   214       }
   215     }
   216     public final Future<?> invokeAsync(T param, AsyncHandler<T> asyncHandler) {
   217         Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
   218         try {
   219             if (LOGGER.isLoggable(Level.FINE)) {
   220               dumpParam(param, "invokeAsync(T, AsyncHandler<T>)");
   221             }
   222             AsyncInvoker invoker = new DispatchAsyncInvoker(param);
   223             AsyncResponseImpl<T> ft = new AsyncResponseImpl<T>(invoker,asyncHandler);
   224             invoker.setReceiver(ft);
   225             invoker.setNonNullAsyncHandlerGiven(asyncHandler != null);
   227             ft.run();
   228             return ft;
   229         } finally {
   230             ContainerResolver.getDefault().exitContainer(old);
   231         }
   232     }
   234     /**
   235      * Synchronously invokes a service.
   236      *
   237      * See {@link #process(Packet, RequestContext, ResponseContextReceiver)} on
   238      * why it takes a {@link RequestContext} and {@link ResponseContextReceiver} as a parameter.
   239      */
   240     public final T doInvoke(T in, RequestContext rc, ResponseContextReceiver receiver){
   241         Packet response = null;
   242         try {
   243                 try {
   244                     checkNullAllowed(in, rc, binding, mode);
   246                     Packet message = createPacket(in);
   247                     message.setState(Packet.State.ClientRequest);
   248                     resolveEndpointAddress(message, rc);
   249                     setProperties(message,true);
   250                     response = process(message,rc,receiver);
   251                     Message msg = response.getMessage();
   253         // REVIEW: eliminate allowFaultResponseMsg, but make that behavior default for MessageDispatch, PacketDispatch
   254                     if(msg != null && msg.isFault() &&
   255                  !allowFaultResponseMsg) {
   256                         SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
   257                         // passing null means there is no checked excpetion we're looking for all
   258                         // it will get back to us is a protocol exception
   259                         throw (SOAPFaultException)faultBuilder.createException(null);
   260                     }
   261                 } catch (JAXBException e) {
   262                     //TODO: i18nify
   263                     throw new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e);
   264                 } catch(WebServiceException e){
   265                     //it could be a WebServiceException or a ProtocolException
   266                     throw e;
   267                 } catch(Throwable e){
   268                     // it could be a RuntimeException resulting due to some internal bug or
   269                     // its some other exception resulting from user error, wrap it in
   270                     // WebServiceException
   271                     throw new WebServiceException(e);
   272                 }
   274                 return toReturnValue(response);
   275         } finally {
   276         // REVIEW: Move to AsyncTransportProvider
   277                 if (response != null && response.transportBackChannel != null)
   278                         response.transportBackChannel.close();
   279         }
   280     }
   282     public final T invoke(T in) {
   283         Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
   284         try {
   285             if (LOGGER.isLoggable(Level.FINE)) {
   286               dumpParam(in, "invoke(T)");
   287             }
   289             return doInvoke(in,requestContext,this);
   290         } finally {
   291             ContainerResolver.getDefault().exitContainer(old);
   292         }
   293     }
   295     public final void invokeOneWay(T in) {
   296         Container old = ContainerResolver.getDefault().enterContainer(owner.getContainer());
   297         try {
   298             if (LOGGER.isLoggable(Level.FINE)) {
   299               dumpParam(in, "invokeOneWay(T)");
   300             }
   302             try {
   303                 checkNullAllowed(in, requestContext, binding, mode);
   305                 Packet request = createPacket(in);
   306                 request.setState(Packet.State.ClientRequest);
   307                 setProperties(request,false);
   308                 process(request,requestContext,this);
   309             } catch(WebServiceException e){
   310                 //it could be a WebServiceException or a ProtocolException
   311                 throw e;
   312             } catch(Throwable e){
   313                 // it could be a RuntimeException resulting due to some internal bug or
   314                 // its some other exception resulting from user error, wrap it in
   315                 // WebServiceException
   316                 throw new WebServiceException(e);
   317             }
   318         } finally {
   319             ContainerResolver.getDefault().exitContainer(old);
   320         }
   321     }
   323     void setProperties(Packet packet, boolean expectReply) {
   324         packet.expectReply = expectReply;
   325     }
   327     static boolean isXMLHttp(@NotNull WSBinding binding) {
   328         return binding.getBindingId().equals(BindingID.XML_HTTP);
   329     }
   331     static boolean isPAYLOADMode(@NotNull Service.Mode mode) {
   332            return mode == Service.Mode.PAYLOAD;
   333     }
   335     static void checkNullAllowed(@Nullable Object in, RequestContext rc, WSBinding binding, Service.Mode mode) {
   337         if (in != null)
   338             return;
   340         //With HTTP Binding a null invocation parameter can not be used
   341         //with HTTP Request Method == POST
   342         if (isXMLHttp(binding)){
   343             if (methodNotOk(rc))
   344                 throw new WebServiceException(DispatchMessages.INVALID_NULLARG_XMLHTTP_REQUEST_METHOD(HTTP_REQUEST_METHOD_POST, HTTP_REQUEST_METHOD_GET));
   345         } else { //soapBinding
   346               if (mode == Service.Mode.MESSAGE )
   347                    throw new WebServiceException(DispatchMessages.INVALID_NULLARG_SOAP_MSGMODE(mode.name(), Service.Mode.PAYLOAD.toString()));
   348         }
   349     }
   351     static boolean methodNotOk(@NotNull RequestContext rc) {
   352         String requestMethod = (String)rc.get(MessageContext.HTTP_REQUEST_METHOD);
   353         String request = (requestMethod == null)? HTTP_REQUEST_METHOD_POST: requestMethod;
   354         // if method == post or put with a null invocation parameter in xml/http binding this is not ok
   355         return HTTP_REQUEST_METHOD_POST.equalsIgnoreCase(request) || HTTP_REQUEST_METHOD_PUT.equalsIgnoreCase(request);
   356     }
   358     public static void checkValidSOAPMessageDispatch(WSBinding binding, Service.Mode mode) {
   359         // Dispatch<SOAPMessage> is only valid for soap binding and in Service.Mode.MESSAGE
   360         if (DispatchImpl.isXMLHttp(binding))
   361             throw new WebServiceException(DispatchMessages.INVALID_SOAPMESSAGE_DISPATCH_BINDING(HTTPBinding.HTTP_BINDING, SOAPBinding.SOAP11HTTP_BINDING + " or " + SOAPBinding.SOAP12HTTP_BINDING));
   362         if (DispatchImpl.isPAYLOADMode(mode))
   363             throw new WebServiceException(DispatchMessages.INVALID_SOAPMESSAGE_DISPATCH_MSGMODE(mode.name(), Service.Mode.MESSAGE.toString()));
   364     }
   366     public static void checkValidDataSourceDispatch(WSBinding binding, Service.Mode mode) {
   367         // Dispatch<DataSource> is only valid with xml/http binding and in Service.Mode.MESSAGE
   368         if (!DispatchImpl.isXMLHttp(binding))
   369             throw new WebServiceException(DispatchMessages.INVALID_DATASOURCE_DISPATCH_BINDING("SOAP/HTTP", HTTPBinding.HTTP_BINDING));
   370         if (DispatchImpl.isPAYLOADMode(mode))
   371             throw new WebServiceException(DispatchMessages.INVALID_DATASOURCE_DISPATCH_MSGMODE(mode.name(), Service.Mode.MESSAGE.toString()));
   372     }
   374     public final @NotNull QName getPortName() {
   375         return portname;
   376     }
   378     void resolveEndpointAddress(@NotNull final Packet message, @NotNull final RequestContext requestContext) {
   379         final boolean p = message.packetTakesPriorityOverRequestContext;
   381         //resolve endpoint look for query parameters, pathInfo
   382         String endpoint;
   383         if (p && message.endpointAddress != null) {
   384             endpoint = message.endpointAddress.toString();
   385         } else {
   386             endpoint = (String) requestContext.get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY);
   387         }
   388         // This is existing before packetTakesPriorityOverRequestContext so leaving in place.
   389         if (endpoint == null) {
   390             if (message.endpointAddress == null) throw new WebServiceException(DispatchMessages.INVALID_NULLARG_URI());
   391             endpoint = message.endpointAddress.toString();
   392         }
   394         String pathInfo = null;
   395         String queryString = null;
   396         if (p && message.invocationProperties.get(MessageContext.PATH_INFO) != null) {
   397             pathInfo = (String) message.invocationProperties.get(MessageContext.PATH_INFO);
   398         } else if (requestContext.get(MessageContext.PATH_INFO) != null) {
   399             pathInfo = (String) requestContext.get(MessageContext.PATH_INFO);
   400         }
   402         if (p && message.invocationProperties.get(MessageContext.QUERY_STRING) != null) {
   403             queryString = (String) message.invocationProperties.get(MessageContext.QUERY_STRING);
   404         } else if (requestContext.get(MessageContext.QUERY_STRING) != null) {
   405             queryString = (String) requestContext.get(MessageContext.QUERY_STRING);
   406         }
   408         if (pathInfo != null || queryString != null) {
   409             pathInfo = checkPath(pathInfo);
   410             queryString = checkQuery(queryString);
   411             if (endpoint != null) {
   412                 try {
   413                     final URI endpointURI = new URI(endpoint);
   414                     endpoint = resolveURI(endpointURI, pathInfo, queryString);
   415                 } catch (URISyntaxException e) {
   416                     throw new WebServiceException(DispatchMessages.INVALID_URI(endpoint));
   417                 }
   418             }
   419         }
   420         // These two lines used to be inside the above if.  It is outside so:
   421         // - in cases where there is no setting of address on a Packet before invocation or no pathInfo/queryString
   422         //   this will just put back what it found in the requestContext - basically a noop.
   423         // - but when info is in the Packet this will update so it will get used later.
   424         // Remember - we are operating on a copied RequestContext at this point - not the sticky one in the Stub.
   425         requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
   426         // This is not necessary because a later step will copy the resolvedEndpoint put above into message.
   427         //message.endpointAddress = EndpointAddress.create(endpoint);
   428     }
   430     protected @NotNull String resolveURI(@NotNull URI endpointURI, @Nullable String pathInfo, @Nullable String queryString) {
   431         String query = null;
   432         String fragment = null;
   433         if (queryString != null) {
   434             final URI result;
   435             try {
   436                 URI tp = new URI(null, null, endpointURI.getPath(), queryString, null);
   437                 result = endpointURI.resolve(tp);
   438             } catch (URISyntaxException e) {
   439                 throw new WebServiceException(DispatchMessages.INVALID_QUERY_STRING(queryString));
   440             }
   441             query = result.getQuery();
   442             fragment = result.getFragment();
   443         }
   445         final String path = (pathInfo != null) ? pathInfo : endpointURI.getPath();
   446         try {
   447             //final URI temp = new URI(null, null, path, query, fragment);
   448             //return endpointURI.resolve(temp).toURL().toExternalForm();
   449             // Using the following HACK instead of the above to avoid double encoding of
   450             // the query. Application's QUERY_STRING is encoded using URLEncoder.encode().
   451             // If we use that query in URI's constructor, it is encoded again.
   452             // URLEncoder's encoding is not the same as URI's encoding of the query.
   453             // See {@link URL}
   454             StringBuilder spec = new StringBuilder();
   455             if (path != null) {
   456                 spec.append(path);
   457             }
   458             if (query != null) {
   459                 spec.append("?");
   460                 spec.append(query);
   461             }
   462             if (fragment != null) {
   463                 spec.append("#");
   464                 spec.append(fragment);
   465             }
   466             return new URL(endpointURI.toURL(), spec.toString()).toExternalForm();
   467        } catch (MalformedURLException e) {
   468             throw new WebServiceException(DispatchMessages.INVALID_URI_RESOLUTION(path));
   469         }
   470     }
   472     private static String checkPath(@Nullable String path) {
   473         //does it begin with /
   474         return (path == null || path.startsWith("/")) ? path : "/" + path;
   475     }
   477     private static String checkQuery(@Nullable String query) {
   478         if (query == null) return null;
   480         if (query.indexOf('?') == 0)
   481            throw new WebServiceException(DispatchMessages.INVALID_QUERY_LEADING_CHAR(query));
   482         return query;
   483     }
   486     protected AttachmentSet setOutboundAttachments() {
   487         HashMap<String, DataHandler> attachments = (HashMap<String, DataHandler>)
   488                 getRequestContext().get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
   490         if (attachments != null) {
   491             List<Attachment> alist = new ArrayList();
   492             for (Map.Entry<String, DataHandler> att : attachments.entrySet()) {
   493                 DataHandlerAttachment dha = new DataHandlerAttachment(att.getKey(), att.getValue());
   494                 alist.add(dha);
   495             }
   496             return new AttachmentSetImpl(alist);
   497         }
   498         return new AttachmentSetImpl();
   499     }
   501    /* private void getInboundAttachments(Message msg) {
   502         AttachmentSet attachments = msg.getAttachments();
   503         if (!attachments.isEmpty()) {
   504             Map<String, DataHandler> in = new HashMap<String, DataHandler>();
   505             for (Attachment attachment : attachments)
   506                 in.put(attachment.getContentId(), attachment.asDataHandler());
   507             getResponseContext().put(MessageContext.INBOUND_MESSAGE_ATTACHMENTS, in);
   508         }
   510     }
   511     */
   514     /**
   515      * Calls {@link DispatchImpl#doInvoke(Object,RequestContext,ResponseContextReceiver)}.
   516      */
   517     private class Invoker implements Callable {
   518         private final T param;
   519         // snapshot the context now. this is necessary to avoid concurrency issue,
   520         // and is required by the spec
   521         private final RequestContext rc = requestContext.copy();
   523         /**
   524          * Because of the object instantiation order,
   525          * we can't take this as a constructor parameter.
   526          */
   527         private ResponseContextReceiver receiver;
   529         Invoker(T param) {
   530             this.param = param;
   531         }
   533         public T call() throws Exception {
   534             if (LOGGER.isLoggable(Level.FINE)) {
   535               dumpParam(param, "call()");
   536             }
   537             return doInvoke(param,rc,receiver);
   538         }
   540         void setReceiver(ResponseContextReceiver receiver) {
   541             this.receiver = receiver;
   542         }
   543     }
   545     /**
   546      *
   547      */
   548     private class DispatchAsyncInvoker extends AsyncInvoker {
   549         private final T param;
   550         // snapshot the context now. this is necessary to avoid concurrency issue,
   551         // and is required by the spec
   552         private final RequestContext rc = requestContext.copy();
   554         DispatchAsyncInvoker(T param) {
   555             this.param = param;
   556         }
   558         public void do_run () {
   559             checkNullAllowed(param, rc, binding, mode);
   560             final Packet message = createPacket(param);
   561             message.setState(Packet.State.ClientRequest);
   562             message.nonNullAsyncHandlerGiven = this.nonNullAsyncHandlerGiven;
   563             resolveEndpointAddress(message, rc);
   564             setProperties(message,true);
   566             String action = null;
   567             String msgId = null;
   568             if (LOGGER.isLoggable(Level.FINE)) {
   569               AddressingVersion av = DispatchImpl.this.getBinding().getAddressingVersion();
   570               SOAPVersion sv = DispatchImpl.this.getBinding().getSOAPVersion();
   571               action =
   572                 av != null && message.getMessage() != null ?
   573                   AddressingUtils.getAction(message.getMessage().getHeaders(), av, sv) : null;
   574               msgId =
   575                 av != null&& message.getMessage() != null ?
   576                   AddressingUtils.getMessageID(message.getMessage().getHeaders(), av, sv) : null;
   577               LOGGER.fine("In DispatchAsyncInvoker.do_run for async message with action: " + action + " and msg ID: " + msgId);
   578             }
   580             final String actionUse = action;
   581             final String msgIdUse = msgId;
   583             Fiber.CompletionCallback callback = new Fiber.CompletionCallback() {
   584                 public void onCompletion(@NotNull Packet response) {
   586                     if (LOGGER.isLoggable(Level.FINE)) {
   587                       LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse);
   588                     }
   590                     Message msg = response.getMessage();
   592                     if (LOGGER.isLoggable(Level.FINE)) {
   593                       LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse + " msg: " + msg);
   594                     }
   596                     try {
   597                         if(msg != null && msg.isFault() &&
   598                            !allowFaultResponseMsg) {
   599                             SOAPFaultBuilder faultBuilder = SOAPFaultBuilder.create(msg);
   600                             // passing null means there is no checked excpetion we're looking for all
   601                             // it will get back to us is a protocol exception
   602                             throw (SOAPFaultException)faultBuilder.createException(null);
   603                         }
   604                         responseImpl.setResponseContext(new ResponseContext(response));
   605                         responseImpl.set(toReturnValue(response), null);
   606                     } catch (JAXBException e) {
   607                         //TODO: i18nify
   608                         responseImpl.set(null, new DeserializationException(DispatchMessages.INVALID_RESPONSE_DESERIALIZATION(),e));
   609                     } catch(WebServiceException e){
   610                         //it could be a WebServiceException or a ProtocolException
   611                         responseImpl.set(null, e);
   612                     } catch(Throwable e){
   613                         // It could be any RuntimeException resulting due to some internal bug.
   614                         // or its some other exception resulting from user error, wrap it in
   615                         // WebServiceException
   616                         responseImpl.set(null, new WebServiceException(e));
   617                     }
   618                 }
   619                 public void onCompletion(@NotNull Throwable error) {
   620                     if (LOGGER.isLoggable(Level.FINE)) {
   621                       LOGGER.fine("Done with processAsync in DispatchAsyncInvoker.do_run, and setting response for async message with action: " + actionUse + " and msg ID: " + msgIdUse + " Throwable: " + error.toString());
   622                     }
   623                     if (error instanceof WebServiceException) {
   624                         responseImpl.set(null, error);
   626                     } else {
   627                         //its RuntimeException or some other exception resulting from user error, wrap it in
   628                         // WebServiceException
   629                         responseImpl.set(null, new WebServiceException(error));
   630                     }
   631                 }
   632             };
   633             processAsync(responseImpl,message,rc, callback);
   634         }
   635     }
   637     public void setOutboundHeaders(Object... headers) {
   638         throw new UnsupportedOperationException();
   639     }
   641     static final String HTTP_REQUEST_METHOD_GET="GET";
   642     static final String HTTP_REQUEST_METHOD_POST="POST";
   643     static final String HTTP_REQUEST_METHOD_PUT="PUT";
   645     @Deprecated
   646     public static Dispatch<Source> createSourceDispatch(QName port, Mode mode, WSServiceDelegate owner, Tube pipe, BindingImpl binding, WSEndpointReference epr) {
   647         if(isXMLHttp(binding))
   648             return new RESTSourceDispatch(port,mode,owner,pipe,binding,epr);
   649         else
   650             return new SOAPSourceDispatch(port,mode,owner,pipe,binding,epr);
   651     }
   653     public static Dispatch<Source> createSourceDispatch(WSPortInfo portInfo, Mode mode, BindingImpl binding, WSEndpointReference epr) {
   654         if (isXMLHttp(binding))
   655             return new RESTSourceDispatch(portInfo, mode, binding, epr);
   656         else
   657             return new SOAPSourceDispatch(portInfo, mode, binding, epr);
   658     }
   659 }

mercurial