001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper.compiler;
019:
020: import java.io.BufferedReader;
021: import java.io.FileInputStream;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.InputStreamReader;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: import org.apache.jasper.JspCompilationContext;
029:
030: /**
031: * Class providing details about a javac compilation error.
032: *
033: * @author Jan Luehe
034: * @author Kin-man Chung
035: */
036: public class JavacErrorDetail {
037:
038: private String javaFileName;
039: private int javaLineNum;
040: private String jspFileName;
041: private int jspBeginLineNum;
042: private StringBuffer errMsg;
043: private String jspExtract = null;
044:
045: /**
046: * Constructor.
047: *
048: * @param javaFileName The name of the Java file in which the
049: * compilation error occurred
050: * @param javaLineNum The compilation error line number
051: * @param errMsg The compilation error message
052: */
053: public JavacErrorDetail(String javaFileName, int javaLineNum,
054: StringBuffer errMsg) {
055:
056: this .javaFileName = javaFileName;
057: this .javaLineNum = javaLineNum;
058: this .errMsg = errMsg;
059: this .jspBeginLineNum = -1;
060: }
061:
062: /**
063: * Constructor.
064: *
065: * @param javaFileName The name of the Java file in which the
066: * compilation error occurred
067: * @param javaLineNum The compilation error line number
068: * @param jspFileName The name of the JSP file from which the Java source
069: * file was generated
070: * @param jspBeginLineNum The start line number of the JSP element
071: * responsible for the compilation error
072: * @param errMsg The compilation error message
073: */
074: public JavacErrorDetail(String javaFileName, int javaLineNum,
075: String jspFileName, int jspBeginLineNum, StringBuffer errMsg) {
076:
077: this (javaFileName, javaLineNum, jspFileName, jspBeginLineNum,
078: errMsg, null);
079: }
080:
081: public JavacErrorDetail(String javaFileName, int javaLineNum,
082: String jspFileName, int jspBeginLineNum,
083: StringBuffer errMsg, JspCompilationContext ctxt) {
084:
085: this (javaFileName, javaLineNum, errMsg);
086: this .jspFileName = jspFileName;
087: this .jspBeginLineNum = jspBeginLineNum;
088:
089: if (jspBeginLineNum > 0 && ctxt != null) {
090: InputStream is = null;
091: FileInputStream fis = null;
092:
093: try {
094: // Read both files in, so we can inspect them
095: is = ctxt.getResourceAsStream(jspFileName);
096: String[] jspLines = readFile(is);
097:
098: fis = new FileInputStream(ctxt.getServletJavaFileName());
099: String[] javaLines = readFile(fis);
100:
101: // If the line contains the opening of a multi-line scriptlet
102: // block, then the JSP line number we got back is probably
103: // faulty. Scan forward to match the java line...
104: if (jspLines[jspBeginLineNum - 1].lastIndexOf("<%") > jspLines[jspBeginLineNum - 1]
105: .lastIndexOf("%>")) {
106: String javaLine = javaLines[javaLineNum - 1].trim();
107:
108: for (int i = jspBeginLineNum - 1; i < jspLines.length; i++) {
109: if (jspLines[i].indexOf(javaLine) != -1) {
110: // Update jsp line number
111: this .jspBeginLineNum = i + 1;
112: break;
113: }
114: }
115: }
116:
117: // copy out a fragment of JSP to display to the user
118: StringBuffer fragment = new StringBuffer(1024);
119: int startIndex = Math.max(0,
120: this .jspBeginLineNum - 1 - 3);
121: int endIndex = Math.min(jspLines.length - 1,
122: this .jspBeginLineNum - 1 + 3);
123:
124: for (int i = startIndex; i <= endIndex; ++i) {
125: fragment.append(i + 1);
126: fragment.append(": ");
127: fragment.append(jspLines[i]);
128: fragment.append("\n");
129: }
130: jspExtract = fragment.toString();
131:
132: } catch (IOException ioe) {
133: // Can't read files - ignore
134: } finally {
135: if (is != null) {
136: try {
137: is.close();
138: } catch (IOException ioe) {
139: // Ignore
140: }
141: }
142: if (fis != null) {
143: try {
144: fis.close();
145: } catch (IOException ioe) {
146: // Ignore
147: }
148: }
149: }
150: }
151: }
152:
153: /**
154: * Gets the name of the Java source file in which the compilation error
155: * occurred.
156: *
157: * @return Java source file name
158: */
159: public String getJavaFileName() {
160: return this .javaFileName;
161: }
162:
163: /**
164: * Gets the compilation error line number.
165: *
166: * @return Compilation error line number
167: */
168: public int getJavaLineNumber() {
169: return this .javaLineNum;
170: }
171:
172: /**
173: * Gets the name of the JSP file from which the Java source file was
174: * generated.
175: *
176: * @return JSP file from which the Java source file was generated.
177: */
178: public String getJspFileName() {
179: return this .jspFileName;
180: }
181:
182: /**
183: * Gets the start line number (in the JSP file) of the JSP element
184: * responsible for the compilation error.
185: *
186: * @return Start line number of the JSP element responsible for the
187: * compilation error
188: */
189: public int getJspBeginLineNumber() {
190: return this .jspBeginLineNum;
191: }
192:
193: /**
194: * Gets the compilation error message.
195: *
196: * @return Compilation error message
197: */
198: public String getErrorMessage() {
199: return this .errMsg.toString();
200: }
201:
202: /**
203: * Gets the extract of the JSP that corresponds to this message.
204: *
205: * @return Extract of JSP where error occurred
206: */
207: public String getJspExtract() {
208: return this .jspExtract;
209: }
210:
211: /**
212: * Reads a text file from an input stream into a String[]. Used to read in
213: * the JSP and generated Java file when generating error messages.
214: */
215: private String[] readFile(InputStream s) throws IOException {
216: BufferedReader reader = new BufferedReader(
217: new InputStreamReader(s));
218: List lines = new ArrayList();
219: String line;
220:
221: while ((line = reader.readLine()) != null) {
222: lines.add(line);
223: }
224:
225: return (String[]) lines.toArray(new String[lines.size()]);
226: }
227: }
|