You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Alex Chaffee <gu...@edamame.stinky.com> on 2000/07/19 01:44:13 UTC

[PATCH] Jasper compiler errors now show JSP line numbers

I've implemented an addition to Jasper's Compiler class that, when it gets 
a compiler error in an intermediate .java file, shows the line number from 
the original JSP file.  (I did this following an argument with Jason Hunter 
where I had to admit that JSP does indeed suck for debugging, due partly to 
the dissociation between JSP-source and Java-source).

I'm reluctant to check it in until someone else tests it for robustness -- 
and/or implements regular expressions and code for -- compilers other than 
the standard JDK 1.2 javac. Any volunteers?

It uses jakarta regexp, so check that out and put it in your classpath. On 
my system, I've modified some build files to (a) make the regexp package 
build regexp.jar into the dist directory, and (b) copy that into the Tomcat 
lib directory.  You may have to do some tweaking to make sure it's in the 
right place at the right time, until I (again) am convinced it's robust 
enough to check in.

Sample output:
Error: 500
Location:/purple/bad.jsp
Internal Servlet Error:
org.apache.jasper.JasperException: Unable to compile class for JSP
Compile error: Class foo not found.
Source file: /bad.jsp:3
Intermediate file: 
D:\jakarta-tomcat\work\localhost_8080%2Fpurple\_0002fbad_0002ejspbad_jsp_0.java:82
                  foo
                  ^
Compile error: Invalid declaration.
Source file: /bad.jsp:3
Intermediate file: 
D:\jakarta-tomcat\work\localhost_8080%2Fpurple\_0002fbad_0002ejspbad_jsp_0.java:85
                 out.write("\r\n");
                          ^

         at org.apache.jasper.compiler.Compiler.compile(Compiler.java:251)
         at org.apache.jasper.servlet.JspServlet.doLoadJSP(JspServlet.java:442)
....

  - Alex


------

jakarta-tomcat/src/share/org/apache/jasper/compiler/ErrorFinder.java:

package org.apache.jasper.compiler;

import java.io.*;
import org.apache.jasper.*;
import org.apache.regexp.*;
import org.apache.tomcat.logging.*;

/**
  * Tries to backtrack a compile error to the original JSP file
  *
  * @author Alex Chaffee (alex@jguru.com)
  **/

public class ErrorFinder extends Logger.Helper {

     RE reCompiler;
     RE reBegin;
     RE reEnd;
     RE reWindows;
     RE reMac;

     public static String newline = System.getProperty("line.separator", "\n");

