1 19 20 package org.apache.tools.ant.module.run; 21 22 import java.io.File ; 23 import java.net.MalformedURLException ; 24 import java.net.URL ; 25 import java.util.ArrayList ; 26 import java.util.Arrays ; 27 import java.util.Collections ; 28 import java.util.List ; 29 import java.util.Map ; 30 import java.util.Set ; 31 import java.util.WeakHashMap ; 32 import java.util.logging.Level ; 33 import java.util.regex.Matcher ; 34 import java.util.regex.Pattern ; 35 import org.apache.tools.ant.module.spi.AntEvent; 36 import org.apache.tools.ant.module.spi.AntLogger; 37 import org.apache.tools.ant.module.spi.AntSession; 38 import org.apache.tools.ant.module.spi.TaskStructure; 39 import org.netbeans.junit.NbTestCase; 40 import org.openide.filesystems.FileUtil; 41 import org.openide.util.NbBundle; 42 import org.openide.util.Utilities; 43 import org.openide.util.WeakSet; 44 import org.openide.windows.OutputEvent; 45 import org.openide.windows.OutputListener; 46 47 51 public class StandardLoggerTest extends NbTestCase { 52 53 55 public StandardLoggerTest(String name) { 56 super(name); 57 } 58 59 public void testBasicUsage() throws Exception { 60 AntLogger[] loggers = new AntLogger[] {new StandardLogger(15345L)}; 65 MockAntSession session = new MockAntSession(loggers, AntEvent.LOG_INFO); 66 AntSession realSession = LoggerTrampoline.ANT_SESSION_CREATOR.makeAntSession(session); 67 session.sendBuildStarted(makeAntEvent(realSession, null, -1, null, null, null)); 68 session.sendTargetStarted(makeAntEvent(realSession, null, -1, null, "some-target", null)); 69 session.sendMessageLogged(makeAntEvent(realSession, "some message", AntEvent.LOG_WARN, null, null, null)); 70 session.sendTargetFinished(makeAntEvent(realSession, null, -1, null, "some-target", null)); 71 session.sendBuildFinished(makeAntEvent(realSession, null, -1, null, null, null)); 72 List <Message> expectedMessages = Arrays.asList(new Message[] { 73 new Message(NbBundle.getMessage(StandardLogger.class, "MSG_target_started_printed", "some-target"), false, null), 74 new Message("some message", true, null), 75 new Message(NbBundle.getMessage(StandardLogger.class, "FMT_finished_target_printed", new Integer (0), new Integer (15)), false, null), 76 }); 77 assertEquals("correct text printed", expectedMessages, session.messages); 78 } 79 80 public void testMultilineMessagesSplit() throws Exception { 81 AntLogger[] loggers = new AntLogger[] {new MockStackTraceLogger(), new StandardLogger(1000L)}; 84 MockAntSession session = new MockAntSession(loggers, AntEvent.LOG_INFO); 85 AntSession realSession = LoggerTrampoline.ANT_SESSION_CREATOR.makeAntSession(session); 86 session.sendBuildStarted(makeAntEvent(realSession, null, -1, null, null, null)); 87 session.sendMessageLogged(makeAntEvent(realSession, "Stack trace in separate lines:", AntEvent.LOG_INFO, null, null, null)); 88 session.sendMessageLogged(makeAntEvent(realSession, "\tat Foo.java:3", AntEvent.LOG_INFO, null, null, null)); 89 session.sendMessageLogged(makeAntEvent(realSession, "\tat Bar.java:5", AntEvent.LOG_INFO, null, null, null)); 90 session.sendMessageLogged(makeAntEvent(realSession, "Stack trace in one big line:\n" + 91 "\tat Quux.java:11\n" + 92 "\tat Baz.java:6\n" + 93 "...and an unrelated message", 94 AntEvent.LOG_WARN, null, null, null)); 95 session.sendBuildFinished(makeAntEvent(realSession, null, -1, null, null, null)); 96 List <Message> expectedMessages = Arrays.asList(new Message[] { 97 new Message("Stack trace in separate lines:", false, null), 98 new Message("\tat Foo.java:3", false, new MockHyperlink("file:/src/Foo.java", "stack trace", 3, -1, -1, -1)), 99 new Message("\tat Bar.java:5", false, new MockHyperlink("file:/src/Bar.java", "stack trace", 5, -1, -1, -1)), 100 new Message("Stack trace in one big line:", true, null), 101 new Message("\tat Quux.java:11", true, new MockHyperlink("file:/src/Quux.java", "stack trace", 11, -1, -1, -1)), 102 new Message("\tat Baz.java:6", true, new MockHyperlink("file:/src/Baz.java", "stack trace", 6, -1, -1, -1)), 103 new Message("...and an unrelated message", true, null), 104 new Message(NbBundle.getMessage(StandardLogger.class, "FMT_finished_target_printed", new Integer (0), new Integer (1)), false, null), 105 }); 106 assertEquals("correct text printed", expectedMessages, session.messages); 107 } 108 109 public void testFileHyperlinks() throws Exception { 110 clearWorkDir(); 111 File top = new File (getWorkDir(), "top"); 112 FileUtil.createData(top); 113 File dir1 = new File (getWorkDir(), "dir1"); 114 File middle = new File (dir1, "middle"); 115 FileUtil.createData(middle); 116 File dir2 = new File (dir1, "dir2"); 117 File bottom = new File (dir2, "bottom"); 118 FileUtil.createData(bottom); 119 MockAntSession session = new MockAntSession(new AntLogger[] {new StandardLogger(1000L)}, AntEvent.LOG_INFO); 120 AntSession realSession = LoggerTrampoline.ANT_SESSION_CREATOR.makeAntSession(session); 121 session.sendBuildStarted(makeAntEvent(realSession, null, -1, null, null, null)); 122 session.sendTargetStarted(makeAntEvent(realSession, null, -1, null, "some-target", null)); 123 127 session.sendMessageLogged(makeAntEvent(realSession, top + ":1: some problem", AntEvent.LOG_WARN, null, null, null)); 128 session.sendMessageLogged(makeAntEvent(realSession, top.toURI() + ":1:10:2:5: same problem", AntEvent.LOG_WARN, null, null, null)); 129 session.sendMessageLogged(makeAntEvent(realSession, "make: Entering directory `" + dir1 + "'", AntEvent.LOG_INFO, null, null, null)); 130 session.sendMessageLogged(makeAntEvent(realSession, "middle:2:3: some other problem", AntEvent.LOG_WARN, null, null, null)); 131 session.sendMessageLogged(makeAntEvent(realSession, "../top: yet another problem", AntEvent.LOG_WARN, null, null, null)); 132 session.sendMessageLogged(makeAntEvent(realSession, "make: Entering directory `" + dir2 + "'", AntEvent.LOG_INFO, null, null, null)); 133 session.sendMessageLogged(makeAntEvent(realSession, "bottom: something new", AntEvent.LOG_WARN, null, null, null)); 134 session.sendMessageLogged(makeAntEvent(realSession, "\"../middle\", line 12: warning: statement is stupid", AntEvent.LOG_WARN, null, null, null)); 135 session.sendMessageLogged(makeAntEvent(realSession, "make: Leaving directory `" + dir2 + "'", AntEvent.LOG_INFO, null, null, null)); 136 session.sendMessageLogged(makeAntEvent(realSession, "middle: back here", AntEvent.LOG_WARN, null, null, null)); 137 session.sendMessageLogged(makeAntEvent(realSession, "make: Leaving directory `" + dir1 + "'", AntEvent.LOG_INFO, null, null, null)); 138 session.sendTargetFinished(makeAntEvent(realSession, null, -1, null, "some-target", null)); 139 session.sendBuildFinished(makeAntEvent(realSession, null, -1, null, null, null)); 140 List <Message> expectedMessages = Arrays.asList( 141 new Message(NbBundle.getMessage(StandardLogger.class, "MSG_target_started_printed", "some-target"), false, null), 142 146 new Message(top + ":1: some problem", true, new MockHyperlink(top.toURI().toString(), "some problem", 1, -1, -1, -1)), 147 new Message(top.toURI() + ":1:10:2:5: same problem", true, new MockHyperlink(top.toURI().toString(), "same problem", 1, 10, 2, 5)), 148 new Message("make: Entering directory `" + dir1 + "'", false, null), 149 new Message("middle:2:3: some other problem", true, new MockHyperlink(middle.toURI().toString(), "some other problem", 2, 3, -1, -1)), 150 new Message("../top: yet another problem", true, new MockHyperlink(top.toURI().toString(), "yet another problem", -1, -1, -1, -1)), 151 new Message("make: Entering directory `" + dir2 + "'", false, null), 152 new Message("bottom: something new", true, new MockHyperlink(bottom.toURI().toString(), "something new", -1, -1, -1, -1)), 153 new Message("\"../middle\", line 12: warning: statement is stupid", true, new MockHyperlink(middle.toURI().toString(), "warning: statement is stupid", 12, -1, -1, -1)), 154 new Message("make: Leaving directory `" + dir2 + "'", false, null), 155 new Message("middle: back here", true, new MockHyperlink(middle.toURI().toString(), "back here", -1, -1, -1, -1)), 156 new Message("make: Leaving directory `" + dir1 + "'", false, null), 157 new Message(NbBundle.getMessage(StandardLogger.class, "FMT_finished_target_printed", 0, 1), false, null)); 158 assertEquals("correct text printed", expectedMessages.toString(), session.messages.toString()); 159 160 } 161 162 166 169 private static AntEvent makeAntEvent(AntSession realSession, String message, int level, Throwable exc, String target, String task) { 170 return LoggerTrampoline.ANT_EVENT_CREATOR.makeAntEvent(new MockAntEvent(realSession, message, level, exc, target, task)); 171 } 172 173 181 private static final class MockAntSession implements LoggerTrampoline.AntSessionImpl { 182 183 private final AntLogger[] loggers; 184 private final int verbosity; 185 private final Map <AntLogger,Object > customData = new WeakHashMap <AntLogger,Object >(); 186 private final Set <Throwable > consumedExceptions = new WeakSet<Throwable >(); 187 public final List <Message> messages = new ArrayList <Message>(); 188 189 public MockAntSession(AntLogger[] loggers, int verbosity) { 190 this.loggers = loggers; 191 this.verbosity = verbosity; 192 } 193 194 public void sendMessageLogged(AntEvent event) { 195 for (AntLogger logger : loggers) { 196 int[] levels = logger.interestedInLogLevels(event.getSession()); 197 Arrays.sort(levels); 198 if (Arrays.binarySearch(levels, event.getLogLevel()) >= 0) { 199 logger.messageLogged(event); 200 } 201 } 202 } 203 204 public void sendBuildStarted(AntEvent event) { 205 for (AntLogger logger : loggers) { 206 logger.buildStarted(event); 207 } 208 } 209 210 public void sendBuildFinished(AntEvent event) { 211 for (AntLogger logger : loggers) { 212 logger.buildFinished(event); 213 } 214 } 215 216 public void sendBuildInitializationFailed(AntEvent event) { 217 for (AntLogger logger : loggers) { 218 logger.buildInitializationFailed(event); 219 } 220 } 221 222 public void sendTargetStarted(AntEvent event) { 223 for (AntLogger logger : loggers) { 224 logger.targetStarted(event); 225 } 226 } 227 228 public void sendTargetFinished(AntEvent event) { 229 for (AntLogger logger : loggers) { 230 logger.targetFinished(event); 231 } 232 } 233 234 public void sendTaskStarted(AntEvent event) { 235 for (AntLogger logger : loggers) { 236 logger.taskStarted(event); 237 } 238 } 239 240 public void sendTaskFinished(AntEvent event) { 241 for (AntLogger logger : loggers) { 242 logger.taskFinished(event); 243 } 244 } 245 246 public void deliverMessageLogged(AntEvent originalEvent, String message, int level) { 247 sendMessageLogged(makeAntEvent(originalEvent.getSession(), message, level, null, originalEvent.getTargetName(), originalEvent.getTaskName())); 248 } 249 250 public OutputListener createStandardHyperlink(URL file, String message, int line1, int column1, int line2, int column2) { 251 return new MockHyperlink(file.toExternalForm(), message, line1, column1, line2, column2); 252 } 253 254 public void println(String message, boolean err, OutputListener listener) { 255 messages.add(new Message(message, err, listener)); 256 } 257 258 public void putCustomData(AntLogger logger, Object data) { 259 customData.put(logger, data); 260 } 261 262 public boolean isExceptionConsumed(Throwable t) { if (consumedExceptions.contains(t)) { 264 return true; 265 } 266 Throwable nested = t.getCause(); 267 if (nested != null && isExceptionConsumed(nested)) { 268 consumedExceptions.add(t); 269 return true; 270 } 271 return false; 272 } 273 274 public void consumeException(Throwable t) throws IllegalStateException { if (isExceptionConsumed(t)) { 276 throw new IllegalStateException (); 277 } 278 consumedExceptions.add(t); 279 } 280 281 public Object getCustomData(AntLogger logger) { 282 return customData.get(logger); 283 } 284 285 public int getVerbosity() { 286 return verbosity; 287 } 288 289 public String [] getOriginatingTargets() { 290 return new String [] {"mock-target"}; 291 } 292 293 public File getOriginatingScript() { 294 return new File (System.getProperty("java.io.tmpdir"), "mock-script"); 295 } 296 297 public String getDisplayName() { 298 return "Mock Session"; 299 } 300 301 } 302 303 308 private static final class MockAntEvent implements LoggerTrampoline.AntEventImpl { 309 310 private final AntSession session; 311 private final String message; 312 private final int level; 313 private final Throwable exc; 314 private final String target; 315 private final String task; 316 private boolean consumed = false; 317 318 public MockAntEvent(AntSession session, String message, int level, Throwable exc, String target, String task) { 319 this.session = session; 320 this.message = message; 321 this.level = level; 322 this.exc = exc; 323 this.target = target; 324 this.task = task; 325 } 326 327 public String evaluate(String text) { 328 return null; 329 } 330 331 public String getProperty(String name) { 332 return null; 333 } 334 335 public boolean isConsumed() { 336 return consumed; 337 } 338 339 public void consume() throws IllegalStateException { 340 if (consumed) { 341 throw new IllegalStateException (); 342 } else { 343 consumed = true; 344 } 345 } 346 347 public Throwable getException() { 348 return exc; 349 } 350 351 public int getLine() { 352 return -1; 353 } 354 355 public int getLogLevel() { 356 return level; 357 } 358 359 public String getMessage() { 360 return message; 361 } 362 363 public Set <String > getPropertyNames() { 364 return Collections.emptySet(); 365 } 366 367 public File getScriptLocation() { 368 return null; 369 } 370 371 public AntSession getSession() { 372 return session; 373 } 374 375 public String getTargetName() { 376 return target; 377 } 378 379 public String getTaskName() { 380 return task; 381 } 382 383 public TaskStructure getTaskStructure() { 384 return null; 385 } 386 387 } 388 389 392 private static final class Message { 393 394 public final String message; 395 public final boolean err; 396 public final MockHyperlink hyperlink; 397 398 public Message(String message, boolean err, OutputListener listener) { 399 this.message = message; 400 this.err = err; 401 if (listener instanceof MockHyperlink) { 402 hyperlink = (MockHyperlink) listener; 403 } else { 404 hyperlink = null; 405 } 406 } 407 408 @Override 409 public boolean equals(Object o) { 410 if (o instanceof Message) { 411 Message m = (Message) o; 412 return m.message.equals(message) && m.err == err && Utilities.compareObjects(m.hyperlink, hyperlink); 413 } else { 414 return false; 415 } 416 } 417 418 @Override 419 public String toString() { 420 return "Message[" + message + "]" + (err ? "(err)" : "(out)") + (hyperlink != null ? "(" + hyperlink + ")" : ""); 421 } 422 423 } 424 425 428 private static final class MockHyperlink implements OutputListener { 429 430 public final String url; 431 public final String message; 432 public final int line1; 433 public final int column1; 434 public final int line2; 435 public final int column2; 436 437 public MockHyperlink(String url, String message, int line1, int column1, int line2, int column2) { 438 this.url = url; 439 this.message = message; 440 this.line1 = line1; 441 this.column1 = column1; 442 this.line2 = line2; 443 this.column2 = column2; 444 } 445 446 @Override 447 public boolean equals(Object o) { 448 if (o instanceof MockHyperlink) { 449 MockHyperlink h = (MockHyperlink) o; 450 return h.url.equals(url) && h.message.equals(message) && 451 h.line1 == line1 && h.column1 == column1 && h.line2 == line2 && h.column2 == column2; 452 } else { 453 return false; 454 } 455 } 456 457 @Override 458 public String toString() { 459 return "MockHyperlink[" + url + ":" + line1 + ":" + column1 + ":" + line2 + ":" + column2 + ":" + message + "]"; 460 } 461 462 public void outputLineSelected(OutputEvent ev) {} 463 464 public void outputLineCleared(OutputEvent ev) {} 465 466 public void outputLineAction(OutputEvent ev) {} 467 468 } 469 470 474 private static final class MockStackTraceLogger extends AntLogger { 475 476 private static final Pattern STACK_TRACE_LINE = Pattern.compile("\tat ([a-zA-Z]+\\.java):([0-9]+)"); 477 478 public MockStackTraceLogger() {} 479 480 @Override 481 public void messageLogged(AntEvent event) { 482 if (event.isConsumed()) { 483 return; 484 } 485 Matcher m = STACK_TRACE_LINE.matcher(event.getMessage()); 486 if (m.matches()) { 487 event.consume(); 488 String filename = m.group(1); 489 int line = Integer.parseInt(m.group(2)); 490 AntSession session = event.getSession(); 491 URL u; 492 try { 493 u = new URL ("file:/src/" + filename); 494 } catch (MalformedURLException e) { 495 throw new AssertionError (e); 496 } 497 session.println(event.getMessage(), 498 event.getLogLevel() <= AntEvent.LOG_WARN, 499 session.createStandardHyperlink(u, "stack trace", line, -1, -1, -1)); 500 } 501 } 502 503 @Override 504 public String [] interestedInTasks(AntSession session) { 505 return AntLogger.ALL_TASKS; 506 } 507 508 @Override 509 public String [] interestedInTargets(AntSession session) { 510 return AntLogger.ALL_TARGETS; 511 } 512 513 @Override 514 public boolean interestedInSession(AntSession session) { 515 return true; 516 } 517 518 @Override 519 public int[] interestedInLogLevels(AntSession session) { 520 return new int[] { 521 AntEvent.LOG_INFO, 522 AntEvent.LOG_WARN, 523 AntEvent.LOG_ERR, 524 }; 525 } 526 527 @Override 528 public boolean interestedInAllScripts(AntSession session) { 529 return true; 530 } 531 532 @Override 533 public boolean interestedInScript(File script, AntSession session) { 534 return true; 535 } 536 537 } 538 539 @Override 540 protected Level logLevel() { 541 return Level.FINE; 542 } 543 544 } 545 | Popular Tags |