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) +