You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by yo...@apache.org on 2005/10/17 00:08:12 UTC

svn commit: r322516 - in /tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper: compiler/Compiler.java servlet/JspServletWrapper.java

Author: yoavs
Date: Sun Oct 16 15:08:10 2005
New Revision: 322516

URL: http://svn.apache.org/viewcvs?rev=322516&view=rev
Log:
Bugzilla 37062: http://issues.apache.org/bugzilla/show_bug.cgi?id=37062

Modified:
    tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/compiler/Compiler.java
    tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java

Modified: tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/compiler/Compiler.java
URL: http://svn.apache.org/viewcvs/tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/compiler/Compiler.java?rev=322516&r1=322515&r2=322516&view=diff
==============================================================================
--- tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/compiler/Compiler.java (original)
+++ tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/compiler/Compiler.java Sun Oct 16 15:08:10 2005
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999,2004 The Apache Software Foundation.
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -76,6 +76,15 @@
 
     // --------------------------------------------------------- Public Methods
 
+    /**
+     * <p>Retrieves the parsed nodes of the JSP page, if they are available.
+     * May return null.  Used in development mode for generating detailed
+     * error messages.  http://issues.apache.org/bugzilla/show_bug.cgi?id=37062.
+     * </p>
+     */
+    public Node.Nodes getPageNodes() {
+        return this.pageNodes;
+    }
 
     /** 
      * Compile the jsp file into equivalent servlet in .java file
@@ -298,7 +307,15 @@
             tfp = null;
             errDispatcher = null;
             pageInfo = null;
-            pageNodes = null;
+
+            // Only get rid of the pageNodes if in production.
+            // In development mode, they are used for detailed
+            // error messages.
+            // http://issues.apache.org/bugzilla/show_bug.cgi?id=37062
+            if(!this.options.getDevelopment()) {
+                pageNodes = null;
+            }
+
             if (ctxt.getWriter() != null) {
                 ctxt.getWriter().close();
                 ctxt.setWriter(null);

Modified: tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java
URL: http://svn.apache.org/viewcvs/tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java?rev=322516&r1=322515&r2=322516&view=diff
==============================================================================
--- tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java (original)
+++ tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper/servlet/JspServletWrapper.java Sun Oct 16 15:08:10 2005
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999,2004 The Apache Software Foundation.
+ * Copyright 1999,2004-2005 The Apache Software Foundation.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,9 +16,16 @@
 
 package org.apache.jasper.servlet;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.IOException;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
@@ -35,6 +42,8 @@
 import org.apache.jasper.JasperException;
 import org.apache.jasper.JspCompilationContext;
 import org.apache.jasper.Options;
+import org.apache.jasper.compiler.ErrorDispatcher;
+import org.apache.jasper.compiler.JavacErrorDetail;
 import org.apache.jasper.compiler.JspRuntimeContext;
 import org.apache.jasper.compiler.Localizer;
 import org.apache.jasper.runtime.JspSourceDependent;
@@ -54,6 +63,7 @@
  * @author Remy Maucherat
  * @author Kin-man Chung
  * @author Glenn Nielsen
+ * @author Tim Fennell
  */
 
 public class JspServletWrapper {
@@ -361,13 +371,29 @@
                 }
             }
         } catch (ServletException ex) {
-	    throw ex;
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw ex;
+            }
         } catch (IOException ex) {
-            throw ex;
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw ex;
+            }
         } catch (IllegalStateException ex) {
-            throw ex;
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw ex;
+            }
         } catch (Exception ex) {
-            throw new JasperException(ex);
+            if(options.getDevelopment()) {
+                throw handleJspException(ex);
+            } else {
+                throw new JasperException(ex);
+            }
         }
     }
 
@@ -389,5 +415,116 @@
     public void setLastModificationTest(long lastModificationTest) {
         this.lastModificationTest = lastModificationTest;
     }