     public ErrorFinder() {
         super("JASPER_LOG");

         try {
             reCompiler = new RE(":(\\d+): (.*)\\n(.*?)\\n(\\s*\\^)");
             reBegin = new RE("^\\s*// begin 
\\[file=\"(.*)\";from=\\((\\d+),(\\d+)\\);to=\\((\\d+),(\\d+)\\)\\]");
             reEnd = new RE("^\\s*// end");

             reWindows = new RE("\r\n");
             reMac = new RE("\r");

         }
         catch (RESyntaxException res) {
             log("Initializing", res);
         }
     }

     /**
      * @param ctx pointers to the various files
      * @param msg message from the compiler
      * @return string describing original error location, or null
      **/
     public String findError(JspCompilationContext ctx,
                                    String msg)
     {
         StringBuffer error = new StringBuffer();
         boolean hasError = false;
         msg = reWindows.subst(msg, "\n", RE.REPLACE_ALL);
         msg = reMac.subst(msg, "\n", RE.REPLACE_ALL);
         try {
             // for each error line in the msg
             int i=0;
             boolean match;
             do {
                 match = reCompiler.match(msg, i);
                 if (match) {
                     String lineStr = reCompiler.getParen(1);
                     String errStr = reCompiler.getParen(2);
                     String codeStr = reCompiler.getParen(3) + newline +
                         reCompiler.getParen(4);
                     i = reCompiler.getParenEnd(0);
                     System.err.println("lineStr="+lineStr+
                                        "\t errStr="+errStr+
                                        "\t i=" + i +
                                        "\n" + codeStr );

                     // found an error match, now go to compiled source
                     String javaSource = ctx.getServletJavaFileName();
                     BufferedReader in = new BufferedReader
                         (new FileReader(javaSource));
                     int lineTarget = Integer.parseInt(lineStr);
                     int lineCurrent = 0;
                     String line;
                     String file = null,
                         fromLine = null, toLine = null,
                         fromChar = null, toChar = null;
                     while ((line = in.readLine())!=null) {
                         lineCurrent++;
                         if (lineCurrent == lineTarget) {
                             // found the Java source line
                             if (file == null) {
                                 // never got a begin, so abort
                                 log("Never got a begin", Logger.DEBUG);
                                 break;  // stop reading file
                             }
                             else {
                                 // got the line of the JSP, now go parse 
the JSP
                                 String jspSource = ctx.getJspFile();

                                 // TODO: get the line referred to (if
                                 // it's only one line) -- if it spans
                                 // multiple lines, do we want to show
                                 // them all?

                                 /*
                                   String jspFile = 
ctx.getRequest().getRealPath(jspFile);
                                   String lineJsp = getLine(jspFile, 
Integer.parseInt(lineFrom), Integer.parseInt(toLine));
                                 */

                                 // we finally have it, make an output message
                                 String desc =
                                     "Compile error: " + errStr + newline +
                                     "Source file: " + jspSource + ":" + 
fromLine +
                                     (fromLine.equals(toLine) ? "" : ("-" + 
toLine)) +
                                     newline +
                                     // insert JSP source lines here
                                     "Intermediate file: " + javaSource + 
":" + lineStr + newline +
                                     codeStr + newline;

                                 System.err.println(desc);

                                 error.append(desc);
                                 hasError = true;
                                 break; // stop reading file
                             }
                         }
                         if (reBegin.match(line)) {
                             file = reBegin.getParen(1);
                             fromLine = reBegin.getParen(2);
                             fromChar = 
reBegin.getParen(3);
                             toLine = reBegin.getParen(4);
                             toChar = reBegin.getParen(5);
                         }
                         /*
                         else if (reEnd.match(line)) {
                         }
                         */
                     } // read file
                     in.close();
                 } // if match (error line number)
             }
             while (match);
         }
         catch (Throwable t) {
             log("Trying to backtrack error from " + msg, t, Logger.DEBUG);
         }
         if (hasError)
             return error.toString();
         else
             return null;
     }
}




Index: Compiler.java
===================================================================
RCS file: 
/home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/Compiler.java,v
retrieving revision 1.19
diff -u -r1.19 Compiler.java
--- Compiler.java       2000/06/27 20:59:40     1.19
+++ Compiler.java       2000/07/19 11:35:04
@@ -237,17 +237,30 @@
           */
          boolean status = javac.compile(javaFileName);

-        if (!ctxt.keepGenerated()) {
-            File javaFile = new File(javaFileName);
-            javaFile.delete();
-        }
-
-        if (status == false) {
-            String msg = out.toString ();
-            throw new 
JasperException(Constants.getString("jsp.error.unable.compile")
-                                      + msg);
-        }
-
+       try {
+           if (status == false) {
+               String msg = out.toString ();
+               ErrorFinder finder = new ErrorFinder();
+               String lineerror = finder.findError(ctxt, msg);
+               if (lineerror == null) {
+                   throw new 
JasperException(Constants.getString("jsp.error.unable.compile")
+                                             + msg);
+               }
+               else {
+                   throw new 
JasperException(Constants.getString("jsp.error.unable.compile")
+                                             + ErrorFinder.newline
+                                             + lineerror );
+               }
+
+           }
+       } // try error
+       finally {       // always kill file if necessary
+           if (!ctxt.keepGenerated()) {
+               File javaFile = new File(javaFileName);
+               javaFile.delete();
+           }
+       }
+
          String classFile = ctxt.getOutputDir() + File.separatorChar;
          if (pkgName != null && !pkgName.equals(""))
              classFile = classFile + pkgName.replace('.', 
File.separatorChar) +