KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jasper > compiler > ErrorDispatcher


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 package org.apache.jasper.compiler;
18
19 import java.io.BufferedReader JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.StringReader JavaDoc;
22 import java.net.MalformedURLException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24
25 import org.apache.jasper.JasperException;
26 import org.xml.sax.SAXException JavaDoc;
27
28 /**
29  * Class responsible for dispatching JSP parse and javac compilation errors
30  * to the configured error handler.
31  *
32  * This class is also responsible for localizing any error codes before they
33  * are passed on to the configured error handler.
34  *
35  * In the case of a Java compilation error, the compiler error message is
36  * parsed into an array of JavacErrorDetail instances, which is passed on to
37  * the configured error handler.
38  *
39  * @author Jan Luehe
40  * @author Kin-man Chung
41  */

42 public class ErrorDispatcher {
43
44     // Custom error handler
45
private ErrorHandler errHandler;
46
47     // Indicates whether the compilation was initiated by JspServlet or JspC
48
private boolean jspcMode = false;
49
50
51     /*
52      * Constructor.
53      *
54      * @param jspcMode true if compilation has been initiated by JspC, false
55      * otherwise
56      */

57     public ErrorDispatcher(boolean jspcMode) {
58     // XXX check web.xml for custom error handler
59
errHandler = new DefaultErrorHandler();
60         this.jspcMode = jspcMode;
61     }
62
63     /*
64      * Dispatches the given JSP parse error to the configured error handler.
65      *
66      * The given error code is localized. If it is not found in the
67      * resource bundle for localized error messages, it is used as the error
68      * message.
69      *
70      * @param errCode Error code
71      */

72     public void jspError(String JavaDoc errCode) throws JasperException {
73     dispatch(null, errCode, null, null);
74     }
75
76     /*
77      * Dispatches the given JSP parse error to the configured error handler.
78      *
79      * The given error code is localized. If it is not found in the
80      * resource bundle for localized error messages, it is used as the error
81      * message.
82      *
83      * @param where Error location
84      * @param errCode Error code
85      */

86     public void jspError(Mark where, String JavaDoc errCode) throws JasperException {
87     dispatch(where, errCode, null, null);
88     }
89
90     /*
91      * Dispatches the given JSP parse error to the configured error handler.
92      *
93      * The given error code is localized. If it is not found in the
94      * resource bundle for localized error messages, it is used as the error
95      * message.
96      *
97      * @param n Node that caused the error
98      * @param errCode Error code
99      */

100     public void jspError(Node n, String JavaDoc errCode) throws JasperException {
101     dispatch(n.getStart(), errCode, null, null);
102     }
103
104     /*
105      * Dispatches the given JSP parse error to the configured error handler.
106      *
107      * The given error code is localized. If it is not found in the
108      * resource bundle for localized error messages, it is used as the error
109      * message.
110      *
111      * @param errCode Error code
112      * @param arg Argument for parametric replacement
113      */

114     public void jspError(String JavaDoc errCode, String JavaDoc arg) throws JasperException {
115     dispatch(null, errCode, new Object JavaDoc[] {arg}, null);
116     }
117
118     /*
119      * Dispatches the given JSP parse error to the configured error handler.
120      *
121      * The given error code is localized. If it is not found in the
122      * resource bundle for localized error messages, it is used as the error
123      * message.
124      *
125      * @param where Error location
126      * @param errCode Error code
127      * @param arg Argument for parametric replacement
128      */

129     public void jspError(Mark where, String JavaDoc errCode, String JavaDoc arg)
130             throws JasperException {
131     dispatch(where, errCode, new Object JavaDoc[] {arg}, null);
132     }
133
134     /*
135      * Dispatches the given JSP parse error to the configured error handler.
136      *
137      * The given error code is localized. If it is not found in the
138      * resource bundle for localized error messages, it is used as the error
139      * message.
140      *
141      * @param n Node that caused the error
142      * @param errCode Error code
143      * @param arg Argument for parametric replacement
144      */

145     public void jspError(Node n, String JavaDoc errCode, String JavaDoc arg)
146             throws JasperException {
147     dispatch(n.getStart(), errCode, new Object JavaDoc[] {arg}, null);
148     }
149
150     /*
151      * Dispatches the given JSP parse error to the configured error handler.
152      *
153      * The given error code is localized. If it is not found in the
154      * resource bundle for localized error messages, it is used as the error
155      * message.
156      *
157      * @param errCode Error code
158      * @param arg1 First argument for parametric replacement
159      * @param arg2 Second argument for parametric replacement
160      */

161     public void jspError(String JavaDoc errCode, String JavaDoc arg1, String JavaDoc arg2)
162             throws JasperException {
163     dispatch(null, errCode, new Object JavaDoc[] {arg1, arg2}, null);
164     }
165
166     /*
167      * Dispatches the given JSP parse error to the configured error handler.
168      *
169      * The given error code is localized. If it is not found in the
170      * resource bundle for localized error messages, it is used as the error
171      * message.
172      *
173      * @param errCode Error code
174      * @param arg1 First argument for parametric replacement
175      * @param arg2 Second argument for parametric replacement
176      * @param arg3 Third argument for parametric replacement
177      */

178     public void jspError(String JavaDoc errCode, String JavaDoc arg1, String JavaDoc arg2, String JavaDoc arg3)
179             throws JasperException {
180     dispatch(null, errCode, new Object JavaDoc[] {arg1, arg2, arg3}, null);
181     }
182
183     /*
184      * Dispatches the given JSP parse error to the configured error handler.
185      *
186      * The given error code is localized. If it is not found in the
187      * resource bundle for localized error messages, it is used as the error
188      * message.
189      *
190      * @param where Error location
191      * @param errCode Error code
192      * @param arg1 First argument for parametric replacement
193      * @param arg2 Second argument for parametric replacement
194      */

195     public void jspError(Mark where, String JavaDoc errCode, String JavaDoc arg1, String JavaDoc arg2)
196             throws JasperException {
197     dispatch(where, errCode, new Object JavaDoc[] {arg1, arg2}, null);
198     }
199
200     /*
201      * Dispatches the given JSP parse error to the configured error handler.
202      *
203      * The given error code is localized. If it is not found in the
204      * resource bundle for localized error messages, it is used as the error
205      * message.
206      *
207      * @param where Error location
208      * @param errCode Error code
209      * @param arg1 First argument for parametric replacement
210      * @param arg2 Second argument for parametric replacement
211      * @param arg3 Third argument for parametric replacement
212      */

213
214     public void jspError(Mark where, String JavaDoc errCode, String JavaDoc arg1, String JavaDoc arg2,
215                          String JavaDoc arg3)
216                 throws JasperException {
217         dispatch(where, errCode, new Object JavaDoc[] {arg1, arg2, arg3}, null);
218     }
219
220     /*
221      * Dispatches the given JSP parse error to the configured error handler.
222      *
223      * The given error code is localized. If it is not found in the
224      * resource bundle for localized error messages, it is used as the error
225      * message.
226      *
227      * @param n Node that caused the error
228      * @param errCode Error code
229      * @param arg1 First argument for parametric replacement
230      * @param arg2 Second argument for parametric replacement
231      */

232
233     public void jspError(Node n, String JavaDoc errCode, String JavaDoc arg1, String JavaDoc arg2)
234             throws JasperException {
235     dispatch(n.getStart(), errCode, new Object JavaDoc[] {arg1, arg2}, null);
236     }
237
238     /*
239      * Dispatches the given JSP parse error to the configured error handler.
240      *
241      * The given error code is localized. If it is not found in the
242      * resource bundle for localized error messages, it is used as the error
243      * message.
244      *
245      * @param n Node that caused the error
246      * @param errCode Error code
247      * @param arg1 First argument for parametric replacement
248      * @param arg2 Second argument for parametric replacement
249      * @param arg3 Third argument for parametric replacement
250      */

251
252     public void jspError(Node n, String JavaDoc errCode, String JavaDoc arg1, String JavaDoc arg2,
253                          String JavaDoc arg3)
254             throws JasperException {
255     dispatch(n.getStart(), errCode, new Object JavaDoc[] {arg1, arg2, arg3}, null);
256     }
257
258     /*
259      * Dispatches the given parsing exception to the configured error handler.
260      *
261      * @param e Parsing exception
262      */

263     public void jspError(Exception JavaDoc e) throws JasperException {
264     dispatch(null, null, null, e);
265     }
266
267     /*
268      * Dispatches the given JSP parse error to the configured error handler.
269      *
270      * The given error code is localized. If it is not found in the
271      * resource bundle for localized error messages, it is used as the error
272      * message.
273      *
274      * @param errCode Error code
275      * @param arg Argument for parametric replacement
276      * @param e Parsing exception
277      */

278     public void jspError(String JavaDoc errCode, String JavaDoc arg, Exception JavaDoc e)
279             throws JasperException {
280     dispatch(null, errCode, new Object JavaDoc[] {arg}, e);
281     }
282
283     /*
284      * Dispatches the given JSP parse error to the configured error handler.
285      *
286      * The given error code is localized. If it is not found in the
287      * resource bundle for localized error messages, it is used as the error
288      * message.
289      *
290      * @param n Node that caused the error
291      * @param errCode Error code
292      * @param arg Argument for parametric replacement
293      * @param e Parsing exception
294      */

295     public void jspError(Node n, String JavaDoc errCode, String JavaDoc arg, Exception JavaDoc e)
296             throws JasperException {
297     dispatch(n.getStart(), errCode, new Object JavaDoc[] {arg}, e);
298     }
299
300     /**
301      * Parses the given error message into an array of javac compilation error
302      * messages (one per javac compilation error line number).
303      *
304      * @param errMsg Error message
305      * @param fname Name of Java source file whose compilation failed
306      * @param page Node representation of JSP page from which the Java source
307      * file was generated
308      *
309      * @return Array of javac compilation errors, or null if the given error
310      * message does not contain any compilation error line numbers
311      */

312     public static JavacErrorDetail[] parseJavacErrors(String JavaDoc errMsg,
313                                                       String JavaDoc fname,
314                                                       Node.Nodes page)
315             throws JasperException, IOException JavaDoc {
316
317     return parseJavacMessage(errMsg, fname, page);
318     }
319
320     /*
321      * Dispatches the given javac compilation errors to the configured error
322      * handler.
323      *
324      * @param javacErrors Array of javac compilation errors
325      */

326     public void javacError(JavacErrorDetail[] javacErrors)
327             throws JasperException {
328
329         errHandler.javacError(javacErrors);
330     }
331
332
333     /*
334      * Dispatches the given compilation error report and exception to the
335      * configured error handler.
336      *
337      * @param errorReport Compilation error report
338      * @param e Compilation exception
339      */

340     public void javacError(String JavaDoc errorReport, Exception JavaDoc e)
341                 throws JasperException {
342
343         errHandler.javacError(errorReport, e);
344     }
345
346
347     //*********************************************************************
348
// Private utility methods
349

350     /*
351      * Dispatches the given JSP parse error to the configured error handler.
352      *
353      * The given error code is localized. If it is not found in the
354      * resource bundle for localized error messages, it is used as the error
355      * message.
356      *
357      * @param where Error location
358      * @param errCode Error code
359      * @param args Arguments for parametric replacement
360      * @param e Parsing exception
361      */

362     private void dispatch(Mark where, String JavaDoc errCode, Object JavaDoc[] args,
363               Exception JavaDoc e) throws JasperException {
364     String JavaDoc file = null;
365     String JavaDoc errMsg = null;
366     int line = -1;
367     int column = -1;
368     boolean hasLocation = false;
369
370     // Localize
371
if (errCode != null) {
372         errMsg = Localizer.getMessage(errCode, args);
373     } else if (e != null) {
374         // give a hint about what's wrong
375
errMsg = e.getMessage();
376     }
377
378     // Get error location
379
if (where != null) {
380             if (jspcMode) {
381                 // Get the full URL of the resource that caused the error
382
try {
383                     file = where.getURL().toString();
384                 } catch (MalformedURLException JavaDoc me) {
385                     // Fallback to using context-relative path
386
file = where.getFile();
387                 }
388             } else {
389                 // Get the context-relative resource path, so as to not
390
// disclose any local filesystem details
391
file = where.getFile();
392             }
393         line = where.getLineNumber();
394         column = where.getColumnNumber();
395         hasLocation = true;
396     }
397
398     // Get nested exception
399
Exception JavaDoc nestedEx = e;
400     if ((e instanceof SAXException JavaDoc)
401             && (((SAXException JavaDoc) e).getException() != null)) {
402         nestedEx = ((SAXException JavaDoc) e).getException();
403     }
404
405     if (hasLocation) {
406         errHandler.jspError(file, line, column, errMsg, nestedEx);
407     } else {
408         errHandler.jspError(errMsg, nestedEx);
409     }
410     }
411
412     /*
413      * Parses the given Java compilation error message, which may contain one
414      * or more compilation errors, into an array of JavacErrorDetail instances.
415      *
416      * Each JavacErrorDetail instance contains the information about a single
417      * compilation error.
418      *
419      * @param errMsg Compilation error message that was generated by the
420      * javac compiler
421      * @param fname Name of Java source file whose compilation failed
422      * @param page Node representation of JSP page from which the Java source
423      * file was generated
424      *
425      * @return Array of JavacErrorDetail instances corresponding to the
426      * compilation errors
427      */

428     private static JavacErrorDetail[] parseJavacMessage(
429                                 String JavaDoc errMsg, String JavaDoc fname, Node.Nodes page)
430             throws IOException JavaDoc, JasperException {
431
432         ArrayList JavaDoc<JavacErrorDetail> errors = new ArrayList JavaDoc<JavacErrorDetail>();
433         StringBuffer JavaDoc errMsgBuf = null;
434         int lineNum = -1;
435         JavacErrorDetail javacError = null;
436         
437         BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new StringReader JavaDoc(errMsg));
438         
439         /*
440          * Parse compilation errors. Each compilation error consists of a file
441          * path and error line number, followed by a number of lines describing
442          * the error.
443          */

444         String JavaDoc line = null;
445         while ((line = reader.readLine()) != null) {
446             
447             /*
448              * Error line number is delimited by set of colons.
449              * Ignore colon following drive letter on Windows (fromIndex = 2).
450              * XXX Handle deprecation warnings that don't have line info
451              */

452             int beginColon = line.indexOf(':', 2);
453             int endColon = line.indexOf(':', beginColon + 1);
454             if ((beginColon >= 0) && (endColon >= 0)) {
455                 if (javacError != null) {
456                     // add previous error to error vector
457
errors.add(javacError);
458                 }
459                 
460                 String JavaDoc lineNumStr = line.substring(beginColon + 1, endColon);
461                 try {
462                     lineNum = Integer.parseInt(lineNumStr);
463                 } catch (NumberFormatException JavaDoc e) {
464                     lineNum = -1;
465                 }
466                 
467                 errMsgBuf = new StringBuffer JavaDoc();
468                 
469                 javacError = createJavacError(fname, page, errMsgBuf, lineNum);
470             }
471             
472             // Ignore messages preceding first error
473
if (errMsgBuf != null) {
474                 errMsgBuf.append(line);
475                 errMsgBuf.append("\n");
476             }
477         }
478         
479         // Add last error to error vector
480
if (javacError != null) {
481             errors.add(javacError);
482         }
483         
484         reader.close();
485         
486         JavacErrorDetail[] errDetails = null;
487         if (errors.size() > 0) {
488             errDetails = new JavacErrorDetail[errors.size()];
489             errors.toArray(errDetails);
490         }
491         
492         return errDetails;
493     }
494
495
496     /**
497      * @param fname
498      * @param page
499      * @param errMsgBuf
500      * @param lineNum
501      * @return JavacErrorDetail The error details
502      * @throws JasperException
503      */

