KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > appserver > server > httpPresentation > ExceptionHandler


1
2 /*
3  * Enhydra Java Application Server Project
4  *
5  * The contents of this file are subject to the Enhydra Public License
6  * Version 1.1 (the "License"); you may not use this file except in
7  * compliance with the License. You may obtain a copy of the License on
8  * the Enhydra web site ( http://www.enhydra.org/ ).
9  *
10  * Software distributed under the License is distributed on an "AS IS"
11  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
12  * the License for the specific terms governing rights and limitations
13  * under the License.
14  *
15  * The Initial Developer of the Enhydra Application Server is Lutris
16  * Technologies, Inc. The Enhydra Application Server and portions created
17  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
18  * All Rights Reserved.
19  *
20  * Contributor(s):
21  *
22  * $Id: ExceptionHandler.java,v 1.2 2005/03/24 10:51:16 slobodan Exp $
23  */

24
25
26
27
28
29 package com.lutris.appserver.server.httpPresentation;
30
31 import java.io.ByteArrayOutputStream JavaDoc;
32 import java.io.File JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.io.PrintWriter JavaDoc;
35
36 import com.lutris.appserver.server.Application;
37 import com.lutris.logging.LogChannel;
38 import com.lutris.logging.Logger;
39
40 /**
41  * Various routines used in handling exceptions.
42  */

