Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » jasper » compiler » [javadoc | source]
    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;
   20   import java.io.IOException;
   21   import java.io.StringReader;
   22   import java.net.MalformedURLException;
   23   import java.util.ArrayList;
   24   
   25   import org.apache.jasper.JasperException;
   26   import org.apache.jasper.JspCompilationContext;
   27   import org.xml.sax.SAXException;
   28   
   29   /**
   30    * Class responsible for dispatching JSP parse and javac compilation errors
   31    * to the configured error handler.
   32    *
   33    * This class is also responsible for localizing any error codes before they
   34    * are passed on to the configured error handler.
   35    * 
   36    * In the case of a Java compilation error, the compiler error message is
   37    * parsed into an array of JavacErrorDetail instances, which is passed on to 
   38    * the configured error handler.
   39    *
   40    * @author Jan Luehe
   41    * @author Kin-man Chung
   42    */
   43   public class ErrorDispatcher {
   44   
   45       // Custom error handler
   46       private ErrorHandler errHandler;
   47   
   48       // Indicates whether the compilation was initiated by JspServlet or JspC
   49       private boolean jspcMode = false;
   50   
   51   
   52       /*
   53        * Constructor.
   54        *
   55        * @param jspcMode true if compilation has been initiated by JspC, false
   56        * otherwise
   57        */
   58       public ErrorDispatcher(boolean jspcMode) {
   59   	// XXX check web.xml for custom error handler
   60   	errHandler = new DefaultErrorHandler();
   61           this.jspcMode = jspcMode;
   62       }
   63   
   64       /*
   65        * Dispatches the given JSP parse error to the configured error handler.
   66        *
   67        * The given error code is localized. If it is not found in the
   68        * resource bundle for localized error messages, it is used as the error
   69        * message.
   70        *
   71        * @param errCode Error code
   72        */
   73       public void jspError(String errCode) throws JasperException {
   74   	dispatch(null, errCode, null, null);
   75       }
   76   
   77       /*
   78        * Dispatches the given JSP parse error to the configured error handler.
   79        *
   80        * The given error code is localized. If it is not found in the
   81        * resource bundle for localized error messages, it is used as the error
   82        * message.
   83        *
   84        * @param where Error location
   85        * @param errCode Error code
   86        */
   87       public void jspError(Mark where, String errCode) throws JasperException {
   88   	dispatch(where, errCode, null, null);
   89       }
   90   
   91       /*
   92        * Dispatches the given JSP parse error to the configured error handler.
   93        *
   94        * The given error code is localized. If it is not found in the
   95        * resource bundle for localized error messages, it is used as the error
   96        * message.
   97        *
   98        * @param n Node that caused the error
   99        * @param errCode Error code
  100        */
  101       public void jspError(Node n, String errCode) throws JasperException {
  102   	dispatch(n.getStart(), errCode, null, null);
  103       }
  104   
  105       /*
  106        * Dispatches the given JSP parse error to the configured error handler.
  107        *
  108        * The given error code is localized. If it is not found in the
  109        * resource bundle for localized error messages, it is used as the error
  110        * message.
  111        *
  112        * @param errCode Error code
  113        * @param arg Argument for parametric replacement
  114        */
  115       public void jspError(String errCode, String arg) throws JasperException {
  116   	dispatch(null, errCode, new Object[] {arg}, null);
  117       }
  118   
  119       /*
  120        * Dispatches the given JSP parse error to the configured error handler.
  121        *
  122        * The given error code is localized. If it is not found in the
  123        * resource bundle for localized error messages, it is used as the error
  124        * message.
  125        *
  126        * @param where Error location
  127        * @param errCode Error code
  128        * @param arg Argument for parametric replacement
  129        */
  130       public void jspError(Mark where, String errCode, String arg)
  131   	        throws JasperException {
  132   	dispatch(where, errCode, new Object[] {arg}, null);
  133       }
  134   
  135       /*
  136        * Dispatches the given JSP parse error to the configured error handler.
  137        *
  138        * The given error code is localized. If it is not found in the
  139        * resource bundle for localized error messages, it is used as the error
  140        * message.
  141        *
  142        * @param n Node that caused the error
  143        * @param errCode Error code
  144        * @param arg Argument for parametric replacement
  145        */
  146       public void jspError(Node n, String errCode, String arg)
  147   	        throws JasperException {
  148   	dispatch(n.getStart(), errCode, new Object[] {arg}, null);
  149       }
  150   
  151       /*
  152        * Dispatches the given JSP parse error to the configured error handler.
  153        *
  154        * The given error code is localized. If it is not found in the
  155        * resource bundle for localized error messages, it is used as the error
  156        * message.
  157        *
  158        * @param errCode Error code
  159        * @param arg1 First argument for parametric replacement
  160        * @param arg2 Second argument for parametric replacement
  161        */
  162       public void jspError(String errCode, String arg1, String arg2)
  163   	        throws JasperException {
  164   	dispatch(null, errCode, new Object[] {arg1, arg2}, null);
  165       }
  166   
  167       /*
  168        * Dispatches the given JSP parse error to the configured error handler.
  169        *
  170        * The given error code is localized. If it is not found in the
  171        * resource bundle for localized error messages, it is used as the error
  172        * message.
  173        *
  174        * @param errCode Error code
  175        * @param arg1 First argument for parametric replacement
  176        * @param arg2 Second argument for parametric replacement
  177        * @param arg3 Third argument for parametric replacement
  178        */
  179       public void jspError(String errCode, String arg1, String arg2, String arg3)
  180   	        throws JasperException {
  181   	dispatch(null, errCode, new Object[] {arg1, arg2, arg3}, null);
  182       }
  183   
  184       /*
  185        * Dispatches the given JSP parse error to the configured error handler.
  186        *
  187        * The given error code is localized. If it is not found in the
  188        * resource bundle for localized error messages, it is used as the error
  189        * message.
  190        *
  191        * @param where Error location
  192        * @param errCode Error code
  193        * @param arg1 First argument for parametric replacement
  194        * @param arg2 Second argument for parametric replacement
  195        */
  196       public void jspError(Mark where, String errCode, String arg1, String arg2)
  197   	        throws JasperException {
  198   	dispatch(where, errCode, new Object[] {arg1, arg2}, null);
  199       }
  200   
  201       /*
  202        * Dispatches the given JSP parse error to the configured error handler.
  203        *
  204        * The given error code is localized. If it is not found in the
  205        * resource bundle for localized error messages, it is used as the error
  206        * message.
  207        *
  208        * @param where Error location
  209        * @param errCode Error code
  210        * @param arg1 First argument for parametric replacement
  211        * @param arg2 Second argument for parametric replacement
  212        * @param arg3 Third argument for parametric replacement
  213        */
  214   
  215       public void jspError(Mark where, String errCode, String arg1, String arg2,
  216                            String arg3)
  217                   throws JasperException {
  218           dispatch(where, errCode, new Object[] {arg1, arg2, arg3}, null);
  219       }
  220   
  221       /*
  222        * Dispatches the given JSP parse error to the configured error handler.
  223        *
  224        * The given error code is localized. If it is not found in the
  225        * resource bundle for localized error messages, it is used as the error
  226        * message.
  227        *
  228        * @param n Node that caused the error
  229        * @param errCode Error code
  230        * @param arg1 First argument for parametric replacement
  231        * @param arg2 Second argument for parametric replacement
  232        */
  233   
  234       public void jspError(Node n, String errCode, String arg1, String arg2)
  235   	        throws JasperException {
  236   	dispatch(n.getStart(), errCode, new Object[] {arg1, arg2}, null);
  237       }
  238   
  239       /*
  240        * Dispatches the given JSP parse error to the configured error handler.
  241        *
  242        * The given error code is localized. If it is not found in the
  243        * resource bundle for localized error messages, it is used as the error
  244        * message.
  245        *
  246        * @param n Node that caused the error
  247        * @param errCode Error code
  248        * @param arg1 First argument for parametric replacement
  249        * @param arg2 Second argument for parametric replacement
  250        * @param arg3 Third argument for parametric replacement
  251        */
  252   
  253       public void jspError(Node n, String errCode, String arg1, String arg2,
  254                            String arg3)
  255   	        throws JasperException {
  256   	dispatch(n.getStart(), errCode, new Object[] {arg1, arg2, arg3}, null);
  257       }
  258   
  259       /*
  260        * Dispatches the given parsing exception to the configured error handler.
  261        *
  262        * @param e Parsing exception
  263        */
  264       public void jspError(Exception e) throws JasperException {
  265   	dispatch(null, null, null, e);
  266       }
  267   
  268       /*
  269        * Dispatches the given JSP parse error to the configured error handler.
  270        *
  271        * The given error code is localized. If it is not found in the
  272        * resource bundle for localized error messages, it is used as the error
  273        * message.
  274        *
  275        * @param errCode Error code
  276        * @param arg Argument for parametric replacement
  277        * @param e Parsing exception
  278        */
  279       public void jspError(String errCode, String arg, Exception e)
  280   	        throws JasperException {
  281   	dispatch(null, errCode, new Object[] {arg}, e);
  282       }
  283   
  284       /*
  285        * Dispatches the given JSP parse error to the configured error handler.
  286        *
  287        * The given error code is localized. If it is not found in the
  288        * resource bundle for localized error messages, it is used as the error
  289        * message.
  290        *
  291        * @param n Node that caused the error
  292        * @param errCode Error code
  293        * @param arg Argument for parametric replacement
  294        * @param e Parsing exception
  295        */
  296       public void jspError(Node n, String errCode, String arg, Exception e)
  297   	        throws JasperException {
  298   	dispatch(n.getStart(), errCode, new Object[] {arg}, e);
  299       }
  300   
  301       /**
  302        * Parses the given error message into an array of javac compilation error
  303        * messages (one per javac compilation error line number).
  304        *
  305        * @param errMsg Error message
  306        * @param fname Name of Java source file whose compilation failed
  307        * @param page Node representation of JSP page from which the Java source
  308        * file was generated
  309        *
  310        * @return Array of javac compilation errors, or null if the given error
  311        * message does not contain any compilation error line numbers
  312        */
  313       public static JavacErrorDetail[] parseJavacErrors(String errMsg,
  314                                                         String fname,
  315                                                         Node.Nodes page)
  316               throws JasperException, IOException {
  317   
  318   	return parseJavacMessage(errMsg, fname, page);
  319       }
  320   
  321       /*
  322        * Dispatches the given javac compilation errors to the configured error
  323        * handler.
  324        *
  325        * @param javacErrors Array of javac compilation errors
  326        */
  327       public void javacError(JavacErrorDetail[] javacErrors)
  328               throws JasperException {
  329   
  330           errHandler.javacError(javacErrors);
  331       }
  332   
  333   
  334       /*
  335        * Dispatches the given compilation error report and exception to the
  336        * configured error handler.
  337        *
  338        * @param errorReport Compilation error report
  339        * @param e Compilation exception
  340        */
  341       public void javacError(String errorReport, Exception e)
  342                   throws JasperException {
  343   
  344           errHandler.javacError(errorReport, e);
  345       }
  346   
  347   
  348       //*********************************************************************
  349       // Private utility methods
  350   
  351       /*
  352        * Dispatches the given JSP parse error to the configured error handler.
  353        *
  354        * The given error code is localized. If it is not found in the
  355        * resource bundle for localized error messages, it is used as the error
  356        * message.
  357        *
  358        * @param where Error location
  359        * @param errCode Error code
  360        * @param args Arguments for parametric replacement
  361        * @param e Parsing exception
  362        */
  363       private void dispatch(Mark where, String errCode, Object[] args,
  364   			  Exception e) throws JasperException {
  365   	String file = null;
  366   	String errMsg = null;
  367   	int line = -1;
  368   	int column = -1;
  369   	boolean hasLocation = false;
  370   
  371   	// Localize
  372   	if (errCode != null) {
  373   	    errMsg = Localizer.getMessage(errCode, args);
  374   	} else if (e != null) {
  375   	    // give a hint about what's wrong
  376   	    errMsg = e.getMessage();
  377   	}
  378   
  379   	// Get error location
  380   	if (where != null) {
  381               if (jspcMode) {
  382                   // Get the full URL of the resource that caused the error
  383                   try {
  384                       file = where.getURL().toString();
  385                   } catch (MalformedURLException me) {
  386                       // Fallback to using context-relative path
  387                       file = where.getFile();
  388                   }
  389               } else {
  390                   // Get the context-relative resource path, so as to not
  391                   // disclose any local filesystem details
  392                   file = where.getFile();
  393               }
  394   	    line = where.getLineNumber();
  395   	    column = where.getColumnNumber();
  396   	    hasLocation = true;
  397   	}
  398   
  399   	// Get nested exception
  400   	Exception nestedEx = e;
  401   	if ((e instanceof SAXException)
  402   	        && (((SAXException) e).getException() != null)) {
  403   	    nestedEx = ((SAXException) e).getException();
  404   	}
  405   
  406   	if (hasLocation) {
  407   	    errHandler.jspError(file, line, column, errMsg, nestedEx);
  408   	} else {
  409   	    errHandler.jspError(errMsg, nestedEx);
  410   	}
  411       }
  412   
  413       /*
  414        * Parses the given Java compilation error message, which may contain one
  415        * or more compilation errors, into an array of JavacErrorDetail instances.
  416        *
  417        * Each JavacErrorDetail instance contains the information about a single
  418        * compilation error.
  419        *
  420        * @param errMsg Compilation error message that was generated by the
  421        * javac compiler
  422        * @param fname Name of Java source file whose compilation failed
  423        * @param page Node representation of JSP page from which the Java source
  424        * file was generated
  425        *
  426        * @return Array of JavacErrorDetail instances corresponding to the
  427        * compilation errors
  428        */
  429       private static JavacErrorDetail[] parseJavacMessage(
  430                                   String errMsg, String fname, Node.Nodes page)
  431   	        throws IOException, JasperException {
  432   
  433           ArrayList<JavacErrorDetail> errors = new ArrayList<JavacErrorDetail>();
  434           StringBuffer errMsgBuf = null;
  435           int lineNum = -1;
  436           JavacErrorDetail javacError = null;
  437           
  438           BufferedReader reader = new BufferedReader(new StringReader(errMsg));
  439           
  440           /*
  441            * Parse compilation errors. Each compilation error consists of a file
  442            * path and error line number, followed by a number of lines describing
  443            * the error.
  444            */
  445           String line = null;
  446           while ((line = reader.readLine()) != null) {
  447               
  448               /*
  449                * Error line number is delimited by set of colons.
  450                * Ignore colon following drive letter on Windows (fromIndex = 2).
  451                * XXX Handle deprecation warnings that don't have line info
  452                */
  453               int beginColon = line.indexOf(':', 2); 
  454               int endColon = line.indexOf(':', beginColon + 1);
  455               if ((beginColon >= 0) && (endColon >= 0)) {
  456                   if (javacError != null) {
  457                       // add previous error to error vector
  458                       errors.add(javacError);
  459                   }
  460                   
  461                   String lineNumStr = line.substring(beginColon + 1, endColon);
  462                   try {
  463                       lineNum = Integer.parseInt(lineNumStr);
  464                   } catch (NumberFormatException e) {
  465                       lineNum = -1;
  466                   }
  467                   
  468                   errMsgBuf = new StringBuffer();
  469                   
  470                   javacError = createJavacError(fname, page, errMsgBuf, lineNum);
  471               }
  472               
  473               // Ignore messages preceding first error
  474               if (errMsgBuf != null) {
  475                   errMsgBuf.append(line);
  476                   errMsgBuf.append("\n");
  477               }
  478           }
  479           
  480           // Add last error to error vector
  481           if (javacError != null) {
  482               errors.add(javacError);
  483           } 
  484           
  485           reader.close();
  486           
  487           JavacErrorDetail[] errDetails = null;
  488           if (errors.size() > 0) {
  489               errDetails = new JavacErrorDetail[errors.size()];
  490               errors.toArray(errDetails);
  491           }
  492           
  493           return errDetails;
  494       }
  495   
  496   
  497       /**
  498        * @param fname
  499        * @param page
  500        * @param errMsgBuf
  501        * @param lineNum
  502        * @return JavacErrorDetail The error details
  503        * @throws JasperException
  504        */
  505       public static JavacErrorDetail createJavacError(String fname,
  506               Node.Nodes page, StringBuffer errMsgBuf, int lineNum)
  507       throws JasperException {
  508           return createJavacError(fname, page, errMsgBuf, lineNum, null);
  509       }
  510       
  511       
  512       /**
  513        * @param fname
  514        * @param page
  515        * @param errMsgBuf
  516        * @param lineNum
  517        * @param ctxt
  518        * @return JavacErrorDetail The error details
  519        * @throws JasperException
  520        */
  521       public static JavacErrorDetail createJavacError(String fname,
  522               Node.Nodes page, StringBuffer errMsgBuf, int lineNum,
  523               JspCompilationContext ctxt) throws JasperException {
  524           JavacErrorDetail javacError;
  525           // Attempt to map javac error line number to line in JSP page
  526           ErrorVisitor errVisitor = new ErrorVisitor(lineNum);
  527           page.visit(errVisitor);
  528           Node errNode = errVisitor.getJspSourceNode();
  529           if ((errNode != null) && (errNode.getStart() != null)) {
  530               // If this is a scriplet node then there is a one to one mapping
  531               // between JSP lines and Java lines
  532               if (errVisitor.getJspSourceNode() instanceof Node.Scriptlet) {
  533                   javacError = new JavacErrorDetail(
  534                           fname,
  535                           lineNum,
  536                           errNode.getStart().getFile(),
  537                           errNode.getStart().getLineNumber() + lineNum -
  538                               errVisitor.getJspSourceNode().getBeginJavaLine(),
  539                           errMsgBuf,
  540                           ctxt);
  541               } else {
  542                   javacError = new JavacErrorDetail(
  543                           fname,
  544                           lineNum,
  545                           errNode.getStart().getFile(),
  546                           errNode.getStart().getLineNumber(),
  547                           errMsgBuf,
  548                           ctxt);
  549               }
  550           } else {
  551               /*
  552                * javac error line number cannot be mapped to JSP page
  553                * line number. For example, this is the case if a 
  554                * scriptlet is missing a closing brace, which causes
  555                * havoc with the try-catch-finally block that the code
  556                * generator places around all generated code: As a result
  557                * of this, the javac error line numbers will be outside
  558                * the range of begin and end java line numbers that were
  559                * generated for the scriptlet, and therefore cannot be
  560                * mapped to the start line number of the scriptlet in the
  561                * JSP page.
  562                * Include just the javac error info in the error detail.
  563                */
  564               javacError = new JavacErrorDetail(
  565                       fname,
  566                       lineNum,
  567                       errMsgBuf);
  568           }
  569           return javacError;
  570       }
  571   
  572   
  573       /*
  574        * Visitor responsible for mapping a line number in the generated servlet
  575        * source code to the corresponding JSP node.
  576        */
  577       static class ErrorVisitor extends Node.Visitor {
  578   
  579   	// Java source line number to be mapped
  580   	private int lineNum;
  581   
  582   	/*
  583   	 * JSP node whose Java source code range in the generated servlet
  584   	 * contains the Java source line number to be mapped
  585   	 */
  586   	Node found;
  587   
  588   	/*
  589   	 * Constructor.
  590   	 *
  591   	 * @param lineNum Source line number in the generated servlet code
  592   	 */
  593   	public ErrorVisitor(int lineNum) {
  594   	    this.lineNum = lineNum;
  595   	}
  596   
  597   	public void doVisit(Node n) throws JasperException {
  598   	    if ((lineNum >= n.getBeginJavaLine())
  599   		    && (lineNum < n.getEndJavaLine())) {
  600   		found = n;
  601   	    }
  602           }
  603   
  604   	/*
  605   	 * Gets the JSP node to which the source line number in the generated
  606   	 * servlet code was mapped.
  607   	 *
  608   	 * @return JSP node to which the source line number in the generated
  609   	 * servlet code was mapped
  610   	 */
  611   	public Node getJspSourceNode() {
  612   	    return found;
  613   	}
  614       }
  615   }

Save This Page
Home » apache-tomcat-6.0.26-src » org.apache » jasper » compiler » [javadoc | source]