1 19 20 package org.netbeans.modules.java.project; 21 22 import java.io.File ; 23 import java.net.MalformedURLException ; 24 import java.net.URL ; 25 import java.util.Arrays ; 26 import java.util.Collection ; 27 import java.util.Collections ; 28 import java.util.Iterator ; 29 import java.util.LinkedHashSet ; 30 import java.util.StringTokenizer ; 31 import java.util.regex.Matcher ; 32 import java.util.regex.Pattern ; 33 import org.apache.tools.ant.module.spi.AntEvent; 34 import org.apache.tools.ant.module.spi.AntLogger; 35 import org.apache.tools.ant.module.spi.AntSession; 36 import org.netbeans.api.java.classpath.ClassPath; 37 import org.netbeans.api.java.classpath.GlobalPathRegistry; 38 import org.netbeans.api.java.platform.JavaPlatform; 39 import org.netbeans.api.java.platform.JavaPlatformManager; 40 import org.netbeans.api.java.queries.SourceForBinaryQuery; 41 import org.openide.filesystems.FileObject; 42 import org.openide.filesystems.FileStateInvalidException; 43 import org.openide.filesystems.FileUtil; 44 45 52 public final class JavaAntLogger extends AntLogger { 53 54 57 66 private static final Pattern STACK_TRACE = Pattern.compile( 67 "(?:\t|\\[catch\\] )at ((?:[a-zA-Z_$][a-zA-Z0-9_$]*\\.)*)[a-zA-Z_$][a-zA-Z0-9_$]*\\.[a-zA-Z_$<][a-zA-Z0-9_$>]*\\(([a-zA-Z_$][a-zA-Z0-9_$]*\\.java):([0-9]+)\\)"); 69 76 private static final Pattern EXCEPTION_MESSAGE = Pattern.compile( 77 "(?:Exception in thread \"(?:main|Main Thread)\" )?(?:(?:[a-zA-Z_$][a-zA-Z0-9_$]*\\.)+)([a-zA-Z_$][a-zA-Z0-9_$]*(?:: .+)?)"); 80 90 private static final Pattern CLASSPATH_ARGS = Pattern.compile("\r?\n'-classpath'\r?\n'(.*)'\r?\n"); 92 97 private static final Pattern JAVA_EXECUTABLE = Pattern.compile("^Executing '(.*)' with arguments:$", Pattern.MULTILINE); 99 102 private static final String [] TASKS_OF_INTEREST = { 103 "java", "junit", "exec", "nb-run", }; 112 113 private static final int[] LEVELS_OF_INTEREST = { 114 AntEvent.LOG_VERBOSE, AntEvent.LOG_INFO, AntEvent.LOG_WARN, AntEvent.LOG_ERR, }; 119 120 123 private static final class SessionData { 124 public ClassPath platformSources = null; 125 public String classpath = null; 126 public Collection <FileObject> classpathSourceRoots = null; 127 public String possibleExceptionText = null; 128 public String lastExceptionMessage = null; 129 public SessionData() {} 130 public void setClasspath(String cp) { 131 classpath = cp; 132 classpathSourceRoots = null; 133 } 134 public void setPlatformSources(ClassPath platformSources) { 135 this.platformSources = platformSources; 136 classpathSourceRoots = null; 137 } 138 } 139 140 141 public JavaAntLogger() {} 142 143 public boolean interestedInSession(AntSession session) { 144 return true; 145 } 146 147 public boolean interestedInAllScripts(AntSession session) { 148 return true; 149 } 150 151 public String [] interestedInTargets(AntSession session) { 152 return AntLogger.ALL_TARGETS; 153 } 154 155 public String [] interestedInTasks(AntSession session) { 156 return TASKS_OF_INTEREST; 157 } 158 159 public int[] interestedInLogLevels(AntSession session) { 160 return LEVELS_OF_INTEREST; 162 } 163 164 private SessionData getSessionData(AntSession session) { 165 SessionData data = (SessionData) session.getCustomData(this); 166 if (data == null) { 167 data = new SessionData(); 168 session.putCustomData(this, data); 169 } 170 return data; 171 } 172 173 public void messageLogged(AntEvent event) { 174 AntSession session = event.getSession(); 175 int messageLevel = event.getLogLevel(); 176 int sessionLevel = session.getVerbosity(); 177 SessionData data = getSessionData(session); 178 String line = event.getMessage(); 179 assert line != null; 180 181 Matcher m = STACK_TRACE.matcher(line); 182 if (m.matches()) { 183 String pkg = m.group(1); 185 String filename = m.group(2); 186 String resource = pkg.replace('.', '/') + filename; 187 int lineNumber = Integer.parseInt(m.group(3)); 188 Iterator it = getCurrentSourceRootsForClasspath(data).iterator(); 191 while (it.hasNext()) { 192 FileObject root = (FileObject)it.next(); 193 FileObject source = root.getFileObject(resource); 195 if (source != null) { 196 hyperlink(line, session, event, source, messageLevel, sessionLevel, data, lineNumber); 198 break; 199 } 200 } 201 if (!event.isConsumed()) { 207 FileObject source = GlobalPathRegistry.getDefault().findResource(resource); 208 if (source != null) { 209 hyperlink(line, session, event, source, messageLevel, sessionLevel, data, lineNumber); 210 } 211 } 212 } else { 213 data.possibleExceptionText = line; 215 data.lastExceptionMessage = null; 216 } 217 218 if (messageLevel == AntEvent.LOG_VERBOSE) { 220 Matcher m2 = CLASSPATH_ARGS.matcher(line); 221 if (m2.find()) { 222 String cp = m2.group(1); 223 data.setClasspath(cp); 224 } 225 m2 = JAVA_EXECUTABLE.matcher(line); 227 if (m2.find()) { 228 String executable = m2.group(1); 229 ClassPath platformSources = findPlatformSources(executable); 230 if (platformSources != null) { 231 data.setPlatformSources(platformSources); 232 } 233 } 234 } 235 } 236 237 private ClassPath findPlatformSources(String javaExecutable) { 238 for (JavaPlatform p : JavaPlatformManager.getDefault().getInstalledPlatforms()) { 239 FileObject fo = p.findTool("java"); if (fo != null) { 241 File f = FileUtil.toFile(fo); 242 if (f.getAbsolutePath().startsWith(javaExecutable)) { 243 return p.getSourceFolders(); 244 } 245 } 246 } 247 return null; 248 } 249 250 private static void hyperlink(String line, AntSession session, AntEvent event, FileObject source, int messageLevel, int sessionLevel, SessionData data, int lineNumber) { 251 if (messageLevel <= sessionLevel && !event.isConsumed()) { 252 event.consume(); 253 try { 254 session.println(line, true, session.createStandardHyperlink(source.getURL(), guessExceptionMessage(data), lineNumber, -1, -1, -1)); 255 } catch (FileStateInvalidException e) { 256 assert false : e; 257 } 258 } 259 } 260 261 265 private static Collection getCurrentSourceRootsForClasspath(SessionData data) { 266 if (data.classpath == null) { 267 return Collections.EMPTY_SET; 268 } 269 if (data.classpathSourceRoots == null) { 270 data.classpathSourceRoots = new LinkedHashSet <FileObject>(); 271 StringTokenizer tok = new StringTokenizer (data.classpath, File.pathSeparator); 272 while (tok.hasMoreTokens()) { 273 String binrootS = tok.nextToken(); 274 File f = FileUtil.normalizeFile(new File (binrootS)); 275 URL binroot; 276 try { 277 binroot = f.toURI().toURL(); 278 } catch (MalformedURLException e) { 279 throw new AssertionError (e); 280 } 281 if (FileUtil.isArchiveFile(binroot)) { 282 URL root = FileUtil.getArchiveRoot(binroot); 283 if (root != null) { 284 binroot = root; 285 } 286 } 287 FileObject[] someRoots = SourceForBinaryQuery.findSourceRoots(binroot).getRoots(); 288 data.classpathSourceRoots.addAll(Arrays.asList(someRoots)); 289 } 290 if (data.platformSources != null) { 291 data.classpathSourceRoots.addAll(Arrays.asList(data.platformSources.getRoots())); 292 } else { 293 JavaPlatform plat = JavaPlatform.getDefault(); 295 if (plat != null) { 297 data.classpathSourceRoots.addAll(Arrays.asList(plat.getSourceFolders().getRoots())); 298 } 299 } 300 } 301 return data.classpathSourceRoots; 302 } 303 304 private static String guessExceptionMessage(SessionData data) { 305 if (data.possibleExceptionText != null) { 306 if (data.lastExceptionMessage == null) { 307 Matcher m = EXCEPTION_MESSAGE.matcher(data.possibleExceptionText); 308 if (m.matches()) { 309 data.lastExceptionMessage = m.group(1); 310 } else { 311 data.possibleExceptionText = null; 312 } 313 } 314 return data.lastExceptionMessage; 315 } 316 return null; 317 } 318 } 319 | Popular Tags |