View Javadoc

1   /*
2    * Copyright (c) 2005, The K-Wf Grid Consortium
3    * Fraunhofer Institute for Computer Architecture and Software Technology
4    * See http://www.kwfgrid.eu and http://www.first.fraunhofer.de for more details.
5    */
6   package net.kwfgrid.gwui.servlets;
7   
8   import javax.servlet.http.HttpServlet;
9   import javax.servlet.http.HttpServletRequest;
10  import javax.servlet.http.HttpServletResponse;
11  import javax.servlet.http.HttpSession;
12  import javax.servlet.ServletException;
13  import javax.servlet.ServletContext;
14  import javax.servlet.RequestDispatcher;
15  import java.io.*;
16  import java.util.Properties;
17  import java.util.List;
18  import java.util.LinkedList;
19  import java.rmi.RemoteException;
20  
21  import org.apache.log4j.Logger;
22  
23  import net.kwfgrid.gworkflowdl.protocol.IllegalModificationException;
24  import net.kwfgrid.gworkflowdl.protocol.IncompatibleVersionsException;
25  import net.kwfgrid.gworkflowdl.protocol.client.ClientWorkflow;
26  import net.kwfgrid.gworkflowdl.structure.*;
27  
28  /***
29     <b>NOTE:</b> All servlets needed to fire one transition (including default and generic servlet) need to be deployed in one and the same webapp 
30     so that they can share session information.
31     The file <code>dataservletbase.properties</code> must be present in the root directory of the classpath and must contain the following properties:
32     <ul>
33     <li>servlet-base-url = &lt;The base URL of the servlets&gt;</li>
34     </ul>
35   */
36  public abstract class DataServletBase extends HttpServlet implements ServletConstants {
37      private static Logger logger = Logger.getLogger(DataServletBase.class);
38  
39      /*** The placeholder for the servlet URL. */
40      public static final String PLACEHOLDER_SERVLET_URL = "//$SERVLET_URL";
41  
42      private static Properties PROPERTIES = new Properties();
43  
44      static {
45  	try {
46  	    PROPERTIES.load(DataServletBase.class.getResourceAsStream("/dataservletbase.properties"));
47  	    PROPERTIES.list(System.out);
48  
49  	    if (PROPERTIES.getProperty(KEY_SERVLET_BASE_URL) == null)
50  		throw new IOException("No servlet-base-url property defined.");
51  	} catch (Exception x) {
52  	    logger.fatal("Could not load properties.", x);
53  	}	
54      }
55  
56      protected abstract Logger getLogger();
57  
58      protected final String getSelfURL() {
59  	return getProperty(KEY_SERVLET_BASE_URL)+getServletName();
60      }
61  
62      protected String getProperty(String key) {
63  	return PROPERTIES.getProperty(key);
64      }
65  
66      protected void doPost(HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException {
67          doAll( request, response );
68      }
69  
70      protected void doGet(HttpServletRequest request,  HttpServletResponse response ) throws ServletException, IOException {
71          doAll( request, response );
72      }
73  
74      private void doAll(HttpServletRequest request, HttpServletResponse response )throws ServletException, IOException {
75  	HttpSession session = request.getSession(true);
76  	boolean invalidate = true;
77  
78  	getLogger().info("Handling session: "+session.getId());
79  
80  	try {
81  	    if (!session.isNew() && request.getParameter("newsession") != null) {
82  		getLogger().info("Got outdated session information. Recreating session.");
83  
84  		session.invalidate();
85  		session = request.getSession(true);
86  	    }
87  
88  	    if (session.isNew() || FORM_ACTION.equals((String)session.getAttribute(KEY_ACTION))) {
89  		try {
90  		    if (session.isNew()) {
91  			getLogger().info("Session is new. Creating session information...");		
92  			createSessionInformation(request, session);
93  		    }
94  
95  		    String formurl = ServletUtilities.decode(request.getParameter(KEY_FORMURL));
96  		    if (formurl == null)
97  			throw new IllegalArgumentException("No formURL parameter specified.");
98  		    session.setAttribute(KEY_FORMURL, formurl);
99  
100 		    getLogger().info("Displaying form...");
101 		    showForm(request, session, response);
102 		    session.setAttribute(KEY_ACTION, TOKEN_ACTION);
103 		    invalidate = false;
104 		} catch (UnsupportedEncodingException x) {
105 		    getLogger().error("Unsupported encoding when creating session information.", x);
106 		    showErrorDialog(session, response, "Unsupported encoding when creating session information.", x);
107 		} catch (IllegalArgumentException x) {
108 		    getLogger().error("Insufficient request.", x);
109 		    showErrorDialog(session, response, "Insufficient request.", x);
110 		} catch (IncompatibleVersionsException x) {
111 		    getLogger().error("Incompatible versions of workflow.", x);
112 		    showErrorDialog(session, response, "Incompatible versions of workflow.", x);
113 		} catch (RemoteException x) {
114 		    getLogger().error("Workflow server unreachable.", x);
115 		    showErrorDialog(session, response, "Workflow server unreachable.", x);
116 		}	    
117 	    } else {
118 		try {
119 		    getLogger().info("Session is known. Handling user input.");
120 		    invalidate = !handleUserRequest(request, session, response);
121 		} catch (IncompatibleVersionsException x) {
122 		    getLogger().error("Incompatible versions of workflow.", x);
123 		    showErrorDialog(session, response, "Incompatible versions of workflow.", x);
124 		} catch (IllegalArgumentException x) {
125 		    getLogger().error("Invalid session information.", x);
126 		    showErrorDialog(session, response, "Invalid session information.", x);
127 		} catch (IllegalModificationException x) {
128 		    getLogger().error("Error manipulating workflow.", x);
129 		    showErrorDialog(session, response, "Error manipulating workflow.", x);
130 		} catch (RemoteException x) {
131 		    getLogger().error("Workflow server unreachable.", x);
132 		    showErrorDialog(session, response, "Workflow server unreachable.", x);
133 		} catch (WorkflowFormatException x) {
134 		    getLogger().error("Could not create token from request.", x);
135 		    showErrorDialog(session, response, "Could not create token from request.", x);
136 		} catch (CapacityException x) {
137 		    getLogger().error("Could not put token on place.", x);
138 		    showErrorDialog(session, response, "Could not put token on place.", x);
139 		} catch (UnsupportedEncodingException x) {
140 		    getLogger().error("Unsupported encoding.", x);
141 		    showErrorDialog(session, response, "Unsupported encoding.", x);
142 		} 	    
143 	    }	
144 	} finally {
145 	    if (invalidate) {
146 		session.invalidate();
147 		getLogger().info("Session invalidated.");
148 	    }
149 	}
150     }
151 
152     ///
153     /// Create session information and check workflow status
154     /// ....................................................................................................
155 
156     /***
157        Create the session information for a request.
158        This will write certain input parameters of the request to the session.
159      */
160     private void createSessionInformation(HttpServletRequest request, HttpSession session) 
161 	throws UnsupportedEncodingException, IllegalArgumentException, RemoteException, IncompatibleVersionsException {
162 	String command = ServletUtilities.decode(request.getParameter(KEY_COMMAND));
163 	String workflowid = ServletUtilities.decode(request.getParameter(KEY_WORKFLOWID));
164 	String gwesaddress = ServletUtilities.decode(request.getParameter(KEY_GWESADDRESS));
165 	String versionnumberspec = ServletUtilities.decode(request.getParameter(KEY_VERSIONNUMBER));
166 	int versionnumber = -1;
167 	ClientWorkflow workflow = null;
168 
169 	if (command == null) 
170 	    throw new IllegalArgumentException("No command specified.");
171 	if (workflowid == null)
172 	    throw new IllegalArgumentException("No Workflow ID specified.");
173 	if (gwesaddress == null)
174 	    throw new IllegalArgumentException("No reference to GWES specified.");
175 	if (versionnumberspec == null)
176 	    throw new IllegalArgumentException("No version number specified.");
177 
178 	session.setAttribute(KEY_COMMAND, command);
179 	session.setAttribute(KEY_WORKFLOWID, workflowid);
180 	session.setAttribute(KEY_GWESADDRESS, gwesaddress);
181 	try {	    
182 	    versionnumber = Integer.parseInt(versionnumberspec);
183 	    session.setAttribute(KEY_VERSIONNUMBER, new Integer(versionnumber));
184 	} catch (NumberFormatException x) {
185 	    IllegalArgumentException iox = new IllegalArgumentException("Could not parse version number.");
186 	    iox.initCause(x);
187 	    throw iox;
188 	}	
189 
190 	if (EDIT_COMMAND.equals(command)) {
191 	    addEditSessionInformation(request, session);
192 	} else if (CREATE_COMMAND.equals(command)) {
193 	    addCreateSessionInformation(request, session);
194 	} else if (FIRE_COMMAND.equals(command)) {
195 	    addFireSessionInformation(request, session);
196 	} else {
197 	    throw new IllegalArgumentException("Unknown command for GWUI servlet: "+command);
198 	}
199 
200 	workflow = (ClientWorkflow)Factory.newWorkflow(workflowid);
201 	workflow.update();
202 	if (workflow.getVersionNumber() != versionnumber)
203 	    throw new IncompatibleVersionsException("Workflow has changed. Please retry.");
204 	if (EDIT_COMMAND.equals(command)) {
205 	    checkWorkflowInstanceForEdit(session, workflow);
206 	} else if (CREATE_COMMAND.equals(command)) {
207 	    checkWorkflowInstanceForCreate(session, workflow);
208 	} else if (FIRE_COMMAND.equals(command)) {
209 	    checkWorkflowInstanceForFire(session, workflow);
210 	} 
211 
212 	session.setAttribute(KEY_WORKFLOWINSTANCE, workflow);
213 	getLogger().info("Added workflow instance "+workflow+" to session.");
214     }
215 
216     private void addEditSessionInformation(HttpServletRequest request, HttpSession session)
217 	throws UnsupportedEncodingException, IllegalArgumentException {
218 	String placeid = ServletUtilities.decode(request.getParameter(KEY_PLACEID));
219 	String tokenindexspec = ServletUtilities.decode(request.getParameter(KEY_TOKENINDEX));
220 
221 	if (placeid == null) 
222 	    throw new IllegalArgumentException("Place ID needs to be specified to edit token.");
223 	if (tokenindexspec == null) 
224 	    throw new IllegalArgumentException("Token index needs to be specified to edit token.");
225 
226 	session.setAttribute(KEY_PLACEID, placeid);
227 	try {
228 	    session.setAttribute(KEY_TOKENINDEX, new Integer(Integer.parseInt(tokenindexspec)));
229 	} catch (NumberFormatException x) {
230 	    IllegalArgumentException iox = new IllegalArgumentException("Could not parse token index.");
231 	    iox.initCause(x);
232 	    throw iox;
233 	}
234     }
235 
236     private void addCreateSessionInformation(HttpServletRequest request, HttpSession session)
237 	throws UnsupportedEncodingException, IllegalArgumentException {
238 	String placeid = ServletUtilities.decode(request.getParameter(KEY_PLACEID));
239 
240 	if (placeid == null) 
241 	    throw new IllegalArgumentException("Place ID needs to be specified to create token.");
242 
243 	session.setAttribute(KEY_PLACEID, placeid);
244     }
245 
246     private void addFireSessionInformation(HttpServletRequest request, HttpSession session)
247 	throws UnsupportedEncodingException, IllegalArgumentException {
248 	String transitionid = ServletUtilities.decode(request.getParameter(KEY_TRANSITIONID));
249 
250 	if (transitionid == null) 
251 	    throw new IllegalArgumentException("Transition ID needs to be specified to fire transition.");
252 
253 	session.setAttribute(KEY_TRANSITIONID, transitionid);
254 	session.setAttribute(KEY_OUTEDGEINDEX, new Integer(0));
255 	session.setAttribute(KEY_TOKENLIST, new LinkedList());
256     }
257 
258     private void checkWorkflowInstanceForEdit(HttpSession session, ClientWorkflow workflow) throws IllegalArgumentException {
259 	String placeid = (String)session.getAttribute(KEY_PLACEID);
260 	int tokenindex = ((Integer)session.getAttribute(KEY_TOKENINDEX)).intValue();
261 	Place place = workflow.getPlace(placeid);
262 	
263 	if (place == null)
264 	    throw new IllegalArgumentException("Workflow does not contain a place with ID "+placeid+".");
265 	if (tokenindex >= place.getTokens().length)
266 	    throw new IllegalArgumentException("Place with ID "+placeid+" does not contain "+(tokenindex+1)+" token(s).");
267     }
268 
269     private void checkWorkflowInstanceForCreate(HttpSession session, ClientWorkflow workflow) throws IllegalArgumentException {
270 	String placeid = (String)session.getAttribute(KEY_PLACEID);
271 	Place place = workflow.getPlace(placeid);
272 	
273 	if (place == null)
274 	    throw new IllegalArgumentException("Workflow does not contain a place with ID "+placeid+".");
275     }
276     
277     private void checkWorkflowInstanceForFire(HttpSession session, ClientWorkflow workflow) throws IllegalArgumentException {
278 	String transitionid = (String)session.getAttribute(KEY_TRANSITIONID);
279 	Transition transition = workflow.getTransition(transitionid);
280 
281 	if (transition == null)
282 	    throw new IllegalArgumentException("Workflow does not contain a transition with ID "+transitionid+".");	
283 	if (!transition.isEnabled()) 
284 	    throw new IllegalArgumentException("Transition with ID "+transitionid+" is not enabled.");
285 
286 	if (transition.getOutEdges().length < 1)
287 	    throw new IllegalArgumentException("Transitions with ID "+transitionid+"  has no output places.");
288     }
289 
290     private void checkWorkflowVersion(HttpSession session, ClientWorkflow workflow) throws IncompatibleVersionsException {
291 	int versionnumber = ((Integer)session.getAttribute(KEY_VERSIONNUMBER)).intValue();
292 	if (workflow.getVersionNumber() != versionnumber)
293 	    throw new IncompatibleVersionsException("Workflow has changed. Please retry.");
294     }
295 
296     ///
297     /// Display form(s)
298     /// ....................................................................................................
299 
300     /***
301        Show the a form.
302      */
303     private void showForm(HttpServletRequest request, HttpSession session, HttpServletResponse response) 
304 	throws IOException, IncompatibleVersionsException, RemoteException, IllegalArgumentException {
305 	String command = (String)session.getAttribute(KEY_COMMAND);
306 	if (EDIT_COMMAND.equals(command)) {
307 	    showEditForm(request, session, response);
308 	} else if (CREATE_COMMAND.equals(command)) {
309 	    showCreateForm(request, session, response);
310 	} else if (FIRE_COMMAND.equals(command)) {
311 	    showFireForm(request, session, response);
312 	} else {
313 	    throw new IllegalArgumentException("Invalid session information. Command attribute invalid or not set.");
314 	}
315     }
316 
317     private void showEditForm(HttpServletRequest request, HttpSession session, HttpServletResponse response) 
318 	throws IOException, IncompatibleVersionsException, RemoteException, IllegalArgumentException {
319 	ClientWorkflow workflow = (ClientWorkflow)session.getAttribute(KEY_WORKFLOWINSTANCE);
320 	workflow.update();
321 	checkWorkflowVersion(session, workflow);
322 	String placeid = (String)session.getAttribute(KEY_PLACEID);
323 	Place place = workflow.getPlace(placeid);
324 	int tokenindex = ((Integer)session.getAttribute(KEY_TOKENINDEX)).intValue();
325 	Token token = place.getTokens()[tokenindex];
326 	String formurl = (String)session.getAttribute(KEY_FORMURL);
327 
328 	getLogger().info("Displaying form for edit: "+formurl);
329 
330 	if (formurl == null)
331 	    throw new IllegalArgumentException("No form specified.");
332 
333 	String form = ServletUtilities.readFile(formurl);	
334 
335 	getLogger().info("Form template before replace:\n"+form);
336 
337 	form = ServletUtilities.replace(form, PLACEHOLDER_SERVLET_URL, response.encodeURL(getSelfURL()));
338 
339 	getLogger().info("Form template after replace servlet URL:\n"+form);
340 
341 	form = replaceValues(form, token);
342 
343 	getLogger().info("Form template after replace servlet values:\n"+form);
344 
345 	PrintWriter out = response.getWriter();
346 	out.println(form);		
347     }
348 
349     private void showCreateForm(HttpServletRequest request, HttpSession session, HttpServletResponse response) 
350 	throws IOException, IncompatibleVersionsException, RemoteException, IllegalArgumentException {
351 	ClientWorkflow workflow = (ClientWorkflow)session.getAttribute(KEY_WORKFLOWINSTANCE);
352 	workflow.update();
353 	checkWorkflowVersion(session, workflow);
354 	String placeid = (String)session.getAttribute(KEY_PLACEID);
355 	Place place = workflow.getPlace(placeid);
356 	String formurl = (String)session.getAttribute(KEY_FORMURL);
357 
358 	getLogger().info("Displaying form for create: "+formurl);
359 
360 	if (formurl == null)
361 	    throw new IllegalArgumentException("No form specified in parameters.");
362 
363 	String form = ServletUtilities.readFile(formurl);	
364 	form = ServletUtilities.replace(form, PLACEHOLDER_SERVLET_URL, response.encodeURL(getSelfURL()));
365 	form = clearValues(form);
366 
367 	PrintWriter out = response.getWriter();
368 	out.println(form);		
369     }
370 
371     private void showFireForm(HttpServletRequest request, HttpSession session, HttpServletResponse response)
372 	throws IOException, IncompatibleVersionsException, RemoteException, IllegalArgumentException {
373 	ClientWorkflow workflow = (ClientWorkflow)session.getAttribute(KEY_WORKFLOWINSTANCE);
374 	workflow.update();
375 	checkWorkflowVersion(session, workflow);
376 	String transitionid = (String)session.getAttribute(KEY_TRANSITIONID);
377 	Transition transition = workflow.getTransition(transitionid);	
378 	int outedgeindex = ((Integer)session.getAttribute(KEY_OUTEDGEINDEX)).intValue();
379 	Edge[] outedges = transition.getOutEdges();	
380 	Place currentplace = outedges[outedgeindex].getPlace();
381 	String formurl = (String)session.getAttribute(KEY_FORMURL);
382 
383 	getLogger().info("Displaying form for fire: "+formurl);
384 
385 	if (formurl == null)
386 	    throw new IllegalArgumentException("No form specified in parameters.");
387 
388 	String form = ServletUtilities.readFile(formurl);	
389 	form = ServletUtilities.replace(form, PLACEHOLDER_SERVLET_URL, response.encodeURL(getSelfURL()));
390 	form = replaceValues(form, transition);
391 
392 	PrintWriter out = response.getWriter();
393 	out.println(form);	
394     }
395 
396     /***
397        Replace all placeholders for values in the form with the actual values from the token. 
398      */
399     protected abstract String replaceValues(String form, Token token);
400 
401     /***
402        Replace all placeholders for values in the form with the empty string.
403      */
404     protected abstract String clearValues(String form);
405     
406     /***
407        Replace all placeholders for values in the form with the correct values from the first tokens on the input
408        places of the specified transition.
409      */
410     protected abstract String replaceValues(String form, Transition transition);
411 
412     ///
413     /// Handle user input
414     /// ....................................................................................................
415 
416     private boolean handleUserRequest(HttpServletRequest request, HttpSession session, HttpServletResponse response) 
417 	throws IOException, 
418 	       IncompatibleVersionsException, 
419 	       RemoteException, 
420 	       WorkflowFormatException, 
421 	       CapacityException, 
422 	       UnsupportedEncodingException,
423 	       IllegalModificationException,
424 	       IllegalArgumentException,
425 	       ServletException {	
426 	String command = (String)session.getAttribute(KEY_COMMAND);
427 	if (EDIT_COMMAND.equals(command)) {
428 	    return handleEditRequest(request, session, response);
429 	} else if (CREATE_COMMAND.equals(command)) {
430 	    return handleCreateRequest(request, session, response);
431 	} else if (FIRE_COMMAND.equals(command)) {
432 	    return handleFireRequest(request, session, response);
433 	} else {
434 	    throw new IllegalArgumentException("Invalid session information. Command attribute invalid or not set.");
435 	}
436     }
437 
438     private boolean handleEditRequest(HttpServletRequest request, HttpSession session, HttpServletResponse response) 
439 	throws IOException, 
440 	       IncompatibleVersionsException, 
441 	       RemoteException, 
442 	       IllegalArgumentException, 
443 	       IllegalModificationException,
444 	       WorkflowFormatException, 
445 	       CapacityException,
446 	       UnsupportedEncodingException {
447 	ClientWorkflow workflow = (ClientWorkflow)session.getAttribute(KEY_WORKFLOWINSTANCE);
448 	workflow.update();
449 	checkWorkflowVersion(session, workflow);
450 	String placeid = (String)session.getAttribute(KEY_PLACEID);
451 	Place place = workflow.getPlace(placeid);
452 	int tokenindex = ((Integer)session.getAttribute(KEY_TOKENINDEX)).intValue();
453 	
454 	Token newtoken = createToken(request);
455 	
456 	place.removeToken(tokenindex);
457 	place.addToken(newtoken);
458 
459 	showConfirmationDialog(session, response);
460 	return false;	
461     }
462 
463     private boolean handleCreateRequest(HttpServletRequest request, HttpSession session, HttpServletResponse response) 
464 	throws IOException, 
465 	       IncompatibleVersionsException, 
466 	       RemoteException, 
467 	       IllegalArgumentException, 
468 	       IllegalModificationException,
469 	       WorkflowFormatException, 
470 	       CapacityException,
471 	       UnsupportedEncodingException {
472 	ClientWorkflow workflow = (ClientWorkflow)session.getAttribute(KEY_WORKFLOWINSTANCE);
473 	workflow.update();
474 	checkWorkflowVersion(session, workflow);
475 	String placeid = (String)session.getAttribute(KEY_PLACEID);
476 	Place place = workflow.getPlace(placeid);
477 	
478 	Token newtoken = createToken(request);
479 	
480 	place.addToken(newtoken);
481 
482 	showConfirmationDialog(session, response);
483 	return false;	
484     }
485 
486     private boolean handleFireRequest(HttpServletRequest request, HttpSession session, HttpServletResponse response)
487 	throws IOException, 
488 	       IncompatibleVersionsException, 
489 	       RemoteException, 
490 	       IllegalArgumentException, 
491 	       IllegalModificationException,
492 	       WorkflowFormatException, 
493 	       CapacityException,
494 	       UnsupportedEncodingException,
495 	       ServletException {
496 	ClientWorkflow workflow = (ClientWorkflow)session.getAttribute(KEY_WORKFLOWINSTANCE);
497 	workflow.update();
498 	checkWorkflowVersion(session, workflow);
499 	String transitionid = (String)session.getAttribute(KEY_TRANSITIONID);
500 	Transition transition = workflow.getTransition(transitionid);	
501 	int outedgeindex = ((Integer)session.getAttribute(KEY_OUTEDGEINDEX)).intValue();
502 	Edge[] outedges = transition.getOutEdges();	
503 	List tokens = (List)session.getAttribute(KEY_TOKENLIST);
504 	Place currentplace = outedges[outedgeindex].getPlace();	
505 
506 	Token token = createToken(request);
507 	tokens.add(token);
508 	
509 	if (outedgeindex == outedges.length-1) {
510 	    getLogger().debug("Removing one token from each input place of transition "+transitionid);
511 
512         // do this only for input edges, not for read edges.
513         Edge[] inedges = transition.getInEdges();
514 	    for (int i=0; i<inedges.length; i++) {
515 		inedges[i].getPlace().removeToken(0);
516 	    }
517 
518 	    getLogger().debug("Adding tokens to output places of transition "+transitionid);
519 
520 	    for (int i=0; i<outedges.length; i++) {
521 		token = (Token)tokens.get(i);
522 		outedges[i].getPlace().addToken(token);
523 	    }
524 
525 	    showConfirmationDialog(session, response);
526 
527 	    return false;
528 	} else {
529 	    // forward request to form selection servlet.
530 	    outedgeindex++;
531 	    session.setAttribute(KEY_OUTEDGEINDEX, new Integer(outedgeindex));
532 	    currentplace = outedges[outedgeindex].getPlace();
533 
534 	    String servlet = "/FormSelectionServlet";
535 	    ServletContext ctx = getServletContext();
536 	    RequestDispatcher rq = ctx.getRequestDispatcher(servlet);
537 	    
538 	    getLogger().info("Forwarding request to "+servlet+" for place "+currentplace.getID());
539 
540 	    session.setAttribute(KEY_ACTION, FORM_ACTION);
541 
542 	    rq.forward(request, response);
543 
544 	    return true;
545 	}
546     }
547 
548     /***
549        Create a token from the specified request.
550      */
551     protected abstract Token createToken(HttpServletRequest request) 
552 	throws WorkflowFormatException, UnsupportedEncodingException, IllegalArgumentException;
553 
554     ///
555     /// Generic dialogs.
556     /// ....................................................................................................
557 
558     /***
559        Show a confirmation dialog after successful workflow manipulation.
560      */
561     protected void showConfirmationDialog(HttpSession session, HttpServletResponse response) throws IOException {
562 	PrintWriter out = response.getWriter();
563 	out.println("<html>\n");
564 	ServletUtilities.printHeadWithTitle("OK", out);
565 	out.println("<body>\n"+
566 		    "<h2>Data has been inserted into the workflow.</h2><br>\n");
567 	out.println("</body></html>\n");		
568     }
569 
570     /***
571        Show an error dialog.
572      */
573     protected void showErrorDialog(HttpSession session, HttpServletResponse response, String message, Exception exception) throws IOException {
574 	PrintWriter out = response.getWriter();
575 	out.println("<html>\n");
576 	ServletUtilities.printHeadWithTitle("Error", out);
577 	out.println("<body>\n"+
578 		    "<h2>Your request could not be handled!</h2><br>\n"+
579 		    "<b>"+message+"</b><br><br>\n");
580 	out.println("<pre>");
581 	exception.printStackTrace(out);
582 	out.println("</pre>");
583 	out.println("</body></html>\n");	
584     }
585 }