KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > valves > ErrorReportValve


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.valves;
20
21
22 import java.io.IOException JavaDoc;
23 import java.io.Writer JavaDoc;
24
25 import javax.servlet.ServletException JavaDoc;
26 import javax.servlet.ServletRequest JavaDoc;
27 import javax.servlet.ServletResponse JavaDoc;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29
30 import org.apache.catalina.Globals;
31 import org.apache.catalina.connector.Request;
32 import org.apache.catalina.connector.Response;
33 import org.apache.catalina.util.RequestUtil;
34 import org.apache.catalina.util.ServerInfo;
35 import org.apache.catalina.util.StringManager;
36 import org.apache.tomcat.util.IntrospectionUtils;
37
38 /**
39  * <p>Implementation of a Valve that outputs HTML error pages.</p>
40  *
41  * <p>This Valve should be attached at the Host level, although it will work
42  * if attached to a Context.</p>
43  *
44  * <p>HTML code from the Cocoon 2 project.</p>
45  *
46  * @author Remy Maucherat
47  * @author Craig R. McClanahan
48  * @author <a HREF="mailto:nicolaken@supereva.it">Nicola Ken Barozzi</a> Aisa
49  * @author <a HREF="mailto:stefano@apache.org">Stefano Mazzocchi</a>
50  * @author Yoav Shapira
51  * @version $Revision: 470756 $ $Date: 2006-11-03 11:56:25 +0100 (ven., 03 nov. 2006) $
52  */

