KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > celtix > bus > handlers > HandlerChainInvoker


1 package org.objectweb.celtix.bus.handlers;
2
3
4 import java.util.ArrayList JavaDoc;
5 import java.util.Collections JavaDoc;
6 import java.util.List JavaDoc;
7 import java.util.logging.Level JavaDoc;
8 import java.util.logging.Logger JavaDoc;
9
10 import javax.xml.ws.ProtocolException;
11 import javax.xml.ws.handler.Handler;
12 import javax.xml.ws.handler.LogicalHandler;
13 import javax.xml.ws.handler.MessageContext;
14
15 import org.objectweb.celtix.bus.context.LogicalMessageContextImpl;
16 import org.objectweb.celtix.bus.context.StreamMessageContextImpl;
17 import org.objectweb.celtix.common.logging.LogUtils;
18 import org.objectweb.celtix.context.InputStreamMessageContext;
19 import org.objectweb.celtix.context.ObjectMessageContext;
20 import org.objectweb.celtix.context.OutputStreamMessageContext;
21 import org.objectweb.celtix.context.WebServiceContextImpl;
22 import org.objectweb.celtix.handlers.HandlerInvoker;
23 import org.objectweb.celtix.handlers.StreamHandler;
24
25 /**
26  * invoke invoke the handlers in a registered handler chain
27  *
28  */

29 public class HandlerChainInvoker implements HandlerInvoker {
30
31     private static final Logger JavaDoc LOG = LogUtils.getL7dLogger(HandlerChainInvoker.class);
32
33     private final List JavaDoc<Handler> protocolHandlers = new ArrayList JavaDoc<Handler>();
34     private List JavaDoc<LogicalHandler> logicalHandlers = new ArrayList JavaDoc<LogicalHandler>();
35     private final List JavaDoc<StreamHandler> streamHandlers = new ArrayList JavaDoc<StreamHandler>();
36     private final List JavaDoc<Handler> invokedHandlers = new ArrayList JavaDoc<Handler>();
37     private final List JavaDoc<Handler> closeHandlers = new ArrayList JavaDoc<Handler>();
38
39     private boolean outbound;
40     private boolean responseExpected = true;
41     private boolean faultExpected;
42     private boolean handlerProcessingAborted;
43     private boolean closed;
44
45     public HandlerChainInvoker(List JavaDoc<Handler> hc) {
46         this(hc, true);
47     }
48
49    
50
51     public HandlerChainInvoker(List JavaDoc<Handler> hc, boolean isOutbound) {
52         if (LOG.isLoggable(Level.FINE)) {
53             LOG.log(Level.FINE, "invoker for chain size: " + (hc != null ? hc.size() : 0));
54         }
55         
56         if (hc != null) {
57             for (Handler h : hc) {
58                 if (h instanceof LogicalHandler) {
59                     logicalHandlers.add((LogicalHandler)h);
60                 } else if (h instanceof StreamHandler) {
61                     streamHandlers.add((StreamHandler)h);
62                 } else {
63                     protocolHandlers.add(h);
64                 }
65             }
66         }
67         outbound = isOutbound;
68     }
69
70     public boolean invokeLogicalHandlers(boolean requestor, ObjectMessageContext objectCtx) {
71         objectCtx.setRequestorRole(requestor);
72         objectCtx.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, isOutbound());
73         LogicalMessageContextImpl logicalContext = new LogicalMessageContextImpl(objectCtx);
74         return invokeHandlerChain(logicalHandlers, logicalContext);
75
76     }
77         
78     public boolean invokeProtocolHandlers(boolean requestor, MessageContext bindingContext) {
79         bindingContext.put(ObjectMessageContext.REQUESTOR_ROLE_PROPERTY, requestor);
80         bindingContext.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, isOutbound());
81
82         return invokeHandlerChain(protocolHandlers, bindingContext);
83     }
84     
85     public boolean invokeStreamHandlers(InputStreamMessageContext ctx) {
86         StreamMessageContextImpl sctx = new StreamMessageContextImpl(ctx);
87         sctx.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, this.outbound);
88         // return invokeHandlerChain(streamHandlers, new StreamMessageContextImpl(ctx));
89
return invokeHandlerChain(streamHandlers, sctx);
90     }
91     
92     public boolean invokeStreamHandlers(OutputStreamMessageContext ctx) {
93         StreamMessageContextImpl sctx = new StreamMessageContextImpl(ctx);
94         sctx.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, this.outbound);
95         return invokeHandlerChain(streamHandlers, sctx);
96     }
97         
98     public void closeHandlers() {
99         //nothing to do
100
}
101     
102     public void setResponseExpected(boolean expected) {
103         responseExpected = expected;
104     }
105
106     public boolean isResponseExpected() {
107         return responseExpected;
108     }
109
110     public boolean isOutbound() {
111         return outbound;
112     }
113     
114     public boolean isInbound() {
115         return !outbound;
116     }
117     
118     public void setInbound() {
119         outbound = false;
120     }
121
122     public void setOutbound() {
123         outbound = true;
124     }
125
126
127     public boolean faultRaised(MessageContext context) {
128         return (null != context && null != context.get(ObjectMessageContext.METHOD_FAULT))
129             || faultExpected;
130     }
131
132     public void setFault(boolean fe) {
133         faultExpected = fe;
134     }
135
136     /** Invoke handlers at the end of an MEP calling close on each.
137      * The handlers must be invoked in the reverse order that they
138      * appear in the handler chain. On the server side this will not
139      * be the reverse order in which they were invoked so use the
140      * handler chain directly and not simply the invokedHandler list.
141      */

