KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > web > jspcompiler > JSPJavacAntLogger


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.web.jspcompiler;
21
22 import java.io.File JavaDoc;
23 import java.io.IOException JavaDoc;
24 import java.io.PrintWriter JavaDoc;
25
26 import java.net.MalformedURLException JavaDoc;
27 import java.net.URL JavaDoc;
28 import java.util.regex.Matcher JavaDoc;
29 import java.util.regex.Pattern JavaDoc;
30 import org.apache.tools.ant.module.spi.AntEvent;
31 import org.apache.tools.ant.module.spi.AntLogger;
32 import org.apache.tools.ant.module.spi.AntSession;
33 import org.netbeans.modules.web.api.webmodule.WebModule;
34 import org.openide.ErrorManager;
35 import org.openide.filesystems.FileObject;
36 import org.openide.filesystems.FileStateInvalidException;
37 import org.openide.filesystems.FileUtil;
38 import org.openide.windows.OutputListener;
39
40 /**
41  * Ant logger which handles compilation of JSPs, both the JSP -> Java and
42  * the Java -> class compilation stages.
43  * Specifically, handles hyperlinking of errors from JspC and from Javac run on
44  * classes generated from JSPs.
45  * @author Petr Jiricka, Jesse Glick
46  * @see "#42525"
47  */

