View Javadoc

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  
18  package org.apache.jasper.compiler;
19  
20  import java.io.BufferedReader;
21  import java.io.FileInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.apache.jasper.JspCompilationContext;
29  
30  /**
31   * Class providing details about a javac compilation error.
32   *
33   * @author Jan Luehe
34   * @author Kin-man Chung
35   */
36  public class JavacErrorDetail {
37  
38      private String javaFileName;
39      private int javaLineNum;
40      private String jspFileName;
41      private int jspBeginLineNum;
42      private StringBuffer errMsg;
43      private String jspExtract = null;
44  
45      /**
46       * Constructor.
47       *
48       * @param javaFileName The name of the Java file in which the 
49       * compilation error occurred
50       * @param javaLineNum The compilation error line number
51       * @param errMsg The compilation error message
52       */
53      public JavacErrorDetail(String javaFileName,
54                              int javaLineNum,
55                              StringBuffer errMsg) {
56  
57          this.javaFileName = javaFileName;
58          this.javaLineNum = javaLineNum;
59          this.errMsg = errMsg;
60          this.jspBeginLineNum = -1;
61      }
62  
63      /**
64       * Constructor.
65       *
66       * @param javaFileName The name of the Java file in which the 
67       * compilation error occurred
68       * @param javaLineNum The compilation error line number
69       * @param jspFileName The name of the JSP file from which the Java source
70       * file was generated
71       * @param jspBeginLineNum The start line number of the JSP element
72       * responsible for the compilation error
73       * @param errMsg The compilation error message
74       */
75      public JavacErrorDetail(String javaFileName,
76                              int javaLineNum,
77                              String jspFileName,
78                              int jspBeginLineNum,
79                              StringBuffer errMsg) {
80  
81          this(javaFileName, javaLineNum, jspFileName, jspBeginLineNum, errMsg,
82                  null);
83      }
84  
85      public JavacErrorDetail(String javaFileName,
86              int javaLineNum,
87              String jspFileName,
88              int jspBeginLineNum,
89              StringBuffer errMsg,
90              JspCompilationContext ctxt) {
91          
92          this(javaFileName, javaLineNum, errMsg);
93          this.jspFileName = jspFileName;
94          this.jspBeginLineNum = jspBeginLineNum;
95          
96          if (jspBeginLineNum > 0 && ctxt != null) {
97              InputStream is = null;
98              FileInputStream  fis = null;
99              
100             try {
101                 // Read both files in, so we can inspect them
102                 is = ctxt.getResourceAsStream(jspFileName);
103                 String[] jspLines = readFile(is);
104     
105                 fis = new FileInputStream(ctxt.getServletJavaFileName());
106                 String[] javaLines = readFile(fis);
107     
108                 // If the line contains the opening of a multi-line scriptlet
109                 // block, then the JSP line number we got back is probably
110                 // faulty.  Scan forward to match the java line...
111                 if (jspLines[jspBeginLineNum-1].lastIndexOf("<%") >
112                     jspLines[jspBeginLineNum-1].lastIndexOf("%>")) {
113                     String javaLine = javaLines[javaLineNum-1].trim();
114     
115                     for (int i=jspBeginLineNum-1; i<jspLines.length; i++) {
116                         if (jspLines[i].indexOf(javaLine) != -1) {
117                             // Update jsp line number
118                             this.jspBeginLineNum = i+1;
119                             break;
120                         }
121                     }
122                 }
123     
124                 // copy out a fragment of JSP to display to the user
125                 StringBuffer fragment = new StringBuffer(1024);
126                 int startIndex = Math.max(0, this.jspBeginLineNum-1-3);
127                 int endIndex = Math.min(
128                         jspLines.length-1, this.jspBeginLineNum-1+3);
129     
130                 for (int i=startIndex;i<=endIndex; ++i) {
131                     fragment.append(i+1);
132                     fragment.append(": ");
133                     fragment.append(jspLines[i]);
134                     fragment.append("\n");
135                 }
136                 jspExtract = fragment.toString();
137     
138             } catch (IOException ioe) {
139                 // Can't read files - ignore
140             } finally {
141                 if (is != null) {
142                     try {
143                         is.close();
144                     } catch (IOException ioe) {
145                         // Ignore
146                     }
147                 }
148                 if (fis != null) {
149                     try {
150                         fis.close();
151                     } catch (IOException ioe) {
152                         // Ignore
153                     }
154                 }
155             }
156         }
157     }
158 
159     /**
160      * Gets the name of the Java source file in which the compilation error
161      * occurred.
162      *
163      * @return Java source file name
164      */
165     public String getJavaFileName() {
166         return this.javaFileName;
167     }
168 
169     /**
170      * Gets the compilation error line number.
171      * 
172      * @return Compilation error line number
173      */
174     public int getJavaLineNumber() {
175         return this.javaLineNum;
176     }
177 
178     /**
179      * Gets the name of the JSP file from which the Java source file was
180      * generated.
181      *
182      * @return JSP file from which the Java source file was generated.
183      */
184     public String getJspFileName() {
185         return this.jspFileName;
186     }
187 
188     /**
189      * Gets the start line number (in the JSP file) of the JSP element
190      * responsible for the compilation error.
191      *
192      * @return Start line number of the JSP element responsible for the
193      * compilation error
194      */
195     public int getJspBeginLineNumber() {
196         return this.jspBeginLineNum;
197     }
198 
199     /**
200      * Gets the compilation error message.
201      *
202      * @return Compilation error message
203      */
204     public String getErrorMessage() {
205         return this.errMsg.toString();
206     }
207     
208     /**
209      * Gets the extract of the JSP that corresponds to this message.
210      *
211      * @return Extract of JSP where error occurred
212      */
213     public String getJspExtract() {
214         return this.jspExtract;
215     }
216     
217     /**
218      * Reads a text file from an input stream into a String[]. Used to read in
219      * the JSP and generated Java file when generating error messages.
220      */
221     private String[] readFile(InputStream s) throws IOException {
222         BufferedReader reader = new BufferedReader(new InputStreamReader(s));
223         List lines = new ArrayList();
224         String line;
225 
226         while ( (line = reader.readLine()) != null ) {
227             lines.add(line);
228         }
229 
230         return (String[]) lines.toArray( new String[lines.size()] );
231     }
232 }