1
2
3
4
5
6
7
8
9
10 package nl.openedge.baritus;
11
12 import java.io.IOException;
13
14 import javax.servlet.RequestDispatcher;
15 import javax.servlet.ServletException;
16 import javax.servlet.http.HttpServletRequest;
17
18 import nl.openedge.baritus.interceptors.AfterPerformInterceptor;
19 import nl.openedge.baritus.interceptors.AfterPopulationInterceptor;
20 import nl.openedge.baritus.interceptors.BeforeMakeFormBeanInterceptor;
21 import nl.openedge.baritus.interceptors.BeforePopulationInterceptor;
22 import nl.openedge.baritus.interceptors.DispatchNowFlowException;
23 import nl.openedge.baritus.interceptors.FlowException;
24 import nl.openedge.baritus.interceptors.Interceptor;
25 import nl.openedge.baritus.interceptors.PerformExceptionInterceptor;
26 import nl.openedge.baritus.interceptors.PopulationErrorInterceptor;
27 import nl.openedge.baritus.interceptors.ReturnNowFlowException;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.infohazard.maverick.flow.ControllerContext;
32
33 /***
34 * Delegate for handling interceptor actions.
35 *
36 * @author Eelco Hillenius
37 */
38 final class InterceptorDelegate
39 {
40
41 private InterceptorRegistry interceptorRegistry = null;
42
43
44 private static Log intercLog = LogFactory.getLog(LogConstants.INTERCEPTION_LOG);
45
46 private final static int LEVEL_BEFORE_MAKE_FORMBEAN = 0;
47 private final static int LEVEL_BEFORE_POPULATION = 1;
48 private final static int LEVEL_POPULATION_ERROR = 2;
49 private final static int LEVEL_AFTER_POPULATION = 3;
50 private final static int LEVEL_PERFORM_EXCEPTION = 4;
51 private final static int LEVEL_AFTER_PERFORM = 5;
52
53 /***
54 * Construct the delegate with an instance of the interceptor registry.
55 *
56 * @param interceptorRegistry the interceptor registry
57 */
58 public InterceptorDelegate(InterceptorRegistry interceptorRegistry)
59 {
60 this.interceptorRegistry = interceptorRegistry;
61 }
62
63 //***************************** interceptors ******************************************/
64
65
66
67
68
69
70
71
72
73 /***
74 * Called before any handling like form population etc.
75 *
76 * @param cctx maverick context
77 * @param formBeanContext context with unpopulated formBean
78 * @throws ServletException
79 */
80 public void doInterceptBeforeMakeFormBean(
81 ControllerContext cctx,
82 FormBeanContext formBeanContext)
83 throws ServletException, FlowException
84 {
85 internalDoInterceptBeforeMakeFormBean(cctx, formBeanContext, true);
86 }
87
88 private void internalDoInterceptBeforeMakeFormBean(
89 ControllerContext cctx,
90 FormBeanContext formBeanContext,
91 boolean handleFlowExceptions)
92 throws ServletException, FlowException
93 {
94 Interceptor[] commands = interceptorRegistry.getInterceptors(
95 BeforeMakeFormBeanInterceptor.class);
96
97 internalDoExecute(commands, 0, cctx, formBeanContext,
98 handleFlowExceptions, LEVEL_BEFORE_MAKE_FORMBEAN, null);
99 }
100
101 /***
102 * Called before any handling like form population etc. but after makeFormBean.
103 *
104 * @param cctx maverick context
105 * @param formBeanContext context with unpopulated formBean
106 * @throws ServletException
107 */
108 public void doInterceptBeforePopulation(
109 ControllerContext cctx,
110 FormBeanContext formBeanContext)
111 throws ServletException, FlowException
112 {
113 internalDoInterceptBeforePopulation(cctx, formBeanContext, true);
114 }
115
116 public void internalDoInterceptBeforePopulation(
117 ControllerContext cctx,
118 FormBeanContext formBeanContext,
119 boolean handleFlowExceptions)
120 throws ServletException, FlowException
121 {
122 Interceptor[] commands = interceptorRegistry.getInterceptors(
123 BeforePopulationInterceptor.class);
124
125 internalDoExecute(commands, 0, cctx, formBeanContext,
126 handleFlowExceptions, LEVEL_BEFORE_POPULATION, null);
127 }
128
129 /***
130 * Called if population or validation failed.
131 *
132 * @param cctx maverick context
133 * @param formBeanContext context with form bean that failed to populate
134 * @param cause possibly the cause of the population error
135 * @throws ServletException
136 */
137 public void doInterceptPopulationError(
138 ControllerContext cctx,
139 FormBeanContext formBeanContext,
140 Exception cause)
141 throws ServletException, FlowException
142 {
143 internalDoInterceptPopulationError(cctx, formBeanContext, cause, true);
144 }
145
146 public void internalDoInterceptPopulationError(
147 ControllerContext cctx,
148 FormBeanContext formBeanContext,
149 Exception cause,
150 boolean handleFlowExceptions)
151 throws ServletException, FlowException
152 {
153 Interceptor[] commands = interceptorRegistry.getInterceptors(
154 PopulationErrorInterceptor.class);
155
156 internalDoExecute(commands, 0, cctx, formBeanContext,
157 handleFlowExceptions, LEVEL_POPULATION_ERROR, cause);
158 }
159
160 /***
161 * Called after population but before executing the command method.
162 *
163 * @param cctx maverick context
164 * @param formBeanContext context with unpopulated formBean
165 * @throws ServletException
166 */
167 public void doInterceptAfterPopulation(
168 ControllerContext cctx,
169 FormBeanContext formBeanContext)
170 throws ServletException, FlowException
171 {
172 internalDoInterceptAfterPopulation(cctx, formBeanContext, true);
173 }
174
175 public void internalDoInterceptAfterPopulation(
176 ControllerContext cctx,
177 FormBeanContext formBeanContext,
178 boolean handleFlowExceptions)
179 throws ServletException, FlowException
180 {
181 Interceptor[] commands = interceptorRegistry.getInterceptors(
182 AfterPopulationInterceptor.class);
183
184 internalDoExecute(commands, 0, cctx, formBeanContext,
185 handleFlowExceptions, LEVEL_AFTER_POPULATION, null);
186 }
187
188 /***
189 * Called when an unhandled exception occured during the execution of the command method.
190 *
191 * @param cctx maverick context
192 * @param formBeanContext context with populated (if succesful) formBean
193 * @param cause the exception that occured during perform
194 * @throws ServletException
195 */
196 public void doInterceptPerformException(
197 ControllerContext cctx,
198 FormBeanContext formBeanContext,
199 Exception cause)
200 throws ServletException, FlowException
201 {
202 internalDoInterceptPerformException(cctx, formBeanContext, cause, true);
203 }
204
205 public void internalDoInterceptPerformException(
206 ControllerContext cctx,
207 FormBeanContext formBeanContext,
208 Exception cause,
209 boolean handleFlowExceptions)
210 throws ServletException, FlowException
211 {
212 Interceptor[] commands = interceptorRegistry.getInterceptors(
213 PerformExceptionInterceptor.class);
214
215 internalDoExecute(commands, 0, cctx, formBeanContext,
216 handleFlowExceptions, LEVEL_PERFORM_EXCEPTION, cause);
217 }
218
219 /***
220 * Called after the command method is executed.
221 *
222 * @param cctx maverick context
223 * @param formBeanContext context with populated (if succesful) formBean
224 * @throws ServletException
225 */
226 public void doInterceptAfterPerform(
227 ControllerContext cctx,
228 FormBeanContext formBeanContext)
229 throws ServletException, FlowException
230 {
231 internalDoInterceptAfterPerform(cctx, formBeanContext, true);
232 }
233
234 public void internalDoInterceptAfterPerform(
235 ControllerContext cctx,
236 FormBeanContext formBeanContext,
237 boolean handleFlowExceptions)
238 throws ServletException, FlowException
239 {
240 Interceptor[] commands = interceptorRegistry.getInterceptors(
241 AfterPerformInterceptor.class);
242
243 internalDoExecute(commands, 0, cctx, formBeanContext,
244 handleFlowExceptions, LEVEL_AFTER_PERFORM, null);
245 }
246
247 private void internalDoExecute(
248 Interceptor[] commands,
249 int fromPos,
250 ControllerContext cctx,
251 FormBeanContext formBeanContext,
252 boolean handleFlowExceptions,
253 int level,
254 Exception exception)
255 throws ServletException, FlowException
256 {
257 if(commands == null) return;
258
259 int nbrcmds = commands.length;
260 if(fromPos >= nbrcmds) return;
261
262 for(int i = fromPos; i < nbrcmds; i++)
263 {
264 if(intercLog.isDebugEnabled())
265 {
266 intercLog.debug("calling interceptor " + commands[i]);
267 }
268 try
269 {
270 switch(level)
271 {
272 case LEVEL_BEFORE_MAKE_FORMBEAN:
273 ((BeforeMakeFormBeanInterceptor)commands[i])
274 .doBeforeMakeFormBean(cctx, formBeanContext);
275 break;
276 case LEVEL_BEFORE_POPULATION:
277 ((BeforePopulationInterceptor)commands[i])
278 .doBeforePopulation(cctx, formBeanContext);
279 break;
280 case LEVEL_POPULATION_ERROR:
281 ((PopulationErrorInterceptor)commands[i])
282 .doOnPopulationError(cctx, formBeanContext, exception);
283 break;
284 case LEVEL_AFTER_POPULATION:
285 ((AfterPopulationInterceptor)commands[i])
286 .doAfterPopulation(cctx, formBeanContext);
287 break;
288 case LEVEL_PERFORM_EXCEPTION:
289 ((PerformExceptionInterceptor)commands[i])
290 .doOnPerformException(cctx, formBeanContext, exception);
291 break;
292 case LEVEL_AFTER_PERFORM:
293 ((AfterPerformInterceptor)commands[i])
294 .doAfterPerform(cctx, formBeanContext);
295 break;
296
297 default: throw new ServletException("invalid interception level " + level);
298 }
299
300 }
301 catch (FlowException e)
302 {
303 if(intercLog.isDebugEnabled())
304 {
305 intercLog.debug(e + " was thrown by interceptor " + commands[i]);
306 }
307 if(handleFlowExceptions)
308 {
309 handleFlowException(
310 cctx, formBeanContext, e, level, commands, i);
311 }
312 throw e;
313 }
314 }
315 }
316
317
318
319
320 private void handleFlowException(
321 ControllerContext cctx,
322 FormBeanContext formBeanContext,
323 FlowException flowException,
324 int level,
325 Interceptor[] currentCommandStack,
326 int currentCommandStackPos)
327 throws ServletException
328 {
329 String view = null;
330 if(flowException != null)
331 {
332 if(flowException instanceof ReturnNowFlowException)
333 {
334 ReturnNowFlowException e = (ReturnNowFlowException)flowException;
335 view = e.getView();
336 if(intercLog.isDebugEnabled())
337 {
338 intercLog.debug("returning view " + view);
339 }
340 }
341 else if(flowException instanceof DispatchNowFlowException)
342 {
343 DispatchNowFlowException e = (DispatchNowFlowException)flowException;
344
345 try
346 {
347 HttpServletRequest request = cctx.getRequest();
348 String dispatchPath = e.getDispatchPath();
349 if(intercLog.isDebugEnabled())
350 {
351 intercLog.debug("trying dispatch to " + dispatchPath);
352 }
353 RequestDispatcher disp = request.getRequestDispatcher(dispatchPath);
354 if(disp == null)
355 {
356 String msg = "dispatcher not found for path " + dispatchPath;
357 ServletException ex = new ServletException(msg);
358 intercLog.error(msg, ex);
359 throw ex;
360 }
361 disp.forward(request, cctx.getResponse());
362 }
363 catch (IOException ex)
364 {
365 intercLog.error(ex.getMessage(), ex);
366 throw new ServletException(e);
367 }
368 }
369 }
370
371 possiblyHandleOtherInterceptors(
372 cctx, formBeanContext, flowException, level, currentCommandStack, currentCommandStackPos);
373 }
374
375
376 private void possiblyHandleOtherInterceptors(
377 ControllerContext cctx,
378 FormBeanContext formBeanContext,
379 FlowException flowException,
380 int level,
381 Interceptor[] currentCommandStack,
382 int currentCommandStackPos)
383 throws ServletException
384 {
385 if(flowException.isExecuteOtherInterceptors())
386 {
387 if(intercLog.isDebugEnabled())
388 {
389 intercLog.debug("handling other interceptors before handling flowexception...");
390 }
391
392 try
393 {
394 internalDoExecute(currentCommandStack, (currentCommandStackPos + 1),
395 cctx, formBeanContext, false, level, null);
396 }
397 catch (FlowException e)
398 {
399
400 intercLog.error(e.getMessage(), e);
401 }
402
403 if(level == LEVEL_BEFORE_MAKE_FORMBEAN)
404 {
405 try
406 {
407 internalDoInterceptBeforePopulation(cctx, formBeanContext, false);
408 }
409 catch (Exception e)
410 {
411 intercLog.error(e.getMessage(), e);
412
413 }
414 }
415 if(level != LEVEL_AFTER_PERFORM)
416 {
417 try
418 {
419 internalDoInterceptAfterPerform(cctx, formBeanContext, false);
420 }
421 catch (Exception e)
422 {
423 intercLog.error(e.getMessage(), e);
424
425 }
426 }
427 }
428 }
429
430 }