43 class ExceptionHandler {
44     /*
45      * Disallow instances.
46      */

47     private ExceptionHandler() {
48     }
49
50     /**
51      * Generate an HTML page describing an exception and log the exception.
52      * If it looks like a client disconnect, log at the DEBUG level.
53      */

54     private static void sendExceptionPage(HttpPresentationComms comms,
55                                           Application application,
56                                           Throwable JavaDoc except)
57             throws HttpPresentationException, IOException JavaDoc {
58
59         String JavaDoc title = "Error in " + application.getName();
60
61         comms.response.setStatus(HttpPresentationResponse.SC_INTERNAL_SERVER_ERROR);
62         comms.response.setContentType("text/html");
63
64         HttpPresentationOutputStream out = comms.response.getOutputStream();
65
66         out.println("<HTML><TITLE>");
67         out.println(title);
68         out.println("</TITLE>");
69
70         out.println("<BODY BGCOLOR=white>");
71         out.println("<H2><P><CENTER><FONT COLOR=red> - " + title + " - </FONT></CENTER></H2>");
72
73         // Reason...
74
if (except instanceof java.io.FileNotFoundException JavaDoc) {
75             out.println("<B>File not found</B>: " +
76                         comms.request.getRequestURI());
77         } else if (except instanceof DirectoryException) {
78             out.println("<B>Directory access error</B>: " +
79                         comms.request.getRequestURI());
80         } else if (except instanceof java.lang.IllegalAccessException JavaDoc) {
81             out.println("<B>Illegal access</B>: " +
82                         comms.request.getRequestURI());
83         } else if ((except instanceof java.lang.ClassNotFoundException JavaDoc)
84                    || (except instanceof java.lang.NoClassDefFoundError JavaDoc)) {
85             out.println("<B>Class not found: " + except.getMessage() + "</B>");
86         } else {
87             // catch all
88
out.println("<B>Reason: </B>" + except.getClass() +
89         ": " + except.getMessage());
90         }
91
92         // Details...
93
out.println("<P>");
94         out.println("<B>Java Call Stack:</B><P><FONT size=-1><PRE>");
95         ByteArrayOutputStream JavaDoc b = new ByteArrayOutputStream JavaDoc(); //FIX: This should be a utility.
96
PrintWriter JavaDoc p = new PrintWriter JavaDoc(b);
97         except.printStackTrace(p);
98         p.flush();
99         out.println(b.toString());
100         out.println("</PRE></FONT>\n");
101
102         // Back button
103
out.println("<FORM>");
104         out.println("<CENTER><INPUT TYPE=BUTTON VALUE=\"back\"");
105         out.println("onClick=\"history.go(-1)\"></CENTER>\n");
106         out.println("</FORM>");
107
108         // EOF
109
out.println("</BODY>");
110         out.println("</HTML>");
111         comms.response.flush();
112     }
113
114
115     /**
116      * Output an HTML page describing an exception and log the exception.
117      * If it looks like a client disconnect, log at the DEBUG level.
118      */

119     protected static void logDisplayException(HttpPresentationComms comms,
120                                               LogChannel logChannel,
121                                               long requestId,
122                                               Application application,
123                                               Throwable JavaDoc except,
124                                               String JavaDoc presObjPath) {
125
126         /*
127          * Log at DEBUG if client I/O error; but generate page anyway. It
128          * will most likely be discarded, but it will prevent just a blank
129          * page if the client is still connected.
130          */

131         try {
132             if (HttpPresentationIOException.isClientIOException(except)) {
133                 logChannel.write(Logger.DEBUG, "RID:" + requestId
134                                  + ": Client appeared to drop connection: "
135                                  + presObjPath);
136                 sendExceptionPage(comms, application, except);
137             } else {
138                 logChannel.write(Logger.ERROR, "RID:" + requestId
139                                  + ": Unhandled Application error in "
140                                  + application.getName(), except);
141                 sendExceptionPage(comms, application, except);
142             }
143         } catch (IllegalStateException JavaDoc except2) {
144             // May not be able set set headers if output has begun.
145
} catch (IOException JavaDoc except2) {
146             // Ignore, client is gone
147
} catch (HttpPresentationException except2) {
148             // Ignore, client maybe gone
149
}
150     }
151
152     /**
153      * Get the path of the error handler for an exception that occured during
154      * the loading and execution of a presentation or the handling of an error
155      * The handler is a presentation named `ErrorHandler' in the current or
156      * a higher level directory.
157      *
158      * This method just returns the path for the error handler for the
159      * specified presentation path. This attempts to load the error handler
160      * just to see if it exists. This also handles errors that are throw while
161      * handling an error (which is often just an ErrorHandler passing an error up
162      * to a higher level).
163      *
164      * @param presObjPath
165      * The path of the presentation object that threw the error. This
166      * may not be the same as the original request URL. This is relative
167      * to <CODE>presentationRoot</CODE>.
168      * @param requestedPresObjPath
169      * Original presentation object that the error hander is being called
170      * for.
171      * @param whileHandlingError
172      * True an error was already being handled.
173      * @param logChannel
174      * Log channel to use.
175      * @return The path to the presentation object to invoke or null if no
176      * is available (reached top of tree).
177      */

178     protected static String JavaDoc getErrorHandler(String JavaDoc presObjPath,
179                                             String JavaDoc requestedPresObjPath,
180                                             boolean whileHandlingError,
181                                             PresentationLoader loader,
182                         LogChannel logChannel,
183                                             long requestId) {
184         String JavaDoc handlerDir;
185
186         logChannel.write(Logger.DEBUG, "RID:" +requestId
187                          + ": Searching for error handler for "
188                          + requestedPresObjPath);
189
190         // Find first place to look.
191
if (!whileHandlingError) {
192             // Look in current package; its ok for dir to be null here.
193
handlerDir = (new File JavaDoc(presObjPath)).getParent();
194         } else {
195             // Look in parent package.
196
String JavaDoc currentDir = (new File JavaDoc(presObjPath)).getParent();
197             if (currentDir == null) {
198                 handlerDir = null;
199             } else {
200                 handlerDir = (new File JavaDoc(currentDir)).getParent();
201                 // already at top level, don't try that handler again
202
if (handlerDir == null) {
203                     logChannel.write(Logger.DEBUG, "RID:" + requestId
204                                      + ": No error handler found for: "
205                                      + presObjPath);
206                     return null;
207                 }
208             }
209         }
210
211         // Try to load, searching up if a handler was not found.
212
while (true) {
213             // handlerDir can be null here (trying the top).
214
String JavaDoc handlerPath = (new File JavaDoc(handlerDir, "ErrorHandler.po")).getPath();
215             logChannel.write(Logger.DEBUG, "RID:" + requestId
216                              + ": Checking for error handler: " + handlerPath);
217             try {
218                 loader.loadPresentation(handlerPath);
219                 return handlerPath; // Found and loaded a handler.
220
} catch (ClassNotFoundException JavaDoc noClass) {
221                 if (handlerDir == null) {
222                     break; // Not found
223
}
224                 String JavaDoc currentDir = (new File JavaDoc(handlerPath)).getParent();
225                 if (currentDir == null) {
226                     handlerDir = null;
227                 } else {
228                     handlerDir = (new File JavaDoc(currentDir)).getParent();
229                 }
230             } catch (Throwable JavaDoc except) {
231                 logChannel.write(Logger.DEBUG, "RID:" + requestId
232                                  + ": Error while loading error handler: "
233                                  + handlerPath, except);
234             }
235         }
236
237         logChannel.write(Logger.DEBUG, "RID:" + requestId
238                          + ": No error handler found for: " + presObjPath);
239         return null;
240     }
241
242
243     /**
244      * Send a simple HTML page as part of a response. This method
245      * composes a complete page with header and body sections.
246      */

247     private static void sendHtml(HttpPresentationComms comms,
248                                  String JavaDoc title,
249                                  String JavaDoc htmlText)
250             throws HttpPresentationException, IOException JavaDoc {
251
252         comms.response.setContentType("text/html");
253         HttpPresentationOutputStream out = comms.response.getOutputStream();
254
255         out.println("<HTML>");
256         out.println("<TITLE>" + title + "</TITLE>");
257         out.println("<BODY>");
258         out.println(htmlText);
259         out.println("</BODY>");
260         out.println("</HTML>");
261         comms.response.flush();
262     }
263
264
265     /**
266      * Process an unauthorized page exception, sending the approriate
267      * HTTP response. <P>
268      *
269      * Two actions are taken: a HTTP header is set telling the browser that it
270      * needs to use basic auth authentication and which relm to ask for, and
271      * the response code is set to 401, which means unauthorized. The response
272      * is now ready to return to the user, no further proccessing needs to be
273      * done on it. Most browsers will see the 401 response, and will create a
274      * dialog box asking the user to enter a username and password. The relm
275      * appears in this dialog, so the user knows what he or she is logging in
276      * to. After gathering the data, most browsers will re-issue the response,
277      * with the username and password in an HTTP header.
278      */

279     protected static void sendUnauthorizedPage(HttpPresentationComms comms,
280                                                LogChannel logChannel,
281                                                long requestId,
282                                                Application application,
283                                                String JavaDoc presObjPath,
284                                                PageUnauthorizedException unauthExcept)
285             throws HttpPresentationException, IOException JavaDoc {
286
287         try {
288             logChannel.write(Logger.DEBUG, "RID:" + requestId
289                              + ": Authentication required: " + presObjPath);
290
291             comms.response.setHeader("WWW-authenticate",
292                                      "basic realm=\"" +
293                      unauthExcept.getRelm() +"\"");
294             comms.response.setStatus(HttpPresentationResponse.SC_UNAUTHORIZED);
295             sendHtml(comms,
296                      unauthExcept.getHtmlTitle(),
297                      unauthExcept.getHtmlText());
298             comms.response.flush();
299         } catch (Exception JavaDoc except) {
300             // Make chained exception
301
HttpPresentationException presExcept =
302                 new HttpPresentationException("Exception while sending page unauthorized response", except);
303             logDisplayException(comms, logChannel, requestId, application, presExcept, presObjPath);
304         }
305     }
306
307     /**
308      * Generate an error for the maximum number of redirect's being
309      * reached.
310      */

311     protected static void maxRedirectsReached(HttpPresentationComms comms,
312                                               LogChannel logChannel,
313                                               long requestId,
314                                               int maxRedirectErrorLoops,
315                                               Application application,
316                                               String JavaDoc presObjPath)
317             throws HttpPresentationException, IOException JavaDoc {
318
319         String JavaDoc msg = "Maximum number of server redirects or ErrorHandler "
320             + "calls per request reached (" + maxRedirectErrorLoops
321             + "); probable endless loop: " + presObjPath;
322         HttpPresentationException except =
323             new HttpPresentationException(msg, comms.exception);
324         logDisplayException(comms, logChannel, requestId, application, except, presObjPath);
325     }
326
327     /**
328      * Process an exception that has not been handled by an error handler or
329      * so other mechanism.
330      */

331     protected static void processUnhandledException(HttpPresentationComms comms,
332                                                     LogChannel logChannel,
333                                                     long requestId,
334                                                     Application application,
335                                                     String JavaDoc presObjPath,
336                                                     Throwable JavaDoc except) {
337
338         try {
339             if ((except instanceof ClassNotFoundException JavaDoc)
340                 || (except instanceof NoClassDefFoundError JavaDoc)
341                 || (except instanceof FilePresentationException)) {
342
343         logChannel.write(Logger.WARNING, "RID:" + requestId
344                                  + ": page not found: " + presObjPath);
345                 comms.response.setStatus(HttpPresentationResponse.SC_NOT_FOUND);
346                 sendHtml(comms, "Page Not Found",
347                          "<B>Page was not found on this server</B>");
348             } else {
349                 logDisplayException(comms, logChannel, requestId, application, except, presObjPath);
350             }
351         } catch (Throwable JavaDoc except2) {
352             // Error handling the error; hang it up.
353
}
354     }
355 }
356
Popular Tags