src/share/jaxws_classes/com/sun/xml/internal/ws/handler/HandlerTube.java

changeset 286
f50545b5e2f1
child 368
0989ad8c0860
equal deleted inserted replaced
284:88b85470e72c 286:f50545b5e2f1
1 /*
2 * Copyright (c) 1997, 2010, 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.handler;
27
28 import com.sun.istack.internal.Nullable;
29 import com.sun.xml.internal.ws.api.WSBinding;
30 import com.sun.xml.internal.ws.api.message.Packet;
31 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
32 import com.sun.xml.internal.ws.api.pipe.*;
33 import com.sun.xml.internal.ws.api.pipe.helper.AbstractFilterTubeImpl;
34 import com.sun.xml.internal.ws.binding.BindingImpl;
35 import com.sun.xml.internal.ws.client.HandlerConfiguration;
36
37 import javax.xml.ws.handler.MessageContext;
38 import javax.xml.ws.handler.Handler;
39 import java.util.List;
40
41 /**
42 * @author WS Development team
43 */
44
45 public abstract class HandlerTube extends AbstractFilterTubeImpl {
46 /**
47 * handle hold reference to other Tube for inter-tube communication
48 */
49 HandlerTube cousinTube;
50 protected List<Handler> handlers;
51 HandlerProcessor processor;
52 boolean remedyActionTaken = false;
53 protected final @Nullable WSDLPort port;
54 // flag used to decide whether to call close on cousinTube
55 boolean requestProcessingSucessful = false;
56 private WSBinding binding;
57 private HandlerConfiguration hc;
58
59 public HandlerTube(Tube next, WSDLPort port, WSBinding binding) {
60 super(next);
61 this.port = port;
62 this.binding = binding;
63 }
64
65 public HandlerTube(Tube next, HandlerTube cousinTube, WSBinding binding) {
66 super(next);
67 this.cousinTube = cousinTube;
68 this.binding = binding;
69 if(cousinTube != null) {
70 this.port = cousinTube.port;
71 } else {
72 this.port = null;
73 }
74 }
75
76 /**
77 * Copy constructor for {@link Tube#copy(TubeCloner)}.
78 */
79 protected HandlerTube(HandlerTube that, TubeCloner cloner) {
80 super(that,cloner);
81 if(that.cousinTube != null) {
82 this.cousinTube = cloner.copy(that.cousinTube);
83 }
84 this.port = that.port;
85 this.binding = that.binding;
86 }
87
88 protected WSBinding getBinding() {
89 return binding;
90 }
91
92 @Override
93 public NextAction processRequest(Packet request) {
94 setupExchange();
95 // This check is done to cover handler returning false in Oneway request
96 if (isHandleFalse()) {
97 // Cousin HandlerTube returned false during Oneway Request processing.
98 // Don't call handlers and dispatch the message.
99 remedyActionTaken = true;
100 return doInvoke(super.next, request);
101 }
102
103 // This is done here instead of the constructor, since User can change
104 // the roles and handlerchain after a stub/proxy is created.
105 setUpProcessorInternal();
106
107 MessageUpdatableContext context = getContext(request);
108 boolean isOneWay = checkOneWay(request);
109 try {
110 if (!isHandlerChainEmpty()) {
111 // Call handlers on Request
112 boolean handlerResult = callHandlersOnRequest(context, isOneWay);
113 //Update Packet with user modifications
114 context.updatePacket();
115 // two-way case where no message is sent
116 if (!isOneWay && !handlerResult) {
117 return doReturnWith(request);
118 }
119 }
120 requestProcessingSucessful = true;
121 // Call next Tube
122 return doInvoke(super.next, request);
123 } catch (RuntimeException re) {
124 if(isOneWay) {
125 //Eat the exception, its already logged and close the transportBackChannel
126 if(request.transportBackChannel != null ) {
127 request.transportBackChannel.close();
128 }
129 request.setMessage(null);
130 return doReturnWith(request);
131 } else
132 throw re;
133 } finally {
134 if(!requestProcessingSucessful) {
135 initiateClosing(context.getMessageContext());
136 }
137 }
138
139 }
140
141 @Override
142 public NextAction processResponse(Packet response) {
143 setupExchange();
144 MessageUpdatableContext context = getContext(response);
145 try {
146 if (isHandleFalse() || (response.getMessage() == null)) {
147 // Cousin HandlerTube returned false during Response processing.
148 // or it is oneway request
149 // or handler chain is empty
150 // Don't call handlers.
151 return doReturnWith(response);
152 }
153
154 setUpProcessorInternal();
155
156 boolean isFault = isHandleFault(response);
157 if (!isHandlerChainEmpty()) {
158 // Call handlers on Response
159 callHandlersOnResponse(context, isFault);
160 }
161 } finally {
162 initiateClosing(context.getMessageContext());
163 }
164 //Update Packet with user modifications
165 context.updatePacket();
166
167 return doReturnWith(response);
168
169 }
170
171 @Override
172 public NextAction processException(Throwable t) {
173 try {
174 return doThrow(t);
175 } finally {
176 Packet packet = Fiber.current().getPacket();
177 MessageUpdatableContext context = getContext(packet);
178 initiateClosing(context.getMessageContext());
179 /* TODO revisit: commented this out as the modified packet is no longer used
180 In future if the message is propagated even when an exception
181 occurs, then uncomment context.updatePacket();
182 */
183 //Update Packet with user modifications
184 //context.updatePacket();
185
186
187 }
188 }
189
190 /**
191 * Must be overridden by HandlerTube that drives other handler tubes for processing a message.
192 * On Client-side: ClientLogicalHandlerTube drives the Handler Processing.
193 * On Server-side: In case SOAP Binding, ServerMessageHandlerTube drives the Handler Processing.
194 * In case XML/HTTP Binding, ServerLogicalHandlerTube drives the Handler Processing.
195 *
196 *
197 * If its a top HandlerTube, should override by calling #close(MessaggeContext);
198 *
199 */
200
201 protected void initiateClosing(MessageContext mc) {
202 // Do nothing
203
204 }
205
206 /**
207 * Calls close on previously invoked handlers.
208 * Also, Cleans up any state left over in the Tube instance from the current
209 * invocation, as Tube instances can be reused after the completion of MEP.
210 *
211 * On Client, SOAPHandlers are closed first and then LogicalHandlers
212 * On Server, LogicalHandlers are closed first and then SOAPHandlers
213 */
214 final public void close(MessageContext msgContext) {
215 //assuming cousinTube is called if requestProcessingSucessful is true
216 if (requestProcessingSucessful) {
217 if (cousinTube != null) {
218 cousinTube.close(msgContext);
219 }
220
221 }
222 if (processor != null)
223 closeHandlers(msgContext);
224
225 // Clean up the exchange for next invocation.
226 exchange = null;
227 requestProcessingSucessful = false;
228
229 }
230
231 /**
232 * On Client, Override by calling #closeClientHandlers(MessageContext mc)
233 * On Server, Override by calling #closeServerHandlers(MessageContext mc)
234 * The difference is the order in which they are closed.
235 * @param mc
236 */
237 abstract void closeHandlers(MessageContext mc);
238
239 /**
240 * Called by close(MessageContext mc) in a Client Handlertube
241 */
242 protected void closeClientsideHandlers(MessageContext msgContext) {
243 if (processor == null)
244 return;
245 if (remedyActionTaken) {
246 //Close only invoked handlers in the chain
247
248 //CLIENT-SIDE
249 processor.closeHandlers(msgContext, processor.getIndex(), 0);
250 processor.setIndex(-1);
251 //reset remedyActionTaken
252 remedyActionTaken = false;
253 } else {
254 //Close all handlers in the chain
255
256 //CLIENT-SIDE
257 processor.closeHandlers(msgContext, handlers.size() - 1, 0);
258
259 }
260 }
261
262 /**
263 * Called by close(MessageContext mc) in a Server Handlertube
264 */
265 protected void closeServersideHandlers(MessageContext msgContext) {
266 if (processor == null)
267 return;
268 if (remedyActionTaken) {
269 //Close only invoked handlers in the chain
270
271 //SERVER-SIDE
272 processor.closeHandlers(msgContext, processor.getIndex(), handlers.size() - 1);
273 processor.setIndex(-1);
274 //reset remedyActionTaken
275 remedyActionTaken = false;
276 } else {
277 //Close all handlers in the chain
278
279 //SERVER-SIDE
280 processor.closeHandlers(msgContext, 0, handlers.size() - 1);
281
282 }
283 }
284
285 abstract void callHandlersOnResponse(MessageUpdatableContext context, boolean handleFault);
286
287 abstract boolean callHandlersOnRequest(MessageUpdatableContext context, boolean oneWay);
288
289 private boolean checkOneWay(Packet packet) {
290 if (port != null) {
291 /* we can determine this value from WSDL */
292 return packet.getMessage().isOneWay(port);
293 } else {
294 /*
295 otherwise use this value as an approximation, since this carries
296 the appliation's intention --- whether it was invokeOneway vs invoke,etc.
297 */
298 return !(packet.expectReply != null && packet.expectReply);
299 }
300 }
301
302 private void setUpProcessorInternal() {
303 HandlerConfiguration hc = ((BindingImpl) binding).getHandlerConfig();
304 if (hc != this.hc)
305 resetProcessor();
306 this.hc = hc;
307
308 setUpProcessor();
309 }
310
311 abstract void setUpProcessor();
312
313 protected void resetProcessor() {
314 handlers = null;
315 }
316
317 final public boolean isHandlerChainEmpty() {
318 return handlers.isEmpty();
319 }
320 abstract MessageUpdatableContext getContext(Packet p);
321
322 private boolean isHandleFault(Packet packet) {
323 if (cousinTube != null) {
324 return exchange.isHandleFault();
325 } else {
326 boolean isFault = packet.getMessage().isFault();
327 exchange.setHandleFault(isFault);
328 return isFault;
329 }
330 }
331
332 final void setHandleFault() {
333 exchange.setHandleFault(true);
334 }
335
336 private boolean isHandleFalse() {
337 return exchange.isHandleFalse();
338 }
339
340 final void setHandleFalse() {
341 exchange.setHandleFalse();
342 }
343
344 private void setupExchange() {
345 if(exchange == null) {
346 exchange = new HandlerTubeExchange();
347 if(cousinTube != null) {
348 cousinTube.exchange = exchange;
349 }
350 } else {
351 if(cousinTube != null) {
352 cousinTube.exchange = exchange;
353 }
354
355 }
356 }
357 private HandlerTubeExchange exchange;
358
359 /**
360 * This class is used primarily to exchange information or status between
361 * LogicalHandlerTube and SOAPHandlerTube
362 */
363 static final class HandlerTubeExchange {
364 private boolean handleFalse;
365 private boolean handleFault;
366
367 boolean isHandleFault() {
368 return handleFault;
369 }
370
371 void setHandleFault(boolean isFault) {
372 this.handleFault = isFault;
373 }
374
375 public boolean isHandleFalse() {
376 return handleFalse;
377 }
378
379 void setHandleFalse() {
380 this.handleFalse = true;
381 }
382 }
383
384 }

mercurial