Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

AjdeCoreBuildManager.java 16KB

17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
15 anos atrás
17 anos atrás
15 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
12 anos atrás
14 anos atrás
14 anos atrás
14 anos atrás
17 anos atrás
14 anos atrás
14 anos atrás
17 anos atrás
9 anos atrás
14 anos atrás
14 anos atrás
14 anos atrás
17 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
17 anos atrás
5 anos atrás
17 anos atrás
5 anos atrás
12 anos atrás
14 anos atrás
14 anos atrás
17 anos atrás
15 anos atrás
17 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
12 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
9 anos atrás
5 anos atrás
17 anos atrás
15 anos atrás
15 anos atrás
15 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
5 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
12 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
17 anos atrás
15 anos atrás
17 anos atrás
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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 v 2.0
  5. * which accompanies this distribution and is available at
  6. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  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.List;
  16. import java.util.Map;
  17. import java.util.StringTokenizer;
  18. import org.aspectj.ajde.core.AjCompiler;
  19. import org.aspectj.ajde.core.ICompilerConfiguration;
  20. import org.aspectj.ajde.core.IOutputLocationManager;
  21. import org.aspectj.ajdt.ajc.AjdtCommand;
  22. import org.aspectj.ajdt.ajc.BuildArgParser;
  23. import org.aspectj.ajdt.ajc.ConfigParser;
  24. import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
  25. import org.aspectj.ajdt.internal.core.builder.AjBuildManager;
  26. import org.aspectj.ajdt.internal.core.builder.AjState;
  27. import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager;
  28. import org.aspectj.asm.AsmManager;
  29. import org.aspectj.bridge.AbortException;
  30. import org.aspectj.bridge.CountingMessageHandler;
  31. import org.aspectj.bridge.IMessage;
  32. import org.aspectj.bridge.IMessageHandler;
  33. import org.aspectj.bridge.ISourceLocation;
  34. import org.aspectj.bridge.Message;
  35. import org.aspectj.bridge.SourceLocation;
  36. import org.aspectj.bridge.context.CompilationAndWeavingContext;
  37. import org.aspectj.org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
  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. for (Object option : options) {
  161. String o = option.toString();
  162. if (formattedOptions.length() > 0) {
  163. formattedOptions.append(", ");
  164. }
  165. formattedOptions.append(o);
  166. }
  167. return formattedOptions.toString();
  168. }
  169. private String formatMap(Map<String,? extends Object> options) {
  170. if (options == null) {
  171. return "<default>";
  172. }
  173. if (options.isEmpty()) {
  174. return "none";
  175. }
  176. return options.toString();
  177. }
  178. private String formatOptionalString(String s) {
  179. if (s == null) {
  180. return "";
  181. } else {
  182. return s;
  183. }
  184. }
  185. /**
  186. * Generate a new AjBuildConfig from the compiler configuration associated with this AjdeCoreBuildManager or from a
  187. * configuration file.
  188. *
  189. * @return null if invalid configuration, corresponding AjBuildConfig otherwise
  190. */
  191. public AjBuildConfig generateAjBuildConfig() {
  192. File configFile = new File(compiler.getId());
  193. ICompilerConfiguration compilerConfig = compiler.getCompilerConfiguration();
  194. CountingMessageHandler handler = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
  195. String[] args = null;
  196. // Retrieve the set of files from either an arg file (@filename) or the compiler configuration
  197. if (configFile.exists() && configFile.isFile()) {
  198. args = new String[] { "@" + configFile.getAbsolutePath() };
  199. } else {
  200. List<String> projectSourceFiles = compilerConfig.getProjectSourceFiles();
  201. if (projectSourceFiles == null) {
  202. return null;
  203. }
  204. List<String> l = new ArrayList<>(projectSourceFiles);
  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. if (compilerConfig.getOutputLocationManager() != null &&
  217. compilerConfig.getOutputLocationManager().getDefaultOutputLocation() != null) {
  218. l.add("-d");
  219. l.add(compilerConfig.getOutputLocationManager().getDefaultOutputLocation().toString());
  220. }
  221. List<String> xmlfiles = compilerConfig.getProjectXmlConfigFiles();
  222. if (xmlfiles != null && !xmlfiles.isEmpty()) {
  223. args = new String[l.size() + xmlfiles.size() + 1];
  224. // TODO speedup
  225. int p = 0;
  226. for (String s : l) {
  227. args[p++] = s;
  228. }
  229. for (String xmlfile : xmlfiles) {
  230. args[p++] = xmlfile;
  231. }
  232. args[p++] = "-xmlConfigured";
  233. } else {
  234. args = l.toArray(new String[0]);
  235. }
  236. }
  237. BuildArgParser parser = new BuildArgParser(handler);
  238. AjBuildConfig config = new AjBuildConfig(parser);
  239. parser.populateBuildConfig(config, args, false, configFile);
  240. // Process the CLASSPATH
  241. String propcp = compilerConfig.getClasspath();
  242. if (propcp != null && propcp.length() != 0) {
  243. StringTokenizer st = new StringTokenizer(propcp, File.pathSeparator);
  244. List<String> configClasspath = config.getClasspath();
  245. ArrayList<String> toAdd = new ArrayList<>();
  246. while (st.hasMoreTokens()) {
  247. String entry = st.nextToken();
  248. if (!configClasspath.contains(entry)) {
  249. toAdd.add(entry);
  250. }
  251. }
  252. if (0 < toAdd.size()) {
  253. List<String> both = new ArrayList<>(configClasspath.size() + toAdd.size());
  254. both.addAll(configClasspath);
  255. both.addAll(toAdd);
  256. config.setClasspath(both);
  257. Classpath[] checkedClasspaths = config.getCheckedClasspaths();
  258. ArrayList<Classpath> cps = parser.handleClasspath(toAdd, compilerConfig.getProjectEncoding());
  259. Classpath[] newCheckedClasspaths = new Classpath[checkedClasspaths.length+cps.size()];
  260. System.arraycopy(checkedClasspaths, 0, newCheckedClasspaths, 0, checkedClasspaths.length);
  261. for (int i=0;i<cps.size();i++) {
  262. newCheckedClasspaths[checkedClasspaths.length+i] = cps.get(i);
  263. }
  264. config.setCheckedClasspaths(newCheckedClasspaths);
  265. }
  266. }
  267. // Process the OUTJAR
  268. if (config.getOutputJar() == null) {
  269. String outJar = compilerConfig.getOutJar();
  270. if (outJar != null && outJar.length() != 0) {
  271. config.setOutputJar(new File(outJar));
  272. }
  273. }
  274. // Process the OUTPUT LOCATION MANAGER
  275. IOutputLocationManager outputLocationManager = compilerConfig.getOutputLocationManager();
  276. if (config.getCompilationResultDestinationManager() == null && outputLocationManager != null) {
  277. config.setCompilationResultDestinationManager(new OutputLocationAdapter(outputLocationManager));
  278. }
  279. // Process the INPATH
  280. config.addToInpath(compilerConfig.getInpath());
  281. // bug 168840 - calling 'setInPath(..)' creates BinarySourceFiles which
  282. // are used to see if there have been changes in classes on the inpath
  283. if (config.getInpath() != null) {
  284. config.processInPath();
  285. }
  286. // Process the SOURCE PATH RESOURCES
  287. config.setSourcePathResources(compilerConfig.getSourcePathResources());
  288. // Process the ASPECTPATH
  289. config.addToAspectpath(compilerConfig.getAspectPath());
  290. // Process the JAVA OPTIONS MAP
  291. Map<String,String> jom = compilerConfig.getJavaOptionsMap();
  292. if (jom != null) {
  293. String version = jom.get(CompilerOptions.OPTION_Compliance);
  294. if (version != null && !version.equals(CompilerOptions.VERSION_1_4)) {
  295. config.setBehaveInJava5Way(true);
  296. }
  297. config.getOptions().set(jom);
  298. }
  299. // Process the NON-STANDARD COMPILER OPTIONS
  300. configureNonStandardOptions(config);
  301. compilerConfig.configurationRead();
  302. ISourceLocation location = null;
  303. if (config.getConfigFile() != null) {
  304. location = new SourceLocation(config.getConfigFile(), 0);
  305. }
  306. String message = parser.getOtherMessages(true);
  307. if (null != message) {
  308. IMessage m = new Message(message, IMessage.ERROR, null, location);
  309. handler.handleMessage(m);
  310. }
  311. // always force model generation in AJDE
  312. config.setGenerateModelMode(true);
  313. // always be in incremental mode in AJDE
  314. config.setIncrementalMode(true);
  315. // always force proceedOnError in AJDE
  316. config.setProceedOnError(true);
  317. config.setProjectEncoding(compilerConfig.getProjectEncoding());
  318. config.setProcessor(compilerConfig.getProcessor());
  319. config.setProcessorPath(compilerConfig.getProcessorPath());
  320. return config;
  321. }
  322. /**
  323. * Helper method for configure build options. This reads all command-line options specified in the non-standard options text
  324. * entry and sets any corresponding unset values in config.
  325. */
  326. private void configureNonStandardOptions(AjBuildConfig config) {
  327. String nonStdOptions = compiler.getCompilerConfiguration().getNonStandardOptions();
  328. if (LangUtil.isEmpty(nonStdOptions)) {
  329. return;
  330. }
  331. // Break a string into a string array of non-standard options.
  332. // Allows for one option to include a ' '. i.e. assuming it has been quoted, it
  333. // won't accidentally get treated as a pair of options (can be needed for xlint props file option)
  334. List<String> tokens = new ArrayList<>();
  335. int ind = nonStdOptions.indexOf('\"');
  336. int ind2 = nonStdOptions.indexOf('\"', ind + 1);
  337. if ((ind > -1) && (ind2 > -1)) { // dont tokenize within double quotes
  338. String pre = nonStdOptions.substring(0, ind);
  339. String quoted = nonStdOptions.substring(ind + 1, ind2);
  340. String post = nonStdOptions.substring(ind2 + 1, nonStdOptions.length());
  341. tokens.addAll(tokenizeString(pre));
  342. tokens.add(quoted);
  343. tokens.addAll(tokenizeString(post));
  344. } else {
  345. tokens.addAll(tokenizeString(nonStdOptions));
  346. }
  347. String[] args = tokens.toArray(new String[] {});
  348. // set the non-standard options in an alternate build config
  349. // (we don't want to lose the settings we already have)
  350. CountingMessageHandler counter = CountingMessageHandler.makeCountingMessageHandler(msgHandlerAdapter);
  351. AjBuildConfig altConfig = AjdtCommand.genBuildConfig(args, counter);
  352. if (counter.hasErrors()) {
  353. return;
  354. }
  355. // copy globals where local is not set
  356. config.installGlobals(altConfig);
  357. }
  358. /** Local helper method for splitting option strings */
  359. private List<String> tokenizeString(String str) {
  360. List<String> tokens = new ArrayList<>();
  361. StringTokenizer tok = new StringTokenizer(str);
  362. while (tok.hasMoreTokens()) {
  363. tokens.add(tok.nextToken());
  364. }
  365. return tokens;
  366. }
  367. /**
  368. * Helper method to ask the messagehandler to handle the given message
  369. */
  370. private void handleMessage(Message msg) {
  371. compiler.getMessageHandler().handleMessage(msg);
  372. }
  373. public void setCustomMungerFactory(Object o) {
  374. ajBuildManager.setCustomMungerFactory(o);
  375. }
  376. public Object getCustomMungerFactory() {
  377. return ajBuildManager.getCustomMungerFactory();
  378. }
  379. public void cleanupEnvironment() {
  380. ajBuildManager.cleanupEnvironment();
  381. }
  382. public AsmManager getStructureModel() {
  383. return ajBuildManager.getStructureModel();
  384. }
  385. }