142     public void mepComplete(MessageContext context) {
143         if (LOG.isLoggable(Level.FINE)) {
144             LOG.log(Level.FINE, "closing protocol handlers - handler count:" + invokedHandlers.size());
145         }
146         invokeClose(protocolHandlers, context);
147         invokeClose(logicalHandlers, context);
148         invokeClose(streamHandlers, context);
149     }
150
151
152     /** Indicates that the invoker is closed. When closed, only @see
153      * #mepComplete may be called. The invoker will become closed if
154      * during a invocation of handlers, a handler throws a runtime
155      * exception that is not a protocol exception and no futher
156      * handler or message processing is possible.
157      *
158      */

159     public boolean isClosed() {
160         return closed;
161     }
162     
163     /**
164      * Allows an the logical handler chain for one invoker to be used
165      * as an alternate chain for another.
166      *
167      * @param invoker the invoker encalsulting the alternate logical handler
168      * chain
169      */

170     public void adoptLogicalHandlers(HandlerInvoker invoker) {
171         logicalHandlers = ((HandlerChainInvoker)invoker).getLogicalHandlers();
172     }
173
174     List JavaDoc getInvokedHandlers() {
175         return Collections.unmodifiableList(invokedHandlers);
176     }
177
178     public List JavaDoc<LogicalHandler> getLogicalHandlers() {
179         return logicalHandlers;
180     }
181
182     List JavaDoc<Handler> getProtocolHandlers() {
183         return protocolHandlers;
184     }
185
186     List JavaDoc<? extends Handler> getStreamHandlers() {
187         return streamHandlers;
188     }
189     
190     private <T extends Handler> void invokeClose(List JavaDoc<T> handlers, MessageContext context) {
191         handlers = reverseHandlerChain(handlers);
192         for (Handler h : handlers) {
193             if (closeHandlers.contains(h)) {
194                 h.close(context);
195             }
196         }
197     }
198
199     private boolean invokeHandlerChain(List JavaDoc<? extends Handler> handlerChain, MessageContext ctx) {
200         if (handlerChain.isEmpty()) {
201             LOG.log(Level.FINEST, "no handlers registered");
202             return true;
203         }
204
205         if (isClosed()) {
206             return false;
207         }
208
209         if (LOG.isLoggable(Level.FINE)) {
210             LOG.log(Level.FINE, "invoking handlers, direction: " + (outbound ? "outbound" : "inbound"));
211         }
212         setMessageOutboundProperty(ctx);
213
214         if (!outbound) {
215             handlerChain = reverseHandlerChain(handlerChain);
216         }
217         
218         boolean continueProcessing = true;
219         
220         WebServiceContextImpl.setMessageContext(ctx);
221
222         if (!faultRaised(ctx)) {
223             continueProcessing = invokeHandleMessage(handlerChain, ctx);
224         } else {
225             continueProcessing = invokeHandleFault(handlerChain, ctx);
226         }
227
228         if (!continueProcessing) {
229             // stop processing handlers, change direction and return
230
// control to the bindng. Then the binding will invoke on
231
// the next set on handlers and they will be processing in
232
// the correct direction. It would be good refactor it
233
// and control all of the processing here.
234
changeMessageDirection(ctx);
235             handlerProcessingAborted = true;
236         }
237         return continueProcessing;
238     }
239
240     @SuppressWarnings JavaDoc("unchecked")
241     private boolean invokeHandleFault(List JavaDoc<? extends Handler> handlerChain, MessageContext ctx) {
242         
243         boolean continueProcessing = true;
244
245         try {
246             for (Handler<MessageContext> h : handlerChain) {
247                 if (invokeThisHandler(h)) {
248                     closeHandlers.add(h);
249                     continueProcessing = h.handleFault(ctx);
250                 }
251                 if (!continueProcessing) {
252                     break;
253                 }
254                 markHandlerInvoked(h);
255             }
256         } catch (RuntimeException JavaDoc e) {
257             LOG.log(Level.WARNING, "HANDLER_RAISED_RUNTIME_EXCEPTION", e);
258             continueProcessing = false;
259             closed = true;
260         }
261         return continueProcessing;
262     }
263
264
265     @SuppressWarnings JavaDoc("unchecked")
266     private boolean invokeHandleMessage(List JavaDoc<? extends Handler> handlerChain, MessageContext ctx) {
267
268         boolean continueProcessing = true;
269         try {
270             for (Handler h : handlerChain) {
271                 if (invokeThisHandler(h)) {
272                     closeHandlers.add(h);
273                     continueProcessing = h.handleMessage(ctx);
274                 }
275                 if (!continueProcessing) {
276                     break;
277                 }
278                 markHandlerInvoked(h);
279             }
280         } catch (ProtocolException e) {
281             LOG.log(Level.FINE, "handleMessage raised exception", e);
282             continueProcessing = false;
283             setFault(ctx, e);
284         } catch (RuntimeException JavaDoc e) {
285             LOG.log(Level.WARNING, "HANDLER_RAISED_RUNTIME_EXCEPTION", e);
286             continueProcessing = false;
287             closed = true;
288         }
289         return continueProcessing;
290     }
291
292     
293     private boolean invokeThisHandler(Handler h) {
294         boolean ret = true;
295         // when handler processing has been aborted, only invoked on
296
// previously invoked handlers
297
//
298
if (handlerProcessingAborted) {
299             ret = invokedHandlers.contains(h);
300         }
301         if (ret && LOG.isLoggable(Level.FINE)) {
302             LOG.log(Level.FINE, "invoking handler of type " + h.getClass().getName());
303         }
304         return ret;
305     }
306
307
308     private void markHandlerInvoked(Handler h) {
309         if (!invokedHandlers.contains(h)) {
310             invokedHandlers.add(h);
311         }
312     }
313
314     private void changeMessageDirection(MessageContext context) {
315         outbound = !outbound;
316         setMessageOutboundProperty(context);
317         context.put(ObjectMessageContext.MESSAGE_INPUT, Boolean.TRUE);
318     }
319     
320     private void setMessageOutboundProperty(MessageContext context) {
321         context.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, this.outbound);
322     }
323     
324     private <T extends Handler> List JavaDoc<T> reverseHandlerChain(List JavaDoc<T> handlerChain) {
325         List JavaDoc<T> reversedHandlerChain = new ArrayList JavaDoc<T>();
326         reversedHandlerChain.addAll(handlerChain);
327         Collections.reverse(reversedHandlerChain);
328         return reversedHandlerChain;
329     }
330     
331     protected final void setFault(MessageContext context, Exception JavaDoc ex) {
332         context.put(ObjectMessageContext.METHOD_FAULT, ex);
333         context.setScope(ObjectMessageContext.METHOD_FAULT, MessageContext.Scope.HANDLER);
334     }
335 }
336
337
Popular Tags