Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

AjdeCoreBuildManager.java 15KB

17 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
14 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
12 лет назад
14 лет назад
15 лет назад
14 лет назад
15 лет назад
14 лет назад
15 лет назад
17 лет назад
12 лет назад
17 лет назад
14 лет назад
15 лет назад
14 лет назад
15 лет назад
17 лет назад
15 лет назад
9 лет назад
14 лет назад
15 лет назад
14 лет назад
15 лет назад
14 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
12 лет назад
15 лет назад
15 лет назад
17 лет назад
12 лет назад
14 лет назад
14 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
12 лет назад
15 лет назад
12 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
9 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
15 лет назад
12 лет назад
15 лет назад
12 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
12 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
12 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
17 лет назад
15 лет назад
15 лет назад
15 лет назад
17 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /********************************************************************
  2. * Copyright (c) 2007 Contributors. All rights reserved.
  3. * This program and the accompanying materials are made available
  4. * under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution and is available at
  6. * http://eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: IBM Corporation - initial API and implementation
  9. * Helen Hawkins - initial version (bug 148190)
  10. *******************************************************************/
  11. package org.aspectj.ajde.core.internal;
  12. import java.io.File;
  13. import java.util.ArrayList;
  14. import java.util.Collection;
  15. import java.util.Iterator;
  16. import java.util.List;
  17. import java.util.Map;
  18. import java.util.StringTokenizer;
  19. import org.aspectj.ajde.core.AjCompiler;
  20. import org.aspectj.ajde.core.ICompilerConfiguration;
  21. import org.aspectj.ajde.core.IOutputLocationManager;
  22. import org.aspectj.ajdt.ajc.AjdtCommand;
  23. import org.aspectj.ajdt.ajc.BuildArgParser;
  24. import org.aspectj.ajdt.ajc.ConfigParser;
  25. import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
  26. import org.aspectj.ajdt.internal.core.builder.AjBuildManager;
  27. import org.aspectj.ajdt.internal.core.builder.AjState;
  28. import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager;
  29. import org.aspectj.asm.AsmManager;
  30. import org.aspectj.bridge.AbortException;
  31. import org.aspectj.bridge.CountingMessageHandler;
  32. import org.aspectj.bridge.IMessage;
  33. import org.aspectj.bridge.IMessageHandler;
  34. import org.aspectj.bridge.ISourceLocation;
  35. import org.aspectj.bridge.Message;
  36. import org.aspectj.bridge.SourceLocation;
  37. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  38. import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
  39. import org.aspectj.util.LangUtil;
  40. /**
  41. * Build Manager which drives the build for a given AjCompiler. Tools call build on the AjCompiler which drives this.
  42. */
  43. public class AjdeCoreBuildManager {
  44. private final AjCompiler compiler;
  45. private AjdeCoreBuildNotifierAdapter buildEventNotifier = null;
  46. private final AjBuildManager ajBuildManager;
  47. private final IMessageHandler msgHandlerAdapter;
  48. public AjdeCoreBuildManager(AjCompiler compiler) {
  49. this.compiler = compiler;
  50. this.msgHandlerAdapter = new AjdeCoreMessageHandlerAdapter(compiler.getMessageHandler());
  51. this.ajBuildManager = new AjBuildManager(msgHandlerAdapter);
  52. this.ajBuildManager.environmentSupportsIncrementalCompilation(true);
  53. // this static information needs to be set to ensure
  54. // incremental compilation works correctly
  55. IncrementalStateManager.recordIncrementalStates = true;
  56. IncrementalStateManager.debugIncrementalStates = false;
  57. AsmManager.attemptIncrementalModelRepairs = true;
  58. }
  59. public AjBuildManager getAjBuildManager() {
  60. return ajBuildManager;
  61. }
  62. /**
  63. * Execute a full or incremental build
  64. *
  65. * @param fullBuild true if requesting a full build, false if requesting to try an incremental build
  66. */
  67. public void performBuild(boolean fullBuild) {
  68. // If an incremental build is requested, check that we can
  69. if (!fullBuild) {
  70. AjState existingState = IncrementalStateManager.retrieveStateFor(compiler.getId());
  71. if (existingState == null || existingState.getBuildConfig() == null
  72. || ajBuildManager.getState().getBuildConfig() == null) {
  73. // No existing state so we must do a full build
  74. fullBuild = true;
  75. } else {
  76. AsmManager.setLastActiveStructureModel(existingState.getStructureModel());
  77. // AsmManager.getDefault().setRelationshipMap(existingState.getRelationshipMap());
  78. // AsmManager.getDefault().setHierarchy(existingState.getStructureModel());
  79. }
  80. }
  81. try {
  82. reportProgressBegin();
  83. // record the options passed to the compiler if INFO turned on
  84. if (!msgHandlerAdapter.isIgnoring(IMessage.INFO)) {
  85. handleMessage(new Message(getFormattedOptionsString(), IMessage.INFO, null, null));
  86. }
  87. CompilationAndWeavingContext.reset();
  88. if (fullBuild) { // FULL BUILD
  89. AjBuildConfig buildConfig = generateAjBuildConfig();
  90. if (buildConfig == null) {
  91. return;
  92. }
  93. ajBuildManager.batchBuild(buildConfig, msgHandlerAdapter);
  94. } else { // INCREMENTAL BUILD
  95. // Only rebuild the config object if the configuration has changed
  96. AjBuildConfig buildConfig = null;
  97. ICompilerConfiguration compilerConfig = compiler.getCompilerConfiguration();
  98. int changes = compilerConfig.getConfigurationChanges();
  99. if (changes != ICompilerConfiguration.NO_CHANGES) {
  100. // What configuration changes can we cope with? And besides just repairing the config object
  101. // what does it mean for any existing state that we have?
  102. buildConfig = generateAjBuildConfig();
  103. if (buildConfig == null) {
  104. return;
  105. }
  106. } else {
  107. buildConfig = ajBuildManager.getState().getBuildConfig();
  108. buildConfig.setChanged(changes); // pass it through for the state to use it when making decisions
  109. buildConfig.setModifiedFiles(compilerConfig.getProjectSourceFilesChanged());
  110. buildConfig.setClasspathElementsWithModifiedContents(compilerConfig.getClasspathElementsWithModifiedContents());
  111. compilerConfig.configurationRead();
  112. }
  113. ajBuildManager.incrementalBuild(buildConfig, msgHandlerAdapter);
  114. }
  115. IncrementalStateManager.recordSuccessfulBuild(compiler.getId(), ajBuildManager.getState());
  116. } catch (ConfigParser.ParseException pe) {
  117. handleMessage(new Message("Config file entry invalid, file: " + pe.getFile().getPath() + ", line number: "
  118. + pe.getLine(), IMessage.WARNING, null, null));
  119. } catch (AbortException e) {
  120. final IMessage message = e.getIMessage();
  121. if (message == null) {
  122. handleMessage(new Message(LangUtil.unqualifiedClassName(e) + " thrown: " + e.getMessage(), IMessage.ERROR, e, null));
  123. } else {
  124. handleMessage(new Message(message.getMessage() + "\n" + CompilationAndWeavingContext.getCurrentContext(),
  125. IMessage.ERROR, e, null));
  126. }
  127. } catch (Throwable t) {
  128. handleMessage(new Message("Compile error: " + LangUtil.unqualifiedClassName(t) + " thrown: " + "" + t.getMessage(),
  129. IMessage.ABORT, t, null));
  130. } finally {
  131. compiler.getBuildProgressMonitor().finish(ajBuildManager.wasFullBuild());
  132. }
  133. }
  134. /**
  135. * Starts the various notifiers which are interested in the build progress
  136. */
  137. private void reportProgressBegin() {
  138. compiler.getBuildProgressMonitor().begin();
  139. buildEventNotifier = new AjdeCoreBuildNotifierAdapter(compiler.getBuildProgressMonitor());
  140. ajBuildManager.setProgressListener(buildEventNotifier);
  141. }
  142. private String getFormattedOptionsString() {
  143. ICompilerConfiguration compilerConfig = compiler.getCompilerConfiguration();
  144. return "Building with settings: " + "\n-> output paths: "
  145. + formatCollection(compilerConfig.getOutputLocationManager().getAllOutputLocations()) + "\n-> classpath: "
  146. + compilerConfig.getClasspath() + "\n-> -inpath " + formatCollection(compilerConfig.getInpath()) + "\n-> -outjar "
  147. + formatOptionalString(compilerConfig.getOutJar()) + "\n-> -aspectpath "
  148. + formatCollection(compilerConfig.getAspectPath()) + "\n-> -sourcePathResources "
  149. + formatMap(compilerConfig.getSourcePathResources()) + "\n-> non-standard options: "
  150. + compilerConfig.getNonStandardOptions() + "\n-> javaoptions:" + formatMap(compilerConfig.getJavaOptionsMap());
  151. }
  152. private String formatCollection(Collection<?> options) {
  153. if (options == null) {
  154. return "<default>";
  155. }
  156. if (options.isEmpty()) {
  157. return "none";
  158. }
  159. StringBuffer formattedOptions = new StringBuffer();
  160. Iterator<?> it = options.iterator();
  161. while (it.hasNext()) {
  162. String o = it.next().toString();
  163. if (formattedOptions.length() > 0) {
  164. formattedOptions.append(", ");
  165. }
  166. formattedOptions.append(o);
  167. }
  168. return formattedOptions.toString();
  169. }
  170. private String formatMap(Map<String,? extends Object> options) {
  171. if (options == null) {
  172. return "<default>";
  173. }
  174. if (options.isEmpty()) {
  175. return "none";
  176. }
  177. return options.toString();
  178. }
  179. private String formatOptionalString(String s) {
  180. if (s == null) {
  181. return "";
  182. } else {
  183. return s;
  184. }
  185. }
  186. /**
  187. * Generate a new AjBuildConfig from the compiler configuration associated with this AjdeCoreBuildManager or from a
  188. * configuration file.
  189. *
  190. * @return null if invalid configuration, corresponding AjBuildConfig otherwise
  191. */
  192. public AjBuildConfig generateAjBuildConfig() {
  193. File configFile = new File(compiler.getId());
  194. ICompilerConfiguration compilerConfig = compiler.getCompilerConfiguration();
  195. CountingMessageHandler handler = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
  196. String[] args = null;
  197. // Retrieve the set of files from either an arg file (@filename) or the compiler configuration
  198. if (configFile.exists() && configFile.isFile()) {
  199. args = new String[] { "@" + configFile.getAbsolutePath() };
  200. } else {
  201. List<String> l = compilerConfig.getProjectSourceFiles();
  202. if (l == null) {
  203. return null;
  204. }
  205. // If the processor options are specified build the command line options for the JDT compiler to see
  206. String processor = compilerConfig.getProcessor();
  207. if (processor != null && processor.length() != 0) {
  208. l.add("-processor");
  209. l.add(processor);
  210. }
  211. String processorPath = compilerConfig.getProcessorPath();
  212. if (processorPath != null && processorPath.length() != 0) {
  213. l.add("-processorpath");
  214. l.add(processorPath);
  215. }
  216. List<String> xmlfiles = compilerConfig.getProjectXmlConfigFiles();
  217. if (xmlfiles != null && !xmlfiles.isEmpty()) {
  218. args = new String[l.size() + xmlfiles.size() + 1];
  219. // TODO speedup
  220. int p = 0;
  221. for (int i = 0; i < l.size(); i++) {
  222. args[p++] = (String) l.get(i);
  223. }
  224. for (int i = 0; i < xmlfiles.size(); i++) {
  225. args[p++] = (String) xmlfiles.get(i);
  226. }
  227. args[p++] = "-xmlConfigured";
  228. } else {
  229. args = (String[]) l.toArray(new String[l.size()]);
  230. }
  231. }
  232. BuildArgParser parser = new BuildArgParser(handler);
  233. AjBuildConfig config = new AjBuildConfig(parser);
  234. parser.populateBuildConfig(config, args, false, configFile);
  235. // Process the CLASSPATH
  236. String propcp = compilerConfig.getClasspath();
  237. if (propcp != null && propcp.length() != 0) {
  238. StringTokenizer st = new StringTokenizer(propcp, File.pathSeparator);
  239. List<String> configClasspath = config.getClasspath();
  240. ArrayList<String> toAdd = new ArrayList<String>();
  241. while (st.hasMoreTokens()) {
  242. String entry = st.nextToken();
  243. if (!configClasspath.contains(entry)) {
  244. toAdd.add(entry);
  245. }
  246. }
  247. if (0 < toAdd.size()) {
  248. ArrayList<String> both = new ArrayList<String>(configClasspath.size() + toAdd.size());
  249. both.addAll(configClasspath);
  250. both.addAll(toAdd);
  251. config.setClasspath(both);
  252. }
  253. }
  254. // Process the OUTJAR
  255. if (config.getOutputJar() == null) {
  256. String outJar = compilerConfig.getOutJar();
  257. if (outJar != null && outJar.length() != 0) {
  258. config.setOutputJar(new File(outJar));
  259. }
  260. }
  261. // Process the OUTPUT LOCATION MANAGER
  262. IOutputLocationManager outputLocationManager = compilerConfig.getOutputLocationManager();
  263. if (config.getCompilationResultDestinationManager() == null && outputLocationManager != null) {
  264. config.setCompilationResultDestinationManager(new OutputLocationAdapter(outputLocationManager));
  265. }
  266. // Process the INPATH
  267. mergeInto(config.getInpath(), compilerConfig.getInpath());
  268. // bug 168840 - calling 'setInPath(..)' creates BinarySourceFiles which
  269. // are used to see if there have been changes in classes on the inpath
  270. if (config.getInpath() != null) {
  271. config.setInPath(config.getInpath());
  272. }
  273. // Process the SOURCE PATH RESOURCES
  274. config.setSourcePathResources(compilerConfig.getSourcePathResources());
  275. // Process the ASPECTPATH
  276. mergeInto(config.getAspectpath(), compilerConfig.getAspectPath());
  277. // Process the JAVA OPTIONS MAP
  278. Map<String,String> jom = compilerConfig.getJavaOptionsMap();
  279. if (jom != null) {
  280. String version = (String) jom.get(CompilerOptions.OPTION_Compliance);
  281. if (version != null && !version.equals(CompilerOptions.VERSION_1_4)) {
  282. config.setBehaveInJava5Way(true);
  283. }
  284. config.getOptions().set(jom);
  285. }
  286. // Process the NON-STANDARD COMPILER OPTIONS
  287. configureNonStandardOptions(config);
  288. compilerConfig.configurationRead();
  289. ISourceLocation location = null;
  290. if (config.getConfigFile() != null) {
  291. location = new SourceLocation(config.getConfigFile(), 0);
  292. }
  293. String message = parser.getOtherMessages(true);
  294. if (null != message) {
  295. IMessage m = new Message(message, IMessage.ERROR, null, location);
  296. handler.handleMessage(m);
  297. }
  298. // always force model generation in AJDE
  299. config.setGenerateModelMode(true);
  300. // always be in incremental mode in AJDE
  301. config.setIncrementalMode(true);
  302. // always force proceedOnError in AJDE
  303. config.setProceedOnError(true);
  304. config.setProjectEncoding(compilerConfig.getProjectEncoding());
  305. config.setProcessor(compilerConfig.getProcessor());
  306. config.setProcessorPath(compilerConfig.getProcessorPath());
  307. return config;
  308. }
  309. private <T> void mergeInto(Collection<T> target, Collection<T> source) {
  310. if ((null == target) || (null == source)) {
  311. return;
  312. }
  313. for (T next : source) {
  314. if (!target.contains(next)) {
  315. target.add(next);
  316. }
  317. }
  318. }
  319. /**
  320. * Helper method for configure build options. This reads all command-line options specified in the non-standard options text
  321. * entry and sets any corresponding unset values in config.
  322. */
  323. private void configureNonStandardOptions(AjBuildConfig config) {
  324. String nonStdOptions = compiler.getCompilerConfiguration().getNonStandardOptions();
  325. if (LangUtil.isEmpty(nonStdOptions)) {
  326. return;
  327. }
  328. // Break a string into a string array of non-standard options.
  329. // Allows for one option to include a ' '. i.e. assuming it has been quoted, it
  330. // won't accidentally get treated as a pair of options (can be needed for xlint props file option)
  331. List<String> tokens = new ArrayList<String>();
  332. int ind = nonStdOptions.indexOf('\"');
  333. int ind2 = nonStdOptions.indexOf('\"', ind + 1);
  334. if ((ind > -1) && (ind2 > -1)) { // dont tokenize within double quotes
  335. String pre = nonStdOptions.substring(0, ind);
  336. String quoted = nonStdOptions.substring(ind + 1, ind2);
  337. String post = nonStdOptions.substring(ind2 + 1, nonStdOptions.length());
  338. tokens.addAll(tokenizeString(pre));
  339. tokens.add(quoted);
  340. tokens.addAll(tokenizeString(post));
  341. } else {
  342. tokens.addAll(tokenizeString(nonStdOptions));
  343. }
  344. String[] args = (String[]) tokens.toArray(new String[] {});
  345. // set the non-standard options in an alternate build config
  346. // (we don't want to lose the settings we already have)
  347. CountingMessageHandler counter = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
  348. AjBuildConfig altConfig = AjdtCommand.genBuildConfig(args, counter);
  349. if (counter.hasErrors()) {
  350. return;
  351. }
  352. // copy globals where local is not set
  353. config.installGlobals(altConfig);
  354. }
  355. /** Local helper method for splitting option strings */
  356. private List<String> tokenizeString(String str) {
  357. List<String> tokens = new ArrayList<String>();
  358. StringTokenizer tok = new StringTokenizer(str);
  359. while (tok.hasMoreTokens()) {
  360. tokens.add(tok.nextToken());
  361. }
  362. return tokens;
  363. }
  364. /**
  365. * Helper method to ask the messagehandler to handle the given message
  366. */
  367. private void handleMessage(Message msg) {
  368. compiler.getMessageHandler().handleMessage(msg);
  369. }
  370. public void setCustomMungerFactory(Object o) {
  371. ajBuildManager.setCustomMungerFactory(o);
  372. }
  373. public Object getCustomMungerFactory() {
  374. return ajBuildManager.getCustomMungerFactory();
  375. }
  376. public void cleanupEnvironment() {
  377. ajBuildManager.cleanupEnvironment();
  378. }
  379. public AsmManager getStructureModel() {
  380. return ajBuildManager.getStructureModel();
  381. }
  382. }