Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

Ajc.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /* *******************************************************************
  2. * Copyright (c) 2004 IBM Corporation
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Adrian Colyer,
  11. * ******************************************************************/
  12. package org.aspectj.tools.ajc;
  13. import java.io.ByteArrayOutputStream;
  14. import java.io.File;
  15. import java.io.FilenameFilter;
  16. import java.io.IOException;
  17. import java.io.PrintStream;
  18. import java.util.ArrayList;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.StringTokenizer;
  22. import junit.framework.AssertionFailedError;
  23. import org.aspectj.asm.AsmManager;
  24. import org.aspectj.asm.IProgramElement;
  25. import org.aspectj.asm.IRelationship;
  26. import org.aspectj.asm.IRelationshipMap;
  27. import org.aspectj.asm.internal.Relationship;
  28. import org.aspectj.bridge.AbortException;
  29. import org.aspectj.bridge.ICommand;
  30. import org.aspectj.bridge.IMessage;
  31. import org.aspectj.bridge.IMessageHandler;
  32. import org.aspectj.bridge.MessageHandler;
  33. import org.aspectj.bridge.IMessage.Kind;
  34. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  35. import org.aspectj.util.FileUtil;
  36. /**
  37. * The Ajc class is intended for use as part of a unit-test suite, it drives the AspectJ compiler and lets you check the compilation
  38. * results. Compilations run in a sandbox that is created in C:\temp\ajcSandbox or /tmp/ajcSandbox depending on your platform.
  39. * <p>
  40. * The expected usage of Ajc is through the TestCase superclass, AjcTestCase, which provides helper methods that conveniently drive
  41. * the base functions exposed by this class.
  42. * </p>
  43. *
  44. * @see org.aspectj.tools.ajc.AjcTestCase
  45. */
  46. public class Ajc {
  47. private static final String SANDBOX_NAME = "ajcSandbox";
  48. // ALSO SEE ANTSPEC AND AJCTESTCASE
  49. private static final String TESTER_PATH = ".." + File.separator + "testing-client" + File.separator + "bin"
  50. + File.pathSeparator + ".." + File.separator + "runtime" + File.separator + "bin" + File.pathSeparator + ".."
  51. + File.separator + "aspectj5rt" + File.separator + "bin" + File.pathSeparator + ".." + File.separator + "lib"
  52. + File.separator + "junit" + File.separator + "junit.jar" + File.pathSeparator + "lib" + File.separator + "bcel"
  53. + File.separator + "bcel.jar" + File.pathSeparator + "lib" + File.separator + "bcel" + File.separator
  54. + "bcel-verifier.jar" +
  55. File.pathSeparator + ".." + File.separator + "bridge" + File.separator + "bin" + File.pathSeparator + ".."
  56. + File.separator + "loadtime" + File.separator + "bin" + File.pathSeparator
  57. + ".."
  58. + File.separator
  59. + "weaver"
  60. + File.separator
  61. + "bin"
  62. + File.pathSeparator
  63. + ".."
  64. + File.separator
  65. + "weaver5"
  66. + File.separator
  67. + "bin"
  68. + File.pathSeparator
  69. + ".."
  70. + File.separator
  71. + "org.aspectj.matcher"
  72. + File.separator
  73. + "bin"
  74. // When the build machine executes the tests, it is using code built into jars rather than code build into
  75. // bin directories. This means for the necessary types to be found we have to put these jars on the classpath:
  76. + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars" + File.separator + "bridge.jar"
  77. + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars" + File.separator
  78. + "org.aspectj.matcher.jar" + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars"
  79. + File.separator + "util.jar" + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars"
  80. + File.separator + "loadtime.jar" + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars"
  81. + File.separator + "weaver.jar" + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars"
  82. + File.separator + "weaver5.jar" + File.pathSeparator + ".." + File.separator + "aj-build" + File.separator + "jars"
  83. + File.separator + "asm.jar" + File.pathSeparator + ".." + File.separator + "lib" + File.separator + "test"
  84. + File.separator + "testing-client.jar"
  85. // hmmm, this next one should perhaps point to an aj-build jar...
  86. + File.pathSeparator + ".." + File.separator + "lib" + File.separator + "test" + File.separator + "aspectjrt.jar";
  87. private CompilationResult result;
  88. private File sandbox;
  89. private File baseDir;
  90. private final Main main;
  91. private String[] ajcArgs;
  92. private int incrementalStage = 10;
  93. private boolean shouldEmptySandbox = true;
  94. private final AjcCommandController controller;
  95. private static boolean verbose = System.getProperty("org.aspectj.tools.ajc.Ajc.verbose", "true").equals("true");
  96. /**
  97. * Constructs a new Ajc instance, with a new AspectJ compiler inside.
  98. */
  99. public Ajc() {
  100. main = new Main();
  101. controller = new AjcCommandController();
  102. main.setController(controller);
  103. }
  104. /**
  105. * By default, each call to <code>compile</code> creates a new sandbox (C:\temp\ajcSandbox\ajtTestxxx.tmp, or
  106. * /tmp/ajcSandbox/ajcTestxxx.tmp depending on your platform). To write a test that performs multiple (non-incremental)
  107. * compiles, building on the results of previous compilations, set 'should empty sandbox' to false after the first compile,
  108. * which will cause subsequent compiles in the test to use the same directory and contents.
  109. */
  110. public void setShouldEmptySandbox(boolean empty) {
  111. this.shouldEmptySandbox = empty;
  112. }
  113. /**
  114. * Call the compiler with the given arguments (args are exactly the same as you would pass to ajc on the command-line). The
  115. * results of the compile are returned in a <code>CompilationResult</code>, which provides for easy testing of results.
  116. * <p>
  117. * The compilation happens in a sandbox (C:\temp\ajcSandbox\ajTestxxx.tmp or /tmp/ajcSandbox/ajcTestxxx.tmp depending on
  118. * platform). Compiler arguments are adapted to the sandbox as follows.
  119. * </p>
  120. * <p>
  121. * For every file or directory listed in an argument (source file, or component of inpath, aspectpath, sourceroots,
  122. * classpath,...), if the file is specified using an absolute path then it is left unchanged, but if the file is specified using
  123. * a relative path, and a base directory (see setBaseDir) has been provided, then files/directories are copied from the base
  124. * directory to the sandbox, and the compiler arguments adjusted to reflect their new location.
  125. * </p>
  126. * <p>
  127. * For example, given a baseDir of "tests/pr12345" and a compile command: "ajc src/A.java src/B.java", the files in
  128. *
  129. * <pre>
  130. * tests/pr12345/
  131. * src/
  132. * A.java
  133. * B.java
  134. * </pre>
  135. *
  136. * are copied to:
  137. *
  138. * <pre>
  139. * ajcSandbox/ajcTestxxx.tmp/
  140. * src/
  141. * A.java
  142. * B.java
  143. * </pre>
  144. * <p>
  145. * If no classpath is specified (no -classpath in the arguments) the classpath will be set to include the sandbox directory,
  146. * testing-client/bin (for the Tester class), and runtime/bin (for the AspectJ runtime). If a classpath <i>is</i> specified,
  147. * then any relative directories in it will be made relative to the sandbox, and the testing-client and runtime bin directories
  148. * are also added.
  149. * </p>
  150. * <p>
  151. * If no output directory is specified (no -d in the arguments), the output directory is set to the sandbox. If a directory is
  152. * specified, and the path is relative, it will be made relative to the sandbox.
  153. * </p>
  154. * <ul>
  155. * </ul>
  156. * </p>
  157. *
  158. * @param args The compiler arguments.
  159. * @return a CompilationResult object with all the messages produced by the compiler, a description of the ajc command that was
  160. * issued, and the standard output and error of the compile (excluding messages which are provided separately)
  161. * @throws IOException
  162. * @see org.aspectj.tools.ajc.CompilationResult
  163. */
  164. public CompilationResult compile(String[] args) throws IOException {
  165. incrementalStage = 10;
  166. return compile(args, false);
  167. }
  168. private CompilationResult compile(String[] args, boolean isIncremental) throws IOException {
  169. result = null;
  170. ajcArgs = args;
  171. ByteArrayOutputStream out = new ByteArrayOutputStream();
  172. PrintStream pout = new PrintStream(out);
  173. ByteArrayOutputStream err = new ByteArrayOutputStream();
  174. PrintStream perr = new PrintStream(err);
  175. PrintStream systemOut = System.out;
  176. PrintStream systemErr = System.err;
  177. System.setOut(pout);
  178. System.setErr(perr);
  179. List<IMessage> fails = new ArrayList<IMessage>();
  180. List<IMessage> errors = new ArrayList<IMessage>();
  181. List<IMessage> warnings = new ArrayList<IMessage>();
  182. List<IMessage> infos = new ArrayList<IMessage>();
  183. List<IMessage> weaves = new ArrayList<IMessage>();
  184. try {
  185. if (!isIncremental && shouldEmptySandbox) {
  186. sandbox = createEmptySandbox();
  187. }
  188. args = adjustToSandbox(args, !isIncremental);
  189. MessageHandler holder = new MessageHandler();
  190. holder.setInterceptor(new AbortInterceptor());
  191. main.setHolder(holder);
  192. if (incrementalStage == 10 && hasSpecifiedIncremental(args)) {
  193. // important to sleep after preparing the sandbox on first incremental stage (see notes in pr90806)
  194. try {
  195. Thread.sleep(1000);
  196. } catch (Exception e) {
  197. }
  198. }
  199. if (isIncremental) {
  200. controller.doIncremental(holder);
  201. } else {
  202. main.runMain(args, false);
  203. }
  204. addMessagesTo(infos, holder.getMessages(IMessage.INFO, false));
  205. addMessagesTo(warnings, holder.getWarnings());
  206. addMessagesTo(errors, holder.getErrors());
  207. addMessagesTo(fails, holder.getMessages(IMessage.FAIL, true));
  208. addMessagesTo(weaves, holder.getMessages(IMessage.WEAVEINFO, false));
  209. String stdOut = new String(out.toByteArray());
  210. String stdErr = new String(err.toByteArray());
  211. result = new CompilationResult(args, stdOut, stdErr, infos, errors, warnings, fails, weaves);
  212. } finally {
  213. System.setOut(systemOut);
  214. System.setErr(systemErr);
  215. }
  216. if (verbose) {
  217. System.err.println(result.getStandardError());
  218. System.out.println(result.getStandardOutput());
  219. System.out.println(result);
  220. }
  221. return result;
  222. }
  223. private boolean hasSpecifiedIncremental(String[] args) {
  224. if (args == null)
  225. return false;
  226. for (int i = 0; i < args.length; i++) {
  227. if (args[i].equals("-incremental"))
  228. return true;
  229. }
  230. return false;
  231. }
  232. /**
  233. * After compiling for the first time with compile(), if the -incremental option was specified you can do as many subsequent
  234. * incremental compiles as you like by calling this method.
  235. * <p>
  236. * Throws an IllegalStateException if you try and call this method without first doing a compile that specified the -incremental
  237. * option.
  238. * </p>
  239. *
  240. * @return A CompilationResult giving the results of the most recent increment.
  241. * @throws IOException
  242. */
  243. public CompilationResult doIncrementalCompile() throws IOException {
  244. if ((ajcArgs == null) || !isIncremental(ajcArgs)) {
  245. throw new IllegalStateException(
  246. "Can't do incremental compile unless -incremental specified and first compile has taken place");
  247. }
  248. incrementalStage += 10;
  249. return compile(ajcArgs, true);
  250. }
  251. /**
  252. * Return the result of the last compile or incremental compile. This is the same as the return value from the compile() or
  253. * doIncrementalCompile() methods.
  254. */
  255. public CompilationResult getLastCompilationResult() {
  256. return result;
  257. }
  258. /**
  259. * Get the sandbox directory used for the compilation.
  260. */
  261. public File getSandboxDirectory() {
  262. if (sandbox == null) {
  263. sandbox = createEmptySandbox();
  264. }
  265. return sandbox;
  266. }
  267. /**
  268. * Set the base directory relative to which all relative paths specified in the arguments to a compile will be interpreted.
  269. */
  270. public void setBaseDir(File dir) {
  271. if ((dir != null) && !dir.isDirectory())
  272. throw new IllegalArgumentException(dir.getPath() + " is not a directory");
  273. baseDir = dir;
  274. }
  275. private void addMessagesTo(List<IMessage> aList, IMessage[] messages) {
  276. for (int i = 0; i < messages.length; i++) {
  277. aList.add(messages[i]);
  278. }
  279. }
  280. private boolean isIncremental(String[] args) {
  281. for (int i = 0; i < args.length; i++) {
  282. if (args[i].trim().equals("-incremental"))
  283. return true;
  284. }
  285. return false;
  286. }
  287. public static File createEmptySandbox() {
  288. File sandbox;
  289. String os = System.getProperty("os.name");
  290. File tempDir = null;
  291. // AMC - I did this rather than use the JDK default as I hate having to go look
  292. // in c:\documents and settings\......... for the results of a failed test.
  293. if (os.startsWith("Windows")) {
  294. tempDir = new File("N:\\temp");
  295. if (!tempDir.exists()) {
  296. tempDir = new File("C:\\temp");
  297. if (!tempDir.exists()) {
  298. tempDir.mkdir();
  299. }
  300. }
  301. } else {
  302. tempDir = new File("/tmp");
  303. }
  304. File sandboxRoot = new File(tempDir, SANDBOX_NAME);
  305. if (!sandboxRoot.exists()) {
  306. sandboxRoot.mkdir();
  307. }
  308. try {
  309. File workspace = new File(".." + File.separator);
  310. String workspaceName = workspace.getCanonicalPath();
  311. int index = workspaceName.lastIndexOf(File.separator);
  312. workspaceName = workspaceName.substring(index + 1);
  313. File workspaceRoot = new File(sandboxRoot, workspaceName);
  314. if (!workspaceRoot.exists()) {
  315. workspaceRoot.mkdir();
  316. }
  317. FileUtil.deleteContents(workspaceRoot);
  318. sandbox = File.createTempFile("ajcTest", ".tmp", workspaceRoot);
  319. sandbox.delete();
  320. sandbox.mkdir();
  321. } catch (IOException ioEx) {
  322. throw new AssertionFailedError("Unable to create sandbox directory for test");
  323. }
  324. return sandbox;
  325. }
  326. /**
  327. * Make every relative file name and dir be absolute under sandbox Add TESTER_PATH to classpath
  328. */
  329. private String[] adjustToSandbox(String[] args, boolean doCopy) throws IOException {
  330. String[] newArgs = new String[args.length];
  331. boolean hasClasspath = false;
  332. boolean hasOutdir = false;
  333. for (int i = 0; i < args.length; i++) {
  334. newArgs[i] = args[i];
  335. if (FileUtil.hasSourceSuffix(args[i])) {
  336. File f = new File(args[i]);
  337. // newArgs[i] = new File(baseDir,args[i]).getAbsolutePath(); // might be quicker?
  338. newArgs[i] = adjustFileOrDir(f, doCopy).getAbsolutePath();
  339. } else if (args[i].endsWith(".xml") && !args[i].startsWith("-")) {
  340. if (i > 0 && args[i - 1].equals("-outxmlfile")) {
  341. // dont adjust it
  342. } else {
  343. File f = new File(args[i]);
  344. // newArgs[i] = new File(baseDir,args[i]).getAbsolutePath(); // might be quicker?
  345. newArgs[i] = adjustFileOrDir(f, doCopy).getAbsolutePath();
  346. }
  347. } else {
  348. if ((args[i].equals("-aspectpath") || args[i].equals("-inpath") || args[i].equals("-injars")
  349. || args[i].equals("-outjar") || args[i].equals("-classpath") || args[i].equals("-sourceroots")
  350. || args[i].equals("-Xlintfile") || args[i].equals("-extdirs") || args[i].equals("-d"))
  351. && args.length > (i + 1)) {
  352. newArgs[i] = args[i];
  353. StringBuffer buff = new StringBuffer();
  354. boolean copyThisTime = doCopy;
  355. if (args[i].equals("-d")) {
  356. copyThisTime = false;
  357. hasOutdir = true;
  358. }
  359. StringTokenizer strTok = new StringTokenizer(args[++i], File.pathSeparator);
  360. while (strTok.hasMoreTokens()) {
  361. File f = new File(strTok.nextToken());
  362. buff.append(adjustFileOrDir(f, copyThisTime).getAbsolutePath());
  363. if (strTok.hasMoreTokens())
  364. buff.append(File.pathSeparator);
  365. }
  366. newArgs[i] = buff.toString();
  367. if (args[i - 1].equals("-classpath")) {
  368. hasClasspath = true;
  369. newArgs[i] = newArgs[i] + File.pathSeparator + TESTER_PATH + File.pathSeparator
  370. + getSandboxDirectory().getAbsolutePath();
  371. }
  372. } else {
  373. // could be resource file
  374. File f = new File(args[i]);
  375. if (f.exists()) {
  376. newArgs[i] = adjustFileOrDir(f, doCopy).getAbsolutePath();
  377. }
  378. }
  379. }
  380. }
  381. if (!hasClasspath) {
  382. String[] oldArgs = newArgs;
  383. newArgs = new String[oldArgs.length + 2];
  384. System.arraycopy(oldArgs, 0, newArgs, 0, oldArgs.length);
  385. newArgs[oldArgs.length] = "-classpath";
  386. newArgs[oldArgs.length + 1] = TESTER_PATH + File.pathSeparator + getSandboxDirectory().getAbsolutePath();
  387. }
  388. if (!hasOutdir) {
  389. String[] oldArgs = newArgs;
  390. newArgs = new String[oldArgs.length + 2];
  391. System.arraycopy(oldArgs, 0, newArgs, 0, oldArgs.length);
  392. newArgs[oldArgs.length] = "-d";
  393. newArgs[oldArgs.length + 1] = getSandboxDirectory().getPath();
  394. }
  395. return newArgs;
  396. }
  397. private File adjustFileOrDir(File from, boolean doCopy) throws IOException {
  398. File to = from;
  399. File ret = from;
  400. if (!from.isAbsolute()) {
  401. ret = new File(sandbox, from.getPath());
  402. File fromParent = from.getParentFile();
  403. String relativeToPath = (fromParent != null) ? (fromParent.getPath() + File.separator) : "";
  404. if (baseDir != null) {
  405. from = new File(baseDir, from.getPath());
  406. }
  407. if (!from.exists())
  408. return ret;
  409. if (doCopy) {
  410. // harness requires that any files with the same name, and a different extension,
  411. // get copied too (e.g. .out, .err, .event files)
  412. if (from.isFile()) {
  413. final String prefix = from.getName().substring(0, from.getName().lastIndexOf('.'));
  414. String[] toCopy = from.getParentFile().list(new FilenameFilter() {
  415. public boolean accept(File dir, String name) {
  416. if (name.indexOf('.') == -1)
  417. return false;
  418. String toMatch = name.substring(0, name.lastIndexOf('.'));
  419. return (toMatch.equals(prefix));
  420. }
  421. });
  422. for (int i = 0; i < toCopy.length; i++) {
  423. String toPath = relativeToPath + toCopy[i];
  424. to = new File(sandbox, toPath);
  425. FileUtil.copyFile(new File(from.getParentFile(), toCopy[i]), to);
  426. }
  427. } else {
  428. FileUtil.copyFile(from, ret);
  429. }
  430. }
  431. }
  432. return ret;
  433. }
  434. public static void dumpAJDEStructureModel(AsmManager model, String prefix) {
  435. dumpAJDEStructureModel(model, prefix, false);
  436. }
  437. public static void dumpAJDEStructureModel(AsmManager model, String prefix, boolean useHandles) {
  438. System.out.println("======================================");//$NON-NLS-1$
  439. System.out.println("start of AJDE structure model:" + prefix); //$NON-NLS-1$
  440. IRelationshipMap asmRelMap = model.getRelationshipMap();
  441. for (Iterator<String> iter = asmRelMap.getEntries().iterator(); iter.hasNext();) {
  442. String sourceOfRelationship = iter.next();
  443. System.err.println("Examining source relationship handle: " + sourceOfRelationship);
  444. List<IRelationship> relationships = null;
  445. if (useHandles) {
  446. relationships = asmRelMap.get(sourceOfRelationship);
  447. } else {
  448. IProgramElement ipe = model.getHierarchy().findElementForHandle(sourceOfRelationship);
  449. relationships = asmRelMap.get(ipe);
  450. }
  451. if (relationships != null) {
  452. for (Iterator<IRelationship> iterator = relationships.iterator(); iterator.hasNext();) {
  453. Relationship rel = (Relationship) iterator.next();
  454. List<String> targets = rel.getTargets();
  455. for (Iterator<String> iterator2 = targets.iterator(); iterator2.hasNext();) {
  456. String t = (String) iterator2.next();
  457. IProgramElement link = model.getHierarchy().findElementForHandle(t);
  458. System.out.println(""); //$NON-NLS-1$
  459. System.out.println(" sourceOfRelationship " + sourceOfRelationship); //$NON-NLS-1$
  460. System.out.println(" relationship " + rel.getName()); //$NON-NLS-1$
  461. System.out.println(" target " + link.getName()); //$NON-NLS-1$
  462. }
  463. }
  464. }
  465. }
  466. System.out.println("End of AJDE structure model"); //$NON-NLS-1$
  467. System.out.println("======================================");//$NON-NLS-1$
  468. }
  469. }
  470. /*
  471. * So that we can drive incremental compilation easily from a unit test.
  472. */
  473. class AjcCommandController extends Main.CommandController {
  474. private ICommand command;
  475. /*
  476. * (non-Javadoc)
  477. *
  478. * @see org.aspectj.tools.ajc.Main.CommandController#doRepeatCommand()
  479. */
  480. boolean doRepeatCommand(ICommand command) {
  481. this.command = command;
  482. return false; // ensure that control returns to caller
  483. }
  484. /*
  485. * (non-Javadoc)
  486. *
  487. * @see org.aspectj.tools.ajc.Main.CommandController#running()
  488. */
  489. public boolean running() {
  490. return false; // so that we can come back for more...
  491. }
  492. public void doIncremental(IMessageHandler handler) {
  493. if (command == null)
  494. throw new IllegalArgumentException("Can't repeat command until it has executed at least once!");
  495. command.repeatCommand(handler);
  496. }
  497. }
  498. class AbortInterceptor implements IMessageHandler {
  499. public boolean handleMessage(IMessage message) throws AbortException {
  500. if (message.getKind() == IMessage.ABORT) {
  501. System.err.println("***** Abort Message Received ******");
  502. System.err.println(CompilationAndWeavingContext.getCurrentContext());
  503. System.err.println(message.getMessage());
  504. if (message.getThrown() != null) {
  505. System.err.println("caused by " + message.getThrown().toString());
  506. }
  507. } // allow message to accumulate...
  508. return false;
  509. }
  510. public boolean isIgnoring(Kind kind) {
  511. if (kind != IMessage.ABORT)
  512. return true;
  513. return false;
  514. }
  515. public void dontIgnore(Kind kind) {
  516. }
  517. public void ignore(Kind kind) {
  518. }
  519. }