53
54 public class ErrorReportValve
55     extends ValveBase {
56
57
58     // ----------------------------------------------------- Instance Variables
59

60
61     /**
62      * The descriptive information related to this implementation.
63      */

64     private static final String JavaDoc info =
65         "org.apache.catalina.valves.ErrorReportValve/1.0";
66
67
68     /**
69      * The StringManager for this package.
70      */

71     protected static StringManager sm =
72         StringManager.getManager(Constants.Package);
73
74
75     // ------------------------------------------------------------- Properties
76

77
78     /**
79      * Return descriptive information about this Valve implementation.
80      */

81     public String JavaDoc getInfo() {
82
83         return (info);
84
85     }
86
87
88     // --------------------------------------------------------- Public Methods
89

90
91     /**
92      * Invoke the next Valve in the sequence. When the invoke returns, check
93      * the response state, and output an error report is necessary.
94      *
95      * @param request The servlet request to be processed
96      * @param response The servlet response to be created
97      *
98      * @exception IOException if an input/output error occurs
99      * @exception ServletException if a servlet error occurs
100      */

101     public void invoke(Request JavaDoc request, Response JavaDoc response)
102         throws IOException JavaDoc, ServletException JavaDoc {
103
104         // Perform the request
105
getNext().invoke(request, response);
106
107         ServletRequest JavaDoc sreq = (ServletRequest JavaDoc) request;
108         Throwable JavaDoc throwable =
109             (Throwable JavaDoc) sreq.getAttribute(Globals.EXCEPTION_ATTR);
110
111         ServletResponse JavaDoc sresp = (ServletResponse JavaDoc) response;
112         if (sresp.isCommitted()) {
113             return;
114         }
115
116         if (throwable != null) {
117
118             // The response is an error
119
response.setError();
120
121             // Reset the response (if possible)
122
try {
123                 sresp.reset();
124             } catch (IllegalStateException JavaDoc e) {
125                 ;
126             }
127
128             response.sendError
129                 (HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
130
131         }
132
133         response.setSuspended(false);
134
135         try {
136             report(request, response, throwable);
137         } catch (Throwable JavaDoc tt) {
138             ;
139         }
140
141     }
142
143
144     // ------------------------------------------------------ Protected Methods
145

146
147     /**
148      * Prints out an error report.
149      *
150      * @param request The request being processed
151      * @param response The response being generated
152      * @param throwable The exception that occurred (which possibly wraps
153      * a root cause exception
154      */

155     protected void report(Request JavaDoc request, Response JavaDoc response,
156                           Throwable JavaDoc throwable) {
157
158         // Do nothing on non-HTTP responses
159
int statusCode = response.getStatus();
160
161         // Do nothing on a 1xx, 2xx and 3xx status
162
// Do nothing if anything has been written already
163
if ((statusCode < 400) || (response.getContentCount() > 0))
164             return;
165
166         Throwable JavaDoc rootCause = null;
167
168         if (throwable != null) {
169
170             if (throwable instanceof ServletException JavaDoc)
171                 rootCause = ((ServletException JavaDoc) throwable).getRootCause();
172
173         }
174
175         String JavaDoc message = RequestUtil.filter(response.getMessage());
176         if (message == null)
177             message = "";
178
179         // Do nothing if there is no report for the specified status code
180
String JavaDoc report = null;
181         try {
182             report = sm.getString("http." + statusCode, message);
183         } catch (Throwable JavaDoc t) {
184             ;
185         }
186         if (report == null)
187             return;
188
189         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
190
191         sb.append("<html><head><title>");
192         sb.append(ServerInfo.getServerInfo()).append(" - ");
193         sb.append(sm.getString("errorReportValve.errorReport"));
194         sb.append("</title>");
195         sb.append("<style><!--");
196         sb.append(org.apache.catalina.util.TomcatCSS.TOMCAT_CSS);
197         sb.append("--></style> ");
198         sb.append("</head><body>");
199         sb.append("<h1>");
200         sb.append(sm.getString("errorReportValve.statusHeader",
201                                "" + statusCode, message)).append("</h1>");
202         sb.append("<HR size=\"1\" noshade=\"noshade\">");
203         sb.append("<p><b>type</b> ");
204         if (throwable != null) {
205             sb.append(sm.getString("errorReportValve.exceptionReport"));
206         } else {
207             sb.append(sm.getString("errorReportValve.statusReport"));
208         }
209         sb.append("</p>");
210         sb.append("<p><b>");
211         sb.append(sm.getString("errorReportValve.message"));
212         sb.append("</b> <u>");
213         sb.append(message).append("</u></p>");
214         sb.append("<p><b>");
215         sb.append(sm.getString("errorReportValve.description"));
216         sb.append("</b> <u>");
217         sb.append(report);
218         sb.append("</u></p>");
219
220         if (throwable != null) {
221
222             String JavaDoc stackTrace = getPartialServletStackTrace(throwable);
223             sb.append("<p><b>");
224             sb.append(sm.getString("errorReportValve.exception"));
225             sb.append("</b> <pre>");
226             sb.append(RequestUtil.filter(stackTrace));
227             sb.append("</pre></p>");
228
229             int loops = 0;
230             while (rootCause != null && (loops < 10)) {
231                 stackTrace = getPartialServletStackTrace(rootCause);
232                 sb.append("<p><b>");
233                 sb.append(sm.getString("errorReportValve.rootCause"));
234                 sb.append("</b> <pre>");
235                 sb.append(RequestUtil.filter(stackTrace));
236                 sb.append("</pre></p>");
237                 // In case root cause is somehow heavily nested
238
rootCause = rootCause.getCause();
239                 loops++;
240             }
241
242             sb.append("<p><b>");
243             sb.append(sm.getString("errorReportValve.note"));
244             sb.append("</b> <u>");
245             sb.append(sm.getString("errorReportValve.rootCauseInLogs",
246                                    ServerInfo.getServerInfo()));
247             sb.append("</u></p>");
248
249         }
250
251         sb.append("<HR size=\"1\" noshade=\"noshade\">");
252         sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
253         sb.append("</body></html>");
254
255         try {
256             try {
257                 response.setContentType("text/html");
258                 response.setCharacterEncoding("utf-8");
259             } catch (Throwable JavaDoc t) {
260                 if (container.getLogger().isDebugEnabled())
261                     container.getLogger().debug("status.setContentType", t);
262             }
263             Writer JavaDoc writer = response.getReporter();
264             if (writer != null) {
265                 // If writer is null, it's an indication that the response has
266
// been hard committed already, which should never happen
267
writer.write(sb.toString());
268             }
269         } catch (IOException JavaDoc e) {
270             ;
271         } catch (IllegalStateException JavaDoc e) {
272             ;
273         }
274         
275     }
276
277
278     /**
279      * Print out a partial servlet stack trace (truncating at the last
280      * occurrence of javax.servlet.).
281      */

282     protected String JavaDoc getPartialServletStackTrace(Throwable JavaDoc t) {
283         StringBuffer JavaDoc trace = new StringBuffer JavaDoc();
284         trace.append(t.toString()).append('\n');
285         StackTraceElement JavaDoc[] elements = t.getStackTrace();
286         int pos = elements.length;
287         for (int i = 0; i < elements.length; i++) {
288             if ((elements[i].getClassName().startsWith
289                  ("org.apache.catalina.core.ApplicationFilterChain"))
290                 && (elements[i].getMethodName().equals("internalDoFilter"))) {
291                 pos = i;
292             }
293         }
294         for (int i = 0; i < pos; i++) {
295             if (!(elements[i].getClassName().startsWith
296                   ("org.apache.catalina.core."))) {
297                 trace.append('\t').append(elements[i].toString()).append('\n');
298             }
299         }
300         return trace.toString();
301     }
302
303 }
304
Popular Tags