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  */
  25 
  26 package com.sun.xml.internal.ws.api.pipe;
  27 
  28 import com.sun.xml.internal.ws.api.message.Message;
  29 import com.sun.xml.internal.ws.api.message.Packet;
  30 import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterPipeImpl;
  31 import com.sun.xml.internal.ws.api.pipe.helper.AbstractPipeImpl;
  32 
  33 import javax.annotation.PreDestroy;
  34 import javax.xml.ws.Dispatch;
  35 import javax.xml.ws.Provider;
  36 import javax.xml.ws.WebServiceException;
  37 import javax.xml.ws.handler.Handler;
  38 import javax.xml.ws.handler.LogicalHandler;
  39 import javax.xml.ws.handler.MessageContext;
  40 import javax.xml.ws.handler.soap.SOAPHandler;
  41 
  42 /**
  43  * Abstraction of the intermediate layers in the processing chain
  44  * and transport.
  45  *
  46  * <h2>What is a {@link Pipe}?</h2>
  47  * <p>
  48  * Transport is a kind of pipe. It sends the {@link Packet}
  49  * through, say, HTTP connection, and receives the data back into another {@link Packet}.
  50  *
  51  * <p>
  52  * More often, a pipe is a filter. It acts on a packet,
  53  * and then it passes the packet into another pipe. It can
  54  * do the same on the way back.
  55  *
  56  * <p>
  57  * For example, XWSS will be a {@link Pipe}
  58  * that delegates to another {@link Pipe}, and it can wrap a {@link Packet} into
  59  * another {@link Packet} to encrypt the body and add a header, for example.
  60  *
  61  * <p>
  62  * Yet another kind of filter pipe is those that wraps {@link LogicalHandler}
  63  * and {@link SOAPHandler}. These pipes are heavy-weight; they often consume
  64  * a message in a packet and create a new one, and then pass it to the next pipe.
  65  * For performance reason it probably makes sense to have one {@link Pipe}
  66  * instance that invokes a series of {@link LogicalHandler}s, another one
  67  * for {@link SOAPHandler}.
  68  *
  69  * <p>
  70  * There would be a {@link Pipe} implementation that invokes {@link Provider}.
  71  * There would be a {@link Pipe} implementation that invokes a service method
  72  * on the user's code.
  73  * There would be a {@link Dispatch} implementation that invokes a {@link Pipe}.
  74  *
  75  * <p>
  76  * WS-MEX can be implemented as a {@link Pipe} that looks for
  77  * {@link Message#getPayloadNamespaceURI()} and serves the request.
  78  *
  79  *
  80  * <h2>Pipe Lifecycle</h2>
  81  * {@link Pipe}line is expensive to set up, so once it's created it will be reused.
  82  * A {@link Pipe}line is not reentrant; one pipeline is used to process one request/response
  83  * at at time. The same pipeline instance may serve request/response for different threads,
  84  * if one comes after another and they don't overlap.
  85  * <p>
  86  * Where a need arises to process multiple requests concurrently, a pipeline
  87  * gets cloned through {@link PipeCloner}. Note that this need may happen on
  88  * both server (because it quite often serves multiple requests concurrently)
  89  * and client (because it needs to support asynchronous method invocations.)
  90  * <p>
  91  * Created pipelines (including cloned ones and the original) may be discarded and GCed
  92  * at any time at the discretion of whoever owns pipelines. Pipes can, however, expect
  93  * at least one copy (or original) of pipeline to live at any given time while a pipeline
  94  * owner is interested in the given pipeline configuration (in more concerete terms,
  95  * for example, as long as a dispatch object lives, it's going to keep at least one
  96  * copy of a pipeline alive.)
  97  * <p>
  98  * Before a pipeline owner dies, it may invoke {@link #preDestroy()} on the last
  99  * remaining pipeline. It is "may" for pipeline owners that live in the client-side
 100  * of JAX-WS (such as dispatches and proxies), but it is a "must" for pipeline owners
 101  * that live in the server-side of JAX-WS.
 102  * <p>
 103  * This last invocation gives a chance for some pipes to clean up any state/resource
 104  * acquired (such as WS-RM's sequence, WS-Trust's SecurityToken), although as stated above,
 105  * this is not required for clients.
 106  *
 107  *
 108  *
 109  * <h2>Pipe and State</h2>
 110  * <p>
 111  * The lifecycle of pipelines is designed to allow a {@link Pipe} to store various
 112  * state in easily accessible fashion.
 113  *
 114  *
 115  * <h3>Per-packet state</h3>
 116  * <p>
 117  * Any information that changes from a packet to packet should be
 118  * stored in {@link Packet}. This includes information like
 119  * transport-specific headers.
 120  *
 121  * <h3>Per-thread state</h3>
 122  * <p>
 123  * Any expensive objects that are non-reentrant can be stored in
 124  * instance variables of a {@link Pipe}, since {@link #process(Packet)} is
 125  * non reentrant. When a pipe is copied, new instances should be allocated
 126  * so that two {@link Pipe} instances don't share thread-unsafe resources.
 127  * This includes things like canonicalizers, JAXB unmarshallers, buffers,
 128  * and so on.
 129  *
 130  * <h3>Per-proxy/per-endpoint state</h3>
 131  * <p>
 132  * Information that is tied to a particular proxy/dispatch can be stored
 133  * in a separate object that is referenced from a pipe. When
 134  * a new pipe is copied, you can simply hand out a reference to the newly
 135  * created one, so that all copied pipes refer to the same instance.
 136  * See the following code as an example:
 137  *
 138  * <pre>
 139  * class PipeImpl {
 140  *   // this object stores per-proxy state
 141  *   class DataStore {
 142  *     int counter;
 143  *   }
 144  *
 145  *   private DataStore ds;
 146  *
 147  *   // create a fresh new pipe
 148  *   public PipeImpl(...) {
 149  *     ....
 150  *     ds = new DataStore();
 151  *   }
 152  *
 153  *   // copy constructor
 154  *   private PipeImpl(PipeImpl that, PipeCloner cloner) {
 155  *     cloner.add(that,this);
 156  *     ...
 157  *     this.ds = that.ds;
 158  *   }
 159  *
 160  *   public PipeImpl copy(PipeCloner pc) {
 161  *     return new PipeImpl(this,pc);
 162  *   }
 163  * }
 164  * </pre>
 165  *
 166  * <p>
 167  * Note that access to such resource often needs to be synchronized,
 168  * since multiple copies of pipelines may execute concurrently.
 169  *
 170  * <p>
 171  * If such information is read-only,
 172  * it can be stored as instance variables of a pipe,
 173  * and its reference copied as pipes get copied. (The only difference between
 174  * this and per-thread state is that you just won't allocate new things when
 175  * pipes get copied here.)
 176  *
 177  *
 178  * <h3>VM-wide state</h3>
 179  * <p>
 180  * <tt>static</tt> is always there for you to use.
 181  *
 182  *
 183  *
 184  * <h2>Pipes and Handlers</h2>
 185  * <p>
 186  * JAX-WS has a notion of {@link LogicalHandler} and {@link SOAPHandler}, and
 187  * we intend to have one {@link Pipe} implementation that invokes all the
 188  * {@link LogicalHandler}s and another {@link Pipe} implementation that invokes
 189  * all the {@link SOAPHandler}s. Those implementations need to convert a {@link Message}
 190  * into an appropriate format, but grouping all the handlers together eliminates
 191  * the intermediate {@link Message} instanciation between such handlers.
 192  * <p>
 193  * This grouping also allows such implementations to follow the event notifications
 194  * to handlers (i.e. {@link Handler#close(MessageContext)} method.
 195  *
 196  *
 197  * <pre>
 198  * TODO: Possible types of pipe:
 199  *      creator: create message from wire
 200  *          to SAAJ SOAP message
 201  *          to cached representation
 202  *          directly to JAXB beans
 203  *      transformer: transform message from one representation to another
 204  *          JAXB beans to encoded SOAP message
 205  *          StAX writing + JAXB bean to encoded SOAP message
 206  *      modifier: modify message
 207  *          add SOAP header blocks
 208  *          security processing
 209  *      header block processor:
 210  *          process certain SOAP header blocks
 211  *      outbound initiator: input from the client
 212  *          Manage input e.g. JAXB beans and associated with parts of the SOAP message
 213  *      inbound invoker: invoke the service
 214  *         Inkoke SEI, e.g. EJB or SEI in servlet.
 215  * </pre>
 216  *
 217  * @see AbstractPipeImpl
 218  * @see AbstractFilterPipeImpl
 219  * @deprecated
 220  *      Use {@link Tube}.
 221  */
 222 public interface Pipe {
 223     /**
 224      * Sends a {@link Packet} and returns a response {@link Packet} to it.
 225      *
 226      * @throws WebServiceException
 227      *      On the server side, this signals an error condition where
 228      *      a fault reply is in order (or the exception gets eaten by
 229      *      the top-most transport {@link Pipe} if it's one-way.)
 230      *      This frees each {@link Pipe} from try/catching a
 231      *      {@link WebServiceException} in every layer.
 232      *
 233      *      Note that this method is also allowed to return a {@link Packet}
 234      *      that has a fault as the payload.
 235      *
 236      *      <p>
 237      *      On the client side, the {@link WebServiceException} thrown
 238      *      will be propagated all the way back to the calling client
 239      *      applications. (The consequence of that is that if you are
 240      *      a filtering {@link Pipe}, you must not catch the exception
 241      *      that your next {@link Pipe} threw.
 242      *
 243      * @throws RuntimeException
 244      *      Other runtime exception thrown by this method must
 245      *      be treated as a bug in the pipe implementation,
 246      *      and therefore should not be converted into a fault.
 247      *      (Otherwise it becomes very difficult to debug implementation
 248      *      problems.)
 249      *
 250      *      <p>
 251      *      On the server side, this exception should be most likely
 252      *      just logged. On the client-side it gets propagated to the
 253      *      client application.
 254      *
 255      *      <p>
 256      *      The consequence of this is that if a pipe calls
 257      *      into an user application (such as {@link SOAPHandler}
 258      *      or {@link LogicalHandler}), where a {@link RuntimeException}
 259      *      is *not* a bug in the JAX-WS implementation, it must be catched
 260      *      and wrapped into a {@link WebServiceException}.
 261      *
 262      * @param request
 263      *      The packet that represents a request message. Must not be null.
 264      *      If the packet has a non-null message, it must be a valid
 265      *      unconsumed {@link Message}. This message represents the
 266      *      SOAP message to be sent as a request.
 267      *      <p>
 268      *      The packet is also allowed to carry no message, which indicates
 269      *      that this is an output-only request.
 270      *      (that's called "solicit", right? - KK)
 271      *
 272      * @return
 273      *      The packet that represents a response message. Must not be null.
 274      *      If the packet has a non-null message, it must be
 275      *      a valid unconsumed {@link Message}. This message represents
 276      *      a response to the request message passed as a parameter.
 277      *      <p>
 278      *      The packet is also allowed to carry no message, which indicates
 279      *      that there was no response. This is used for things like
 280      *      one-way message and/or one-way transports.
 281      */
 282     Packet process( Packet request);
 283 
 284     /**
 285      * Invoked before the last copy of the pipeline is about to be discarded,
 286      * to give {@link Pipe}s a chance to clean up any resources.
 287      *
 288      * <p>
 289      * This can be used to invoke {@link PreDestroy} lifecycle methods
 290      * on user handler. The invocation of it is optional on the client side,
 291      * but mandatory on the server side.
 292      *
 293      * <p>
 294      * When multiple copies of pipelines are created, this method is called
 295      * only on one of them.
 296      *
 297      * @throws WebServiceException
 298      *      If the clean up fails, {@link WebServiceException} can be thrown.
 299      *      This exception will be propagated to users (if this is client),
 300      *      or recorded (if this is server.)
 301      */
 302     void preDestroy();
 303 
 304     /**
 305      * Creates an identical clone of this {@link Pipe}.
 306      *
 307      * <p>
 308      * This method creates an identical pipeline that can be used
 309      * concurrently with this pipeline. When the caller of a pipeline
 310      * is multi-threaded and need concurrent use of the same pipeline,
 311      * it can do so by creating copies through this method.
 312      *
 313      * <h3>Implementation Note</h3>
 314      * <p>
 315      * It is the implementation's responsibility to call
 316      * {@link PipeCloner#add(Pipe,Pipe)} to register the copied pipe
 317      * with the original. This is required before you start copying
 318      * the other {@link Pipe} references you have, or else there's a
 319      * risk of infinite recursion.
 320      * <p>
 321      * For most {@link Pipe} implementations that delegate to another
 322      * {@link Pipe}, this method requires that you also copy the {@link Pipe}
 323      * that you delegate to.
 324      * <p>
 325      * For limited number of {@link Pipe}s that do not maintain any
 326      * thread unsafe resource, it is allowed to simply return <tt>this</tt>
 327      * from this method (notice that even if you are stateless, if you
 328      * got a delegating {@link Pipe} and that one isn't stateless, you
 329      * still have to copy yourself.)
 330      *
 331      * <p>
 332      * Note that this method might be invoked by one thread while another
 333      * thread is executing the {@link #process(Packet)} method. See
 334      * the {@link Codec#copy()} for more discussion about this.
 335      *
 336      * @param cloner
 337      *      Use this object (in particular its {@link PipeCloner#copy(Pipe)} method
 338      *      to clone other pipe references you have
 339      *      in your pipe. See {@link PipeCloner} for more discussion
 340      *      about why.
 341      *
 342      * @return
 343      *      always non-null {@link Pipe}.
 344      */
 345     Pipe copy(PipeCloner cloner);
 346 }