-    
+
+    /**
+     * <p>Attempts to construct a JasperException that contains helpful information
+     * about what went wrong. Uses the JSP compiler system to translate the line
+     * number in the generated servlet that originated the exception to a line
+     * number in the JSP.  Then constructs an exception containing that
+     * information, and a snippet of the JSP to help debugging.
+     * Please see http://issues.apache.org/bugzilla/show_bug.cgi?id=37062 and
+     * http://www.tfenne.com/jasper/ for more details.
+     *</p>
+     *
+     * @param ex the exception that was the cause of the problem.
+     * @return a JasperException with more detailed information
+     */
+    protected JasperException handleJspException(Exception ex) {
+        try {
+            Throwable realException = ex;
+            if (ex instanceof ServletException) {
+                realException = ((ServletException) ex).getRootCause();
+            }
+
+            // First identify the stack frame in the trace that represents the JSP
+            StackTraceElement[] frames = realException.getStackTrace();
+            StackTraceElement jspFrame = null;
+
+            for (int i=0; i<frames.length; ++i) {
+                if ( frames[i].getClassName().equals(this.getServlet().getClass().getName()) ) {
+                    jspFrame = frames[i];
+                    break;
+                }
+            }
+
+            if (jspFrame == null) {
+                // If we couldn't find a frame in the stack trace corresponding
+                // to the generated servlet class, we can't really add anything
+                return new JasperException(ex);
+            }
+            else {
+                int javaLineNumber = jspFrame.getLineNumber();
+                JavacErrorDetail detail = ErrorDispatcher.createJavacError(
+                                                                           jspFrame.getMethodName(),
+                                                                           this.ctxt.getCompiler().getPageNodes(),
+                                                                           null,
+                                                                           javaLineNumber);
+
+                // If the line number is less than one we couldn't find out
+                // where in the JSP things went wrong
+                int jspLineNumber = detail.getJspBeginLineNumber();
+                if (jspLineNumber < 1) {
+                    throw new JasperException(ex);
+                }
+
+                // Read both files in, so we can inspect them
+                String[] jspLines = readFile
+                    (this.ctxt.getResourceAsStream(this.ctxt.getJspFile()));
+
+                String[] javaLines = readFile
+                    (new FileInputStream(this.ctxt.getServletJavaFileName()));
+
+                // If the line contains the opening of a multi-line scriptlet
+                // block, then the JSP line number we got back is probably
+                // faulty.  Scan forward to match the java line...
+                if (jspLines[jspLineNumber-1].lastIndexOf("<%") >
+                    jspLines[jspLineNumber-1].lastIndexOf("%>")) {
+                    String javaLine = javaLines[javaLineNumber-1].trim();
+
+                    for (int i=jspLineNumber-1; i<jspLines.length; i++) {
+                        if (jspLines[i].indexOf(javaLine) != -1) {
+                            jspLineNumber = i+1;
+                            break;
+                        }
+                    }
+                }
+
+                // copy out a fragment of JSP to display to the user
+                StringBuffer buffer = new StringBuffer(1024);
+                int startIndex = Math.max(0, jspLineNumber-1-3);
+                int endIndex = Math.min(jspLines.length-1, jspLineNumber-1+3);
+
+                for (int i=startIndex;i<=endIndex; ++i) {
+                    buffer.append(i+1);
+                    buffer.append(": ");
+                    buffer.append(jspLines[i]);
+                    buffer.append("\n");
+                }
+
+                return new JasperException(
+                                           "Exception in JSP: " + detail.getJspFileName() + ":" +
+                                           jspLineNumber + "\n\n" + buffer + "\n\nStacktrace:", ex);
+            }
+        } catch (Exception je) {
+            // If anything goes wrong, just revert to the original behaviour
+            return new JasperException(ex);
+        }
+    }
+
+    /**
+     * Reads a text file from an input stream into a String[]. Used to read in
+     * the JSP and generated Java file when generating error messages.
+     */
+    private String[] readFile(InputStream s) throws IOException {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(s));
+        List lines = new ArrayList();
+        String line;
+
+        while ( (line = reader.readLine()) != null ) {
+            lines.add(line);
+        }
+
+        return (String[]) lines.toArray( new String[lines.size()] );
+    }
+
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: svn commit: r322516 - in /tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper: compiler/Compiler.java servlet/JspServletWrapper.java

Posted by Bill Barker <wb...@wilshire.com>.
----- Original Message ----- 
From: <yo...@apache.org>
To: <to...@jakarta.apache.org>
Sent: Sunday, October 16, 2005 3:08 PM
Subject: svn commit: r322516 - in 
/tomcat/jasper/tc5.5.x/jasper2/src/share/org/apache/jasper: 
compiler/Compiler.java servlet/JspServletWrapper.java


> Author: yoavs
> Date: Sun Oct 16 15:08:10 2005
> New Revision: 322516
>
> URL: http://svn.apache.org/viewcvs?rev=322516&view=rev
> Log:
> Bugzilla 37062: http://issues.apache.org/bugzilla/show_bug.cgi?id=37062
>

It would be much better to re-work the patch to use the smap files, instead 
of holding the entire JSP page in memory.  Since it only kills off 
development servers, I guess I'm ok with it as is :).



This message is intended only for the use of the person(s) listed above as the intended recipient(s), and may contain information that is PRIVILEGED and CONFIDENTIAL.  If you are not an intended recipient, you may not read, copy, or distribute this message or any attachment. If you received this communication in error, please notify us immediately by e-mail and then delete all copies of this message and any attachments.

In addition you should be aware that ordinary (unencrypted) e-mail sent through the Internet is not secure. Do not send confidential or sensitive information, such as social security numbers, account numbers, personal identification numbers and passwords, to us via ordinary (unencrypted) e-mail.


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org