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 }