src/share/jaxws_classes/com/sun/xml/internal/ws/api/pipe/Tube.java

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

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

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.api.pipe;
aoqi@0 27
aoqi@0 28 import com.sun.istack.internal.NotNull;
aoqi@0 29 import com.sun.xml.internal.ws.api.message.Message;
aoqi@0 30 import com.sun.xml.internal.ws.api.message.Packet;
aoqi@0 31 import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl;
aoqi@0 32 import com.sun.xml.internal.ws.api.pipe.helper.AbstractTubeImpl;
aoqi@0 33 import com.sun.xml.internal.ws.api.server.Adapter;
aoqi@0 34
aoqi@0 35 import javax.annotation.PreDestroy;
aoqi@0 36 import javax.xml.ws.Dispatch;
aoqi@0 37 import javax.xml.ws.Provider;
aoqi@0 38 import javax.xml.ws.WebServiceException;
aoqi@0 39 import javax.xml.ws.handler.LogicalHandler;
aoqi@0 40 import javax.xml.ws.handler.soap.SOAPHandler;
aoqi@0 41 import java.text.SimpleDateFormat;
aoqi@0 42
aoqi@0 43 /**
aoqi@0 44 * Abstraction of the intermediate layers in the processing chain
aoqi@0 45 * and transport.
aoqi@0 46 *
aoqi@0 47 * <h2>What is a {@link Tube}?</h2>
aoqi@0 48 * <p>
aoqi@0 49 * {@link Tube} is a basic processing unit that represents SOAP-level
aoqi@0 50 * protocol handling code. Mutliple tubes are often put together in
aoqi@0 51 * a line (it needs not one dimensional &mdash; more later), and act on
aoqi@0 52 * {@link Packet}s in a sequential fashion.
aoqi@0 53 *
aoqi@0 54 * <p>
aoqi@0 55 * {@link Tube}s run asynchronously. That is, there is no guarantee that
aoqi@0 56 * {@link #processRequest(Packet)} and {@link #processResponse(Packet)} runs
aoqi@0 57 * in the same thread, nor is there any guarantee that this tube and next
aoqi@0 58 * tube runs in the same thread. Furthermore, one thread may be used to
aoqi@0 59 * run multiple pipeline in turn (just like a real CPU runs multiple
aoqi@0 60 * threads in turn.)
aoqi@0 61 *
aoqi@0 62 *
aoqi@0 63 * <h2>Tube examples</h2>
aoqi@0 64 * <p>
aoqi@0 65 * Transport is a kind of tube. It sends the {@link Packet}
aoqi@0 66 * through, say, HTTP connection, and receives the data back into another {@link Packet}.
aoqi@0 67 *
aoqi@0 68 * <p>
aoqi@0 69 * More often, a tube works like a filter. It acts on a packet,
aoqi@0 70 * and then it tells the JAX-WS that the packet should be passed into another
aoqi@0 71 * tube. It can do the same on the way back.
aoqi@0 72 *
aoqi@0 73 * <p>
aoqi@0 74 * For example, XWSS will be a {@link Tube}. It will act on a request
aoqi@0 75 * {@link Packet}, then perhaps wrap it into
aoqi@0 76 * another {@link Packet} to encrypt the body and add a header, then
aoqi@0 77 * the processing will go on to the next tube.
aoqi@0 78 *
aoqi@0 79 * <p>
aoqi@0 80 * Yet another kind of filter tube is those that wraps {@link LogicalHandler}
aoqi@0 81 * and {@link SOAPHandler}. These tubes are heavy-weight; they often consume
aoqi@0 82 * a message in a packet and create a new one, and then pass it to the next tube.
aoqi@0 83 *
aoqi@0 84 * <p>
aoqi@0 85 * There would be a {@link Tube} implementation that invokes {@link Provider}.
aoqi@0 86 * There would be a {@link Tube} implementation that invokes a service method
aoqi@0 87 * on the user's code.
aoqi@0 88 * There would be a {@link Dispatch} implementation that invokes a {@link Tube}.
aoqi@0 89 *
aoqi@0 90 * <p>
aoqi@0 91 * WS-MEX can be implemented as a {@link Tube} that looks for
aoqi@0 92 * {@link Message#getPayloadNamespaceURI()} and serves the request.
aoqi@0 93 *
aoqi@0 94 *
aoqi@0 95 *
aoqi@0 96 *
aoqi@0 97 * <h2>Tube Lifecycle</h2>
aoqi@0 98 * Pipeline is expensive to set up, so once it's created it will be reused.
aoqi@0 99 * A pipeline is not reentrant; one pipeline is used to process one request/response
aoqi@0 100 * at at time. The same pipeline instance may serve multiple request/response,
aoqi@0 101 * if one comes after another and they don't overlap.
aoqi@0 102 * <p>
aoqi@0 103 * Where a need arises to process multiple requests concurrently, a pipeline
aoqi@0 104 * gets cloned through {@link TubeCloner}. Note that this need may happen on
aoqi@0 105 * both server (because it quite often serves multiple requests concurrently)
aoqi@0 106 * and client (because it needs to support asynchronous method invocations.)
aoqi@0 107 * <p>
aoqi@0 108 * Created pipelines (including cloned ones and the original) may be discarded and GC-ed
aoqi@0 109 * at any time at the discretion of whoever owns pipelines. Tubes can, however, expect
aoqi@0 110 * at least one copy (or original) of pipeline to live at any given time while a pipeline
aoqi@0 111 * owner is interested in the given pipeline configuration (in more concerete terms,
aoqi@0 112 * for example, as long as a dispatch object lives, it's going to keep at least one
aoqi@0 113 * copy of a pipeline alive.)
aoqi@0 114 * <p>
aoqi@0 115 * Before a pipeline owner dies, it may invoke {@link #preDestroy()} on the last
aoqi@0 116 * remaining pipeline. It is "may" for pipeline owners that live in the client-side
aoqi@0 117 * of JAX-WS (such as dispatches and proxies), but it is a "must" for pipeline owners
aoqi@0 118 * that live in the server-side of JAX-WS.
aoqi@0 119 * <p>
aoqi@0 120 * This last invocation gives a chance for some pipes to clean up any state/resource
aoqi@0 121 * acquired (such as WS-RM's sequence, WS-Trust's SecurityToken), although as stated above,
aoqi@0 122 * this is not required for clients.
aoqi@0 123 *
aoqi@0 124 *
aoqi@0 125 *
aoqi@0 126 * <h2>Tube and state</h2>
aoqi@0 127 * <p>
aoqi@0 128 * The lifecycle of pipelines is designed to allow a {@link Tube} to store various
aoqi@0 129 * state in easily accessible fashion.
aoqi@0 130 *
aoqi@0 131 *
aoqi@0 132 * <h3>Per-packet state</h3>
aoqi@0 133 * <p>
aoqi@0 134 * Any information that changes from a packet to packet should be
aoqi@0 135 * stored in {@link Packet} (if such informaton is specific to your problem domain,
aoqi@0 136 * then most likely {@link Packet#invocationProperties}.)
aoqi@0 137 * This includes information like transport-specific headers.
aoqi@0 138 *
aoqi@0 139 * <h3>Per-thread state</h3>
aoqi@0 140 * <p>
aoqi@0 141 * Any expensive-to-create objects that are non-reentrant can be stored
aoqi@0 142 * either in instance variables of a {@link Tube}, or a static {@link ThreadLocal}.
aoqi@0 143 *
aoqi@0 144 * <p>
aoqi@0 145 * The first approach works, because {@link Tube} is
aoqi@0 146 * non reentrant. When a tube is copied, new instances should be allocated
aoqi@0 147 * so that two {@link Tube} instances don't share thread-unsafe resources.
aoqi@0 148 *
aoqi@0 149 * Similarly the second approach works, since {@link ThreadLocal} guarantees
aoqi@0 150 * that each thread gets its own private copy.
aoqi@0 151 *
aoqi@0 152 * <p>
aoqi@0 153 * The former is faster to access, and you need not worry about clean up.
aoqi@0 154 * On the other hand, because there can be many more concurrent requests
aoqi@0 155 * than # of threads, you may end up holding onto more resources than necessary.
aoqi@0 156 *
aoqi@0 157 * <p>
aoqi@0 158 * This includes state like canonicalizers, JAXB unmarshallers,
aoqi@0 159 * {@link SimpleDateFormat}, etc.
aoqi@0 160 *
aoqi@0 161 *
aoqi@0 162 * <h3>Per-proxy/per-endpoint state</h3>
aoqi@0 163 * <p>
aoqi@0 164 * Information that is tied to a particular proxy/dispatch can be stored
aoqi@0 165 * in a separate object that is referenced from a tube. When
aoqi@0 166 * a new tube is copied, you can simply hand out a reference to the newly
aoqi@0 167 * created one, so that all copied tubes refer to the same instance.
aoqi@0 168 * See the following code as an example:
aoqi@0 169 *
aoqi@0 170 * <pre>
aoqi@0 171 * class TubeImpl {
aoqi@0 172 * // this object stores per-proxy state
aoqi@0 173 * class DataStore {
aoqi@0 174 * int counter;
aoqi@0 175 * }
aoqi@0 176 *
aoqi@0 177 * private DataStore ds;
aoqi@0 178 *
aoqi@0 179 * // create a fresh new pipe
aoqi@0 180 * public TubeImpl(...) {
aoqi@0 181 * ....
aoqi@0 182 * ds = new DataStore();
aoqi@0 183 * }
aoqi@0 184 *
aoqi@0 185 * // copy constructor
aoqi@0 186 * private TubeImpl(TubeImpl that, PipeCloner cloner) {
aoqi@0 187 * cloner.add(that,this);
aoqi@0 188 * ...
aoqi@0 189 * this.ds = that.ds;
aoqi@0 190 * }
aoqi@0 191 *
aoqi@0 192 * public TubeImpl copy(PipeCloner pc) {
aoqi@0 193 * return new TubeImpl(this,pc);
aoqi@0 194 * }
aoqi@0 195 * }
aoqi@0 196 * </pre>
aoqi@0 197 *
aoqi@0 198 * <p>
aoqi@0 199 * Note that access to such resource may need to be synchronized,
aoqi@0 200 * since multiple copies of pipelines may execute concurrently.
aoqi@0 201 *
aoqi@0 202 *
aoqi@0 203 *
aoqi@0 204 * <h3>VM-wide state</h3>
aoqi@0 205 * <p>
aoqi@0 206 * <tt>static</tt> is always there for you to use.
aoqi@0 207 *
aoqi@0 208 *
aoqi@0 209 *
aoqi@0 210 * @see AbstractTubeImpl
aoqi@0 211 * @see AbstractFilterTubeImpl
aoqi@0 212 *
aoqi@0 213 * @author Kohsuke Kawaguchi
aoqi@0 214 * @author Jitendra Kotamraju
aoqi@0 215 */
aoqi@0 216 public interface Tube {
aoqi@0 217 /**
aoqi@0 218 * Acts on a request and perform some protocol specific operation.
aoqi@0 219 *
aoqi@0 220 * TODO: exception handling semantics need more discussion
aoqi@0 221 *
aoqi@0 222 * @throws WebServiceException
aoqi@0 223 * On the server side, this signals an error condition where
aoqi@0 224 * a fault reply is in order (or the exception gets eaten by
aoqi@0 225 * the top-most transport {@link Adapter} if it's one-way.)
aoqi@0 226 * This frees each {@link Tube} from try/catching a
aoqi@0 227 * {@link WebServiceException} in every layer.
aoqi@0 228 *
aoqi@0 229 * Note that this method is also allowed to return
aoqi@0 230 * {@link NextAction#returnWith(Packet)} with
aoqi@0 231 * a {@link Packet} that has a fault as the payload.
aoqi@0 232 *
aoqi@0 233 * <p>
aoqi@0 234 * On the client side, the {@link WebServiceException} thrown
aoqi@0 235 * will be propagated all the way back to the calling client
aoqi@0 236 * applications. (The consequence of that is that if you are
aoqi@0 237 * a filtering {@link Tube}, you must not eat the exception
aoqi@0 238 * that was given to {@link #processException(Throwable)} .
aoqi@0 239 *
aoqi@0 240 * @throws RuntimeException
aoqi@0 241 * Other runtime exception thrown by this method must
aoqi@0 242 * be treated as a bug in the tube implementation,
aoqi@0 243 * and therefore should not be converted into a fault.
aoqi@0 244 * (Otherwise it becomes very difficult to debug implementation
aoqi@0 245 * problems.)
aoqi@0 246 *
aoqi@0 247 * <p>
aoqi@0 248 * On the server side, this exception should be most likely
aoqi@0 249 * just logged. On the client-side it gets propagated to the
aoqi@0 250 * client application.
aoqi@0 251 *
aoqi@0 252 * <p>
aoqi@0 253 * The consequence of this is that if a pipe calls
aoqi@0 254 * into an user application (such as {@link SOAPHandler}
aoqi@0 255 * or {@link LogicalHandler}), where a {@link RuntimeException}
aoqi@0 256 * is *not* a bug in the JAX-WS implementation, it must be catched
aoqi@0 257 * and wrapped into a {@link WebServiceException}.
aoqi@0 258 *
aoqi@0 259 * @param request
aoqi@0 260 * The packet that represents a request message.
aoqi@0 261 * If the packet has a non-null message, it must be a valid
aoqi@0 262 * unconsumed {@link Message}. This message represents the
aoqi@0 263 * SOAP message to be sent as a request.
aoqi@0 264 * <p>
aoqi@0 265 * The packet is also allowed to carry no message, which indicates
aoqi@0 266 * that this is an output-only request.
aoqi@0 267 * (that's called "solicit", right? - KK)
aoqi@0 268 *
aoqi@0 269 * @return
aoqi@0 270 * A {@link NextAction} object that represents the next action
aoqi@0 271 * to be taken by the JAX-WS runtime.
aoqi@0 272 */
aoqi@0 273 @NotNull NextAction processRequest(@NotNull Packet request);
aoqi@0 274
aoqi@0 275 /**
aoqi@0 276 * Acts on a response and performs some protocol specific operation.
aoqi@0 277 *
aoqi@0 278 * <p>
aoqi@0 279 * Once a {@link #processRequest(Packet)} is invoked, this method
aoqi@0 280 * will be always invoked with the response, before this {@link Tube}
aoqi@0 281 * processes another request.
aoqi@0 282 *
aoqi@0 283 * @param response
aoqi@0 284 * If the packet has a non-null message, it must be
aoqi@0 285 * a valid unconsumed {@link Message}. This message represents
aoqi@0 286 * a response to the request message passed to
aoqi@0 287 * {@link #processRequest(Packet)} earlier.
aoqi@0 288 * <p>
aoqi@0 289 * The packet is also allowed to carry no message, which indicates
aoqi@0 290 * that there was no response. This is used for things like
aoqi@0 291 * one-way message and/or one-way transports.
aoqi@0 292 *
aoqi@0 293 * TODO: exception handling semantics need more discussion
aoqi@0 294 *
aoqi@0 295 * @return
aoqi@0 296 * A {@link NextAction} object that represents the next action
aoqi@0 297 * to be taken by the JAX-WS runtime.
aoqi@0 298 */
aoqi@0 299 @NotNull NextAction processResponse(@NotNull Packet response);
aoqi@0 300
aoqi@0 301
aoqi@0 302 /**
aoqi@0 303 * Acts on a exception and performs some clean up operations.
aoqi@0 304 *
aoqi@0 305 * <p>
aoqi@0 306 * If a {@link #processRequest(Packet)}, {@link #processResponse(Packet)},
aoqi@0 307 * {@link #processException(Throwable)} throws an exception, this method
aoqi@0 308 * will be always invoked on all the {@link Tube}s in the remaining
aoqi@0 309 * {@link NextAction}s.
aoqi@0 310 *
aoqi@0 311 * <p>
aoqi@0 312 * On the server side, the {@link Throwable} thrown will be propagated to the
aoqi@0 313 * top-most transport. The transport converts the exception to fault reply or
aoqi@0 314 * simply logs in case of one-way MEP. If you are a filtering {@link Tube} like
aoqi@0 315 * {@link AbstractTubeImpl}, you don't have to override the implementation). On
aoqi@0 316 * the other hand, any intermediate {@link Tube} may want to convert the exception
aoqi@0 317 * to a fault message.
aoqi@0 318 *
aoqi@0 319 * <p>
aoqi@0 320 * On the client side, the {@link Throwable} thrown
aoqi@0 321 * will be propagated all the way back to the calling client
aoqi@0 322 * applications. (The consequence of that is that if you are
aoqi@0 323 * a filtering {@link Tube} like {@link AbstractTubeImpl}, you don't have to
aoqi@0 324 * override the implementation)
aoqi@0 325 *
aoqi@0 326 * @param t
aoqi@0 327 *
aoqi@0 328 * @return
aoqi@0 329 * A {@link NextAction} object that represents the next action
aoqi@0 330 * to be taken by the JAX-WS runtime.
aoqi@0 331 */
aoqi@0 332 @NotNull NextAction processException(@NotNull Throwable t);
aoqi@0 333
aoqi@0 334 /**
aoqi@0 335 * Invoked before the last copy of the pipeline is about to be discarded,
aoqi@0 336 * to give {@link Tube}s a chance to clean up any resources.
aoqi@0 337 *
aoqi@0 338 * <p>
aoqi@0 339 * This can be used to invoke {@link PreDestroy} lifecycle methods
aoqi@0 340 * on user handler. The invocation of it is optional on the client side,
aoqi@0 341 * but mandatory on the server side.
aoqi@0 342 *
aoqi@0 343 * <p>
aoqi@0 344 * When multiple copies of pipelines are created, this method is called
aoqi@0 345 * only on one of them.
aoqi@0 346 *
aoqi@0 347 * @throws WebServiceException
aoqi@0 348 * If the clean up fails, {@link WebServiceException} can be thrown.
aoqi@0 349 * This exception will be propagated to users (if this is client),
aoqi@0 350 * or recorded (if this is server.)
aoqi@0 351 */
aoqi@0 352 void preDestroy();
aoqi@0 353
aoqi@0 354 /**
aoqi@0 355 * Creates an identical clone of this {@link Tube}.
aoqi@0 356 *
aoqi@0 357 * <p>
aoqi@0 358 * This method creates an identical pipeline that can be used
aoqi@0 359 * concurrently with this pipeline. When the caller of a pipeline
aoqi@0 360 * is multi-threaded and need concurrent use of the same pipeline,
aoqi@0 361 * it can do so by creating copies through this method.
aoqi@0 362 *
aoqi@0 363 * <h3>Implementation Note</h3>
aoqi@0 364 * <p>
aoqi@0 365 * It is the implementation's responsibility to call
aoqi@0 366 * {@link TubeCloner#add(Tube,Tube)} to register the copied pipe
aoqi@0 367 * with the original. This is required before you start copying
aoqi@0 368 * the other {@link Tube} references you have, or else there's a
aoqi@0 369 * risk of infinite recursion.
aoqi@0 370 * <p>
aoqi@0 371 * For most {@link Tube} implementations that delegate to another
aoqi@0 372 * {@link Tube}, this method requires that you also copy the {@link Tube}
aoqi@0 373 * that you delegate to.
aoqi@0 374 * <p>
aoqi@0 375 * For limited number of {@link Tube}s that do not maintain any
aoqi@0 376 * thread unsafe resource, it is allowed to simply return <tt>this</tt>
aoqi@0 377 * from this method (notice that even if you are stateless, if you
aoqi@0 378 * got a delegating {@link Tube} and that one isn't stateless, you
aoqi@0 379 * still have to copy yourself.)
aoqi@0 380 *
aoqi@0 381 * <p>
aoqi@0 382 * Note that this method might be invoked by one thread while another
aoqi@0 383 * thread is executing the other process method. See
aoqi@0 384 * the {@link Codec#copy()} for more discussion about this.
aoqi@0 385 *
aoqi@0 386 * @param cloner
aoqi@0 387 * Use this object (in particular its {@link TubeCloner#copy(Tube)} method
aoqi@0 388 * to clone other pipe references you have
aoqi@0 389 * in your pipe. See {@link TubeCloner} for more discussion
aoqi@0 390 * about why.
aoqi@0 391 *
aoqi@0 392 * @return
aoqi@0 393 * always non-null {@link Tube}.
aoqi@0 394 */
aoqi@0 395 Tube copy(TubeCloner cloner);
aoqi@0 396 }

mercurial