48 public final class JSPJavacAntLogger extends AntLogger {
49     
50 // private static PrintWriter debugwriter = null;
51
// private static void debug(String s) {
52
// if (debugwriter == null) {
53
// try {
54
// debugwriter = new PrintWriter(new java.io.FileWriter("/local/repo/trunk/nb_all/nbbuild/AntOutputParser.log")); // NOI18N
55
// } catch (java.io.IOException ioe) {
56
// return;
57
// }
58
// }
59
// debugwriter.println(s);
60
// debugwriter.flush();
61
// }
62

63     private static final ErrorManager ERR = ErrorManager.getDefault().getInstance(JSPJavacAntLogger.class.getName());
64     private static final boolean LOGGABLE = ERR.isLoggable(ErrorManager.INFORMATIONAL);
65     
66     /**
67      * Regexp matching the compilation error from JspC. Sample message could look like this:
68      * org.apache.jasper.JasperException: file:C:/project/AntParseTestProject2/build/web/index.jsp(6,0) Include action: Mandatory attribute page missing
69      */

70     private static final Pattern JavaDoc JSP_COMPILER_ERROR = Pattern.compile(
71         "(.*)(org.apache.jasper.JasperException: file:)([^\\(]*)\\(([0-9]+),([0-9]+)\\)(.*)"); // NOI18N
72

73
74     private static final String JavaDoc[] TASKS_OF_INTEREST = AntLogger.ALL_TASKS;
75     
76     private static final int[] LEVELS_OF_INTEREST = {
77         //AntEvent.LOG_DEBUG, // XXX is this needed?
78
//AntEvent.LOG_VERBOSE, // XXX is this needed?
79
AntEvent.LOG_INFO, // XXX is this needed?
80
AntEvent.LOG_WARN, // XXX is this needed?
81
AntEvent.LOG_ERR, // XXX is this needed?
82
};
83     
84     
85     /** Default constructor for lookup. */
86     public JSPJavacAntLogger() {}
87     
88     public boolean interestedInSession(AntSession session) {
89         return true;
90     }
91     
92     public boolean interestedInAllScripts(AntSession session) {
93         return true;
94     }
95     
96     public boolean interestedInScript(File JavaDoc script, AntSession session) {
97         return true;
98     }
99     
100     public String JavaDoc[] interestedInTargets(AntSession session) {
101         return AntLogger.ALL_TARGETS;
102     }
103     
104     public String JavaDoc[] interestedInTasks(AntSession session) {
105         return TASKS_OF_INTEREST;
106     }
107     
108     public int[] interestedInLogLevels(AntSession session) {
109         // XXX could exclude those in [INFO..ERR] greater than session.verbosity
110
return LEVELS_OF_INTEREST;
111     }
112
113     
114     private static FileObject guessWebModuleOutputRoot(WebModule wm, FileObject fo) {
115         /*
116         File outputF = wm.getWebOutputRoot();
117         if (outputF != null) {
118             return FileUtil.toFileObject(outputF);
119         }
120         */

121         FileObject potentialRoot = fo.getParent();
122         while (potentialRoot != null) {
123             if (potentialRoot.getFileObject("WEB-INF") != null) {
124                 return potentialRoot;
125             }
126             potentialRoot = potentialRoot.getParent();
127         }
128         return null;
129     }
130     
131     public void messageLogged(AntEvent event) {
132         if (event.isConsumed()) {
133             return;
134         }
135         AntSession session = event.getSession();
136         String JavaDoc line = event.getMessage();
137         OutputListener hyper = findHyperlink(session, line);
138         // XXX should translate tabs to spaces here as a safety measure
139
if (hyper != null) {
140             event.getSession().println(line, event.getLogLevel() <= AntEvent.LOG_WARN, hyper);
141             event.consume();
142         }
143     }
144
145     /**
146      * Possibly hyperlink a message logged event.
147      */

148     private static OutputListener findHyperlink(AntSession session, String JavaDoc line) {
149         if (LOGGABLE) ERR.log("line: " + line);
150         // #29246: handle new (Ant 1.5.1) URLifications:
151
// [PENDING] Under JDK 1.4, could use new File(URI)... if Ant uses URI too (Jakarta BZ #8031)
152
// XXX so tweak that for Ant 1.6 support!
153
// XXX would be much easier to use a regexp here
154
if (line.startsWith("file:///")) { // NOI18N
155
line = line.substring(7);
156             if (LOGGABLE) ERR.log("removing file:///");
157         } else if (line.startsWith("file:")) { // NOI18N
158
line = line.substring(5);
159             if (LOGGABLE) ERR.log("removing file:");
160         } else if (line.length() > 0 && line.charAt(0) == '/') {
161             if (LOGGABLE) ERR.log("result: looks like Unix file");
162         } else if (line.length() > 2 && line.charAt(1) == ':' && line.charAt(2) == '\\') {
163             if (LOGGABLE) ERR.log("result: looks like Windows file");
164         } else {
165             // not a file -> nothing to parse
166
if (LOGGABLE) ERR.log("result: not a file");
167             return null;
168         }
169         
170         int colon1 = line.indexOf(':');
171         if (colon1 == -1) {
172             if (LOGGABLE) ERR.log("result: no colon found");
173             return null;
174         }
175         String JavaDoc fileName = line.substring (0, colon1); //.replace(File.separatorChar, '/');
176
File JavaDoc file = FileUtil.normalizeFile(new File JavaDoc(fileName));
177         if (!file.exists()) {
178             if (LOGGABLE) ERR.log("result: no FO for " + fileName);
179             // maybe we are on Windows and filename is "c:\temp\file.java:25"
180
// try to do the same for the second colon
181
colon1 = line.indexOf (':', colon1+1);
182             if (colon1 == -1) {
183                 if (LOGGABLE) ERR.log("result: no second colon found");
184                 return null;
185             }
186             fileName = line.substring (0, colon1);
187             file = FileUtil.normalizeFile(new File JavaDoc(fileName));
188             if (!file.exists()) {
189                 if (LOGGABLE) ERR.log("result: no FO for " + fileName);
190                 return null;
191             }
192         }
193
194         int line1 = -1, col1 = -1, line2 = -1, col2 = -1;
195         int start = colon1 + 1; // start of message
196
int colon2 = line.indexOf (':', colon1 + 1);
197         if (colon2 != -1) {
198             try {
199                 line1 = Integer.parseInt (line.substring (colon1 + 1, colon2).trim ());
200                 start = colon2 + 1;
201                 int colon3 = line.indexOf (':', colon2 + 1);
202                 if (colon3 != -1) {
203                     col1 = Integer.parseInt (line.substring (colon2 + 1, colon3).trim ());
204                     start = colon3 + 1;
205                     int colon4 = line.indexOf (':', colon3 + 1);
206                     if (colon4 != -1) {
207                         line2 = Integer.parseInt (line.substring (colon3 + 1, colon4).trim ());
208                         start = colon4 + 1;
209                         int colon5 = line.indexOf (':', colon4 + 1);
210                         if (colon5 != -1) {
211                             col2 = Integer.parseInt (line.substring (colon4 + 1, colon5).trim ());
212                             if (col2 == col1)
213                                 col2 = -1;
214                             start = colon5 + 1;
215                         }
216                     }
217                 }
218             } catch (NumberFormatException JavaDoc nfe) {
219                 // Fine, rest is part of the message.
220
}
221         }
222         String JavaDoc message = line.substring (start).trim ();
223         if (message.length () == 0) {
224             message = null;
225         }
226         if (LOGGABLE) ERR.log("Hyperlink: [" + file + "," + line1 + "," + col1 + "," + line2 + "," + col2 + "," + message + "]");
227
228         File JavaDoc smapFile = getSMAPFileForFile(file);
229         if (LOGGABLE) ERR.log("smapfile: [" + smapFile + "]");
230         if ((smapFile != null) && (smapFile.exists())) {
231             try {
232                 SmapResolver resolver = new SmapResolver(new SmapFileReader(smapFile));
233                 String JavaDoc jspName = resolver.getJspFileName(line1, col1);
234                 if (jspName == null) {
235                     return null;
236                 }
237                 if (LOGGABLE) ERR.log("translate: [" + line1 + ", " + col1 + "]");
238                 int newRow = resolver.unmangle(line1, col1);
239 //debug ("translated to '" + jspName + ":" + newRow + "'");
240
// some mappings may not exist, so try next or previous lines, too
241
if (newRow == -1) {
242                     newRow = resolver.unmangle(line1-1, col1);
243                     jspName = resolver.getJspFileName(line1-1, col1);
244                 }
245                 if (newRow == -1) {
246                     newRow = resolver.unmangle(line1+1, col1);
247                     jspName = resolver.getJspFileName(line1+1, col1);
248                 }
249                 try {
250                     WebModule wm = WebModule.getWebModule(FileUtil.toFileObject(file));
251                     if (wm == null) {
252                         return null;
253                     }
254                     FileObject jspFO = wm.getDocumentBase().getFileObject(jspName);
255 //debug ("jsp '" + jspFO + "'");
256
if (jspFO != null) {
257                         return session.createStandardHyperlink(FileUtil.toFile(jspFO).toURI().toURL(), message, newRow, -1, -1, -1);
258                     }
259                     return null;
260                 } catch (MalformedURLException JavaDoc e) {
261                     assert false : e;
262                     return null;
263                 }
264             }
265             catch (IOException JavaDoc e) {
266                 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
267                 // PENDING
268
return null;
269             }
270             catch (Exception JavaDoc e) {
271                 // PENDING - this catch clause should not be here, it's here only to
272
// hide bugs in the SmapResolver library
273
ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
274                 return null;
275             }
276         } else {
277             return null;
278         }
279         
280     }
281     
282     private static final String JavaDoc JAVA_SUFFIX = ".java"; // NOI18N
283
private static final String JavaDoc SMAP_SUFFIX = ".class.smap"; // NOI18N
284
/** Returns a SMAP file corresponding to the given file, if exists.
285      */

286     public static File JavaDoc getSMAPFileForFile(File JavaDoc javaFile) {
287         File JavaDoc f = FileUtil.normalizeFile(javaFile);
288         File JavaDoc dir = f.getAbsoluteFile().getParentFile();
289         String JavaDoc name = f.getName();
290         if (!name.endsWith(JAVA_SUFFIX)) {
291             return null;
292         }
293         name = name.substring(0, name.length() - JAVA_SUFFIX.length());
294         File JavaDoc newFile = new File JavaDoc(dir, name + SMAP_SUFFIX);
295         return newFile;
296     }
297     
298 }
299
Popular Tags