504     public static JavacErrorDetail createJavacError(String JavaDoc fname, Node.Nodes page,
505             StringBuffer JavaDoc errMsgBuf, int lineNum) throws JasperException {
506         JavacErrorDetail javacError;
507         // Attempt to map javac error line number to line in JSP page
508
ErrorVisitor errVisitor = new ErrorVisitor(lineNum);
509         page.visit(errVisitor);
510         Node errNode = errVisitor.getJspSourceNode();
511         if ((errNode != null) && (errNode.getStart() != null)) {
512             javacError = new JavacErrorDetail(
513                     fname,
514                     lineNum,
515                     errNode.getStart().getFile(),
516                     errNode.getStart().getLineNumber(),
517                     errMsgBuf);
518         } else {
519             /*
520              * javac error line number cannot be mapped to JSP page
521              * line number. For example, this is the case if a
522              * scriptlet is missing a closing brace, which causes
523              * havoc with the try-catch-finally block that the code
524              * generator places around all generated code: As a result
525              * of this, the javac error line numbers will be outside
526              * the range of begin and end java line numbers that were
527              * generated for the scriptlet, and therefore cannot be
528              * mapped to the start line number of the scriptlet in the
529              * JSP page.
530              * Include just the javac error info in the error detail.
531              */

532             javacError = new JavacErrorDetail(
533                     fname,
534                     lineNum,
535                     errMsgBuf);
536         }
537         return javacError;
538     }
539
540
541     /*
542      * Visitor responsible for mapping a line number in the generated servlet
543      * source code to the corresponding JSP node.
544      */

545     static class ErrorVisitor extends Node.Visitor {
546
547     // Java source line number to be mapped
548
private int lineNum;
549
550     /*
551      * JSP node whose Java source code range in the generated servlet
552      * contains the Java source line number to be mapped
553      */

554     Node found;
555
556     /*
557      * Constructor.
558      *
559      * @param lineNum Source line number in the generated servlet code
560      */

561     public ErrorVisitor(int lineNum) {
562         this.lineNum = lineNum;
563     }
564
565     public void doVisit(Node n) throws JasperException {
566         if ((lineNum >= n.getBeginJavaLine())
567             && (lineNum < n.getEndJavaLine())) {
568         found = n;
569         }
570         }
571
572     /*
573      * Gets the JSP node to which the source line number in the generated
574      * servlet code was mapped.
575      *
576      * @return JSP node to which the source line number in the generated
577      * servlet code was mapped
578      */

579     public Node getJspSourceNode() {
580         return found;
581     }
582     }
583 }
584
Popular Tags