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