You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AjdtCommand.java 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  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. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.ajdt.ajc;
  13. import org.aspectj.ajdt.internal.core.builder.*;
  14. import org.aspectj.bridge.*;
  15. import org.aspectj.weaver.Dump;
  16. import org.aspectj.org.eclipse.jdt.internal.core.builder.MissingSourceFileException;
  17. /**
  18. * ICommand adapter for the AspectJ compiler.
  19. * Not thread-safe.
  20. */
  21. public class AjdtCommand implements ICommand {
  22. /** Message String for any AbortException thrown from ICommand API's */
  23. public static final String ABORT_MESSAGE = "ABORT";
  24. // private boolean canRepeatCommand = true;
  25. AjBuildManager buildManager = null;
  26. String[] savedArgs = null;
  27. /**
  28. * Run AspectJ compiler, wrapping any exceptions thrown as
  29. * ABORT messages (containing ABORT_MESSAGE String).
  30. * @param args the String[] for the compiler
  31. * @param handler the IMessageHandler for any messages
  32. * @see org.aspectj.bridge.ICommand#runCommand(String[], IMessageHandler)
  33. * @return false if handler has errors or the command failed
  34. */
  35. public boolean runCommand(String[] args, IMessageHandler handler) {
  36. buildManager = new AjBuildManager(handler);
  37. savedArgs = new String[args.length];
  38. System.arraycopy(args, 0, savedArgs, 0, savedArgs.length);
  39. return doCommand(handler, false);
  40. }
  41. /**
  42. * Run AspectJ compiler, wrapping any exceptions thrown as
  43. * ABORT messages (containing ABORT_MESSAGE String).
  44. * @param handler the IMessageHandler for any messages
  45. * @see org.aspectj.bridge.ICommand#repeatCommand(IMessageHandler)
  46. * @return false if handler has errors or the command failed
  47. */
  48. public boolean repeatCommand(IMessageHandler handler) {
  49. if (null == buildManager) {
  50. MessageUtil.abort(handler, "repeatCommand called before runCommand");
  51. return false;
  52. }
  53. return doCommand(handler, true);
  54. }
  55. /**
  56. * Delegate of both runCommand and repeatCommand.
  57. * This invokes the argument parser each time
  58. * (even when repeating).
  59. * If the parser detects errors, this signals an
  60. * abort with the usage message and returns false.
  61. * @param handler the IMessageHandler sink for any messages
  62. * @param repeat if true, do incremental build, else do batch build
  63. * @return false if handler has any errors or command failed
  64. */
  65. protected boolean doCommand(IMessageHandler handler, boolean repeat) {
  66. try {
  67. if (handler instanceof IMessageHolder) {
  68. Dump.saveMessageHolder((IMessageHolder) handler);
  69. }
  70. // buildManager.setMessageHandler(handler);
  71. CountingMessageHandler counter = new CountingMessageHandler(handler);
  72. if (counter.hasErrors()) {
  73. return false;
  74. }
  75. // regenerate configuration b/c world might have changed (?)
  76. AjBuildConfig config = genBuildConfig(savedArgs, counter);
  77. if (!config.shouldProceed()) {
  78. return true;
  79. }
  80. if (!config.hasSources()) {
  81. MessageUtil.error(counter, "no sources specified");
  82. }
  83. if (counter.hasErrors()) {
  84. // Do *not* print usage for config errors (just like ECJ does it). Otherwise the user would have to
  85. // scroll up several screens in order to actually see the error messages.
  86. // String usage = BuildArgParser.getUsage();
  87. // MessageUtil.abort(handler, usage);
  88. return false;
  89. }
  90. //System.err.println("errs: " + counter.hasErrors());
  91. boolean result = ((repeat
  92. ? buildManager.incrementalBuild(config, handler)
  93. : buildManager.batchBuild(config, handler))
  94. && !counter.hasErrors());
  95. Dump.dumpOnExit();
  96. return result;
  97. } catch (AbortException ae) {
  98. if (ae.isSilent()) {
  99. throw ae;
  100. } else {
  101. MessageUtil.abort(handler, ABORT_MESSAGE, ae);
  102. }
  103. } catch (MissingSourceFileException t) {
  104. MessageUtil.error(handler, t.getMessage());
  105. } catch (Throwable t) {
  106. MessageUtil.abort(handler, ABORT_MESSAGE, t);
  107. Dump.dumpWithException(t);
  108. }
  109. return false;
  110. }
  111. /**
  112. * This creates a build configuration for the arguments.
  113. * Errors reported to the handler:
  114. * <ol>
  115. * <li>The parser detects some directly</li>
  116. * <li>The parser grabs some from the error stream
  117. * emitted by its superclass</li>
  118. * <li>The configuration has a self-test</li>
  119. * </ol>
  120. * In the latter two cases, the errors do not have
  121. * a source location context for locating the error.
  122. */
  123. public static AjBuildConfig genBuildConfig(String[] args, CountingMessageHandler handler) {
  124. BuildArgParser parser = new BuildArgParser(handler);
  125. AjBuildConfig config = parser.genBuildConfig(args);
  126. ISourceLocation location = null;
  127. if (config.getConfigFile() != null) {
  128. location = new SourceLocation(config.getConfigFile(), 0);
  129. }
  130. String message = parser.getOtherMessages(true);
  131. if (null != message) {
  132. IMessage.Kind kind = inferKind(message);
  133. IMessage m = new Message(message, kind, null, location);
  134. handler.handleMessage(m);
  135. }
  136. // message = config.configErrors();
  137. // if (null != message) {
  138. // IMessage.Kind kind = inferKind(message);
  139. // IMessage m = new Message(message, kind, null, location);
  140. // handler.handleMessage(m);
  141. // }
  142. return config;
  143. }
  144. /**
  145. * Heuristically infer the type of output message logged by the AspectJ compiler. This is a simple keyword matcher
  146. * looking for substrings like "[error]", "[warning]", "AspectJ-specific options:", "AspectJ-specific non-standard
  147. * options:"
  148. *
  149. * @param message AspectJ compiler message
  150. * @return inferred message kind, either of ERROR, WARNING, USAGE, INFO
  151. */
  152. protected static IMessage.Kind inferKind(String message) { // XXX dubious
  153. if (message.contains("[error]")) {
  154. return IMessage.ERROR;
  155. } else if (message.contains("[warning]")) {
  156. return IMessage.WARNING;
  157. } else if (message.contains("AspectJ-specific options:") || message.contains("AspectJ-specific non-standard options:")) {
  158. return IMessage.USAGE;
  159. } else {
  160. return IMessage.INFO;
  161. }
  162. }
  163. }