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.

Builder.java 25KB

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC),
  3. * 2003 Contributors.
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v1.0
  7. * which accompanies this distribution and is available at
  8. * http://www.eclipse.org/legal/epl-v10.html
  9. *
  10. * Contributors:
  11. * PARC initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.internal.tools.build;
  14. import java.io.File;
  15. import java.io.FileFilter;
  16. import java.io.InputStream;
  17. import java.util.ArrayList;
  18. import java.util.Arrays;
  19. import java.util.Collections;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import java.util.ListIterator;
  23. import java.util.Properties;
  24. import java.util.StringTokenizer;
  25. import org.apache.tools.ant.BuildException;
  26. import org.aspectj.internal.tools.build.Result.Kind;
  27. /**
  28. * Template class to build (eclipse) modules (and, weakly, products), including
  29. * any required modules. When building modules, this assumes:
  30. * <ul>
  31. * <li>the name of the module is the base name of the module directory</li>
  32. * <li>all module directories are in the same base (workspace) directory</li>
  33. * <li>the name of the target module jar is {moduleName}.jar</li>
  34. * <li>a module directory contains a <code>.classpath</code> file with
  35. * (currently line-parseable) entries per Eclipse (XML) conventions</li>
  36. * <li><code>Builder.RESOURCE_PATTERN</code> identifies all resources to copy
  37. * to output.</li>
  38. * <li>This can safely trim test-related code:
  39. * <ul>
  40. * <li>source directories named "testsrc"</li>
  41. * <li>libraries named "junit.jar"</li>
  42. * <li>required modules whose names start with "testing"</li>
  43. * </ul>
  44. * <li>A file <code>{moduleDir}/{moduleName}.properties</code> is a property
  45. * file possibly containing entries defining requirements to be merged with the
  46. * output jar (deprecated mechanism - use assembleAll or products)</li>
  47. * </ul>
  48. * This currently provides no control over the compile or assembly process, but
  49. * clients can harvest <code>{moduleDir}/bin</code> directories to re-use the
  50. * results of eclipse compiles.
  51. * <p>
  52. * When building products, this assumes:
  53. * <ul>
  54. * <li>the installer-resources directory is a peer of the products directory,
  55. * itself the parent of the particular product directory.</li>
  56. * <li>the dist, jar, product, and base (module) directory are set</li>
  57. * <li>the product distribution consists of all (and only) the files in the
  58. * dist sub-directory of the product directory</li>
  59. * <li>files in the dist sub-directory that are empty and end with .jar
  60. * represent modules to build, either as named or through aliases known here.</li>
  61. * <li>When assembling the distribution, all non-binary files are to be
  62. * filtered.
  63. * <li>
  64. * <li>the name of the product installer is
  65. * aspectj-{productName}-{version}.jar, where {productName} is the base name of
  66. * the product directory</li>
  67. * </ul>
  68. * <p>
  69. * When run using main(String[]), all relevant Ant libraries and properties must
  70. * be defined.
  71. * <p>
  72. * Written to compile standalone. Refactor if using utils, bridge, etc.
  73. */
  74. public abstract class Builder {
  75. /**
  76. * This has only weak forms for build instructions needed: - resource
  77. * pattern - compiler selection and control
  78. *
  79. * Both assumed and generated paths are scattered; see XXXNameLiteral and
  80. * XXXFileLiteral.
  81. *
  82. * Builder is supposed to be thread-safe, but currently caches build
  83. * properties to tunnel for filters. hmm.
  84. */
  85. public static final String RESOURCE_PATTERN;
  86. public static final String BINARY_SOURCE_PATTERN;
  87. public static final String ALL_PATTERN;
  88. /** enable copy filter semantics */
  89. protected static final boolean FILTER_ON = true;
  90. /** disable copy filter semantics */
  91. protected static final boolean FILTER_OFF = false;
  92. /** define libraries to skip as comma-delimited values for this key */
  93. private static final String SKIP_LIBRARIES_KEY = "skip.libraries";
  94. /** List (String) names of libraries to skip during assembly */
  95. private static final List<String> SKIP_LIBRARIES;
  96. private static final String ERROR_KEY = "error loading properties";
  97. private static final Properties PROPS;
  98. static {
  99. PROPS = new Properties();
  100. List<String> skips = Collections.emptyList();
  101. String resourcePattern = "**/*.txt,**/*.rsc,**/*.gif,**/*.properties";
  102. String allPattern = "**/*";
  103. String binarySourcePattern = "**/*.rsc,**/*.gif,**/*.jar,**/*.zip";
  104. String name = Builder.class.getName().replace('.', '/') + ".properties";
  105. try {
  106. InputStream in = Builder.class.getClassLoader()
  107. .getResourceAsStream(name);
  108. PROPS.load(in);
  109. allPattern = PROPS.getProperty("all.pattern");
  110. resourcePattern = PROPS.getProperty("resource.pattern");
  111. binarySourcePattern = PROPS.getProperty("binarySource.pattern");
  112. skips = commaStrings(PROPS.getProperty(SKIP_LIBRARIES_KEY));
  113. } catch (Throwable t) {
  114. if (t instanceof ThreadDeath) {
  115. throw (ThreadDeath) t;
  116. }
  117. String m = "error loading " + name + ": " + t.getClass() + " " + t;
  118. PROPS.setProperty(ERROR_KEY, m);
  119. }
  120. SKIP_LIBRARIES = skips;
  121. ALL_PATTERN = allPattern;
  122. BINARY_SOURCE_PATTERN = binarySourcePattern;
  123. RESOURCE_PATTERN = resourcePattern;
  124. }
  125. /**
  126. * Splits strings into an unmodifable <code>List</code> of String using
  127. * comma as the delimiter and trimming whitespace from the result.
  128. *
  129. * @param text
  130. * <code>String</code> to split.
  131. * @return unmodifiable List (String) of String delimited by comma in text
  132. */
  133. public static List commaStrings(String text) {
  134. if ((null == text) || (0 == text.length())) {
  135. return Collections.EMPTY_LIST;
  136. }
  137. List<String> strings = new ArrayList<String>();
  138. StringTokenizer tok = new StringTokenizer(text, ",");
  139. while (tok.hasMoreTokens()) {
  140. String token = tok.nextToken().trim();
  141. if (0 < token.length()) {
  142. strings.add(token);
  143. }
  144. }
  145. return Collections.unmodifiableList(strings);
  146. }
  147. /**
  148. * Map delivered-jar name to created-module name
  149. *
  150. * @param jarName
  151. * the String (lowercased) of the jar/zip to map
  152. */
  153. private String moduleAliasFor(String jarName) {
  154. String result = PROPS.getProperty("alias." + jarName, jarName);
  155. if (verbose && result.equals(jarName)) {
  156. String m = "expected alias for " + jarName;
  157. handler.error(m + PROPS.getProperty(ERROR_KEY, ""));
  158. }
  159. return result;
  160. }
  161. protected final Messager handler;
  162. protected boolean buildingEnabled;
  163. private final File tempDir;
  164. private final ArrayList tempFiles;
  165. private final boolean useEclipseCompiles;
  166. protected boolean verbose;
  167. protected Builder(File tempDir, boolean useEclipseCompiles, Messager handler) {
  168. Util.iaxIfNull(handler, "handler");
  169. this.useEclipseCompiles = useEclipseCompiles;
  170. this.handler = handler;
  171. this.tempFiles = new ArrayList();
  172. if ((null == tempDir) || !tempDir.canWrite() || !tempDir.isDirectory()) {
  173. this.tempDir = Util.makeTempDir("Builder");
  174. } else {
  175. this.tempDir = tempDir;
  176. }
  177. buildingEnabled = true;
  178. }
  179. /** tell builder to stop or that it's ok to run */
  180. public void setBuildingEnabled(boolean enabled) {
  181. buildingEnabled = enabled;
  182. }
  183. public void setVerbose(boolean verbose) {
  184. this.verbose = verbose;
  185. }
  186. private void verifyBuildSpec(BuildSpec buildSpec) {
  187. if (null == buildSpec.productDir) { // ensure module properties
  188. // derive moduleDir from baseDir + module
  189. if (null == buildSpec.moduleDir) {
  190. if (null == buildSpec.baseDir) {
  191. throw new BuildException("require baseDir or moduleDir");
  192. } else if (null == buildSpec.module) {
  193. throw new BuildException("require module with baseDir");
  194. } else {
  195. if (null == buildSpec.baseDir) {
  196. buildSpec.baseDir = new File("."); // user.home?
  197. }
  198. buildSpec.moduleDir = new File(buildSpec.baseDir,
  199. buildSpec.module);
  200. }
  201. } else if (null == buildSpec.baseDir) {
  202. // derive baseDir from moduleDir parent
  203. buildSpec.baseDir = buildSpec.moduleDir.getParentFile();
  204. // rule: base is parent
  205. if (null == buildSpec.baseDir) {
  206. buildSpec.baseDir = new File("."); // user.home?
  207. }
  208. handler.log("Builder using derived baseDir: "
  209. + buildSpec.baseDir);
  210. }
  211. Util.iaxIfNotCanReadDir(buildSpec.moduleDir, "moduleDir");
  212. if (null == buildSpec.module) {
  213. // derive module name from directory
  214. buildSpec.module = buildSpec.moduleDir.getName();
  215. if (null == buildSpec.module) {
  216. throw new BuildException("no name, even from "
  217. + buildSpec.moduleDir);
  218. }
  219. }
  220. }
  221. }
  222. /**
  223. * Find the Result (and hence Module and Modules) for this BuildSpec.
  224. */
  225. protected Result specifyResultFor(BuildSpec buildSpec) {
  226. if (buildSpec.trimTesting
  227. && (-1 != buildSpec.module.indexOf("testing"))) { // XXXNameLiteral
  228. String warning = "Warning - cannot trimTesting for testing modules: ";
  229. handler.log(warning + buildSpec.module);
  230. }
  231. Messager handler = new Messager();
  232. Modules modules = new Modules(buildSpec.baseDir, buildSpec.jarDir,
  233. handler);
  234. final Module moduleToBuild = modules.getModule(buildSpec.module);
  235. Kind kind = Result.kind(buildSpec.trimTesting,
  236. buildSpec.assembleAll);
  237. return moduleToBuild.getResult(kind);
  238. }
  239. public final boolean build(BuildSpec buildSpec) {
  240. if (!buildingEnabled) {
  241. return false;
  242. }
  243. verifyBuildSpec(buildSpec);
  244. if (null != buildSpec.productDir) {
  245. return buildProduct(buildSpec);
  246. }
  247. Result result = specifyResultFor(buildSpec);
  248. ArrayList<String> errors = new ArrayList<String>();
  249. try {
  250. return buildAll(result, errors);
  251. } finally {
  252. if (0 < errors.size()) {
  253. String label = "error building " + buildSpec + ": ";
  254. for (Iterator<String> iter = errors.iterator(); iter.hasNext();) {
  255. String m = label + iter.next();
  256. handler.error(m);
  257. }
  258. }
  259. }
  260. }
  261. /**
  262. * Clean up any temporary files, etc. after build completes
  263. */
  264. public boolean cleanup() {
  265. boolean noErr = true;
  266. for (ListIterator iter = tempFiles.listIterator(); iter.hasNext();) {
  267. File file = (File) iter.next();
  268. if (!Util.deleteContents(file) || !file.delete()) {
  269. if (noErr) {
  270. noErr = false;
  271. }
  272. handler.log("unable to clean up " + file);
  273. }
  274. }
  275. return noErr;
  276. }
  277. protected final boolean isLogging() {
  278. return (verbose && (null != this.handler));
  279. }
  280. protected Result[] skipUptodate(Result[] results) {
  281. if (null == results) {
  282. return new Result[0];
  283. }
  284. Result[] done = new Result[results.length];
  285. int to = 0;
  286. for (int i = 0; i < done.length; i++) {
  287. if ((null != results[i]) && results[i].outOfDate()) {
  288. done[to++] = results[i];
  289. }
  290. }
  291. if (to < results.length) {
  292. Result[] newdone = new Result[to];
  293. System.arraycopy(done, 0, newdone, 0, newdone.length);
  294. done = newdone;
  295. }
  296. return done;
  297. }
  298. /**
  299. * Build a result with all antecedants.
  300. *
  301. * @param result
  302. * the Result to build
  303. * @param errors
  304. * the List sink for errors, if any
  305. * @return false after successful build, when module jar should exist
  306. */
  307. protected final boolean buildAll(Result result, List errors) {
  308. Result[] buildList = skipUptodate(getAntecedantResults(result));
  309. ArrayList<String> doneList = new ArrayList<String>();
  310. if ((null != buildList) && (0 < buildList.length)) {
  311. if (isLogging()) {
  312. handler.log("modules to build: " + Arrays.asList(buildList));
  313. }
  314. for (int i = 0; i < buildList.length; i++) {
  315. Result required = buildList[i];
  316. if (!buildingEnabled) {
  317. return false;
  318. }
  319. String requiredName = required.getName();
  320. if (!doneList.contains(requiredName)) {
  321. doneList.add(requiredName);
  322. if (!buildOnly(required, errors)) {
  323. return false;
  324. }
  325. }
  326. }
  327. }
  328. return true;
  329. }
  330. /**
  331. * Build a module but no antecedants.
  332. *
  333. * @param module
  334. * the Module to build
  335. * @param errors
  336. * the List sink for errors, if any
  337. * @return false after successful build, when module jar should exist
  338. */
  339. protected final boolean buildOnly(Result result, List<String> errors) {
  340. if (!result.outOfDate()) {
  341. return true;
  342. }
  343. if (isLogging()) {
  344. handler.log("building " + result);
  345. }
  346. if (!buildingEnabled) {
  347. return false;
  348. }
  349. if (result.getKind().assemble) {
  350. return assembleAll(result, handler);
  351. }
  352. Module module = result.getModule();
  353. final File classesDir;
  354. if (useEclipseCompiles) {
  355. classesDir = new File(module.moduleDir, "bin"); // FileLiteral
  356. } else {
  357. String name = "classes-" + System.currentTimeMillis();
  358. classesDir = new File(tempDir, name);
  359. }
  360. if (verbose) {
  361. handler.log("buildOnly " + module);
  362. }
  363. try {
  364. return (compile(result, classesDir,useEclipseCompiles, errors))
  365. && assemble(result, classesDir, errors);
  366. } finally {
  367. if (!useEclipseCompiles && !Util.delete(classesDir)) {
  368. errors.add("buildOnly unable to delete " + classesDir);
  369. }
  370. }
  371. }
  372. /**
  373. * Register temporary file or directory to be deleted when the build is
  374. * complete, even if an Exception is thrown.
  375. */
  376. protected void addTempFile(File tempFile) {
  377. if (null != tempFile) {
  378. tempFiles.add(tempFile);
  379. }
  380. }
  381. /**
  382. * Build product by discovering any modules to build, building those,
  383. * assembling the product distribution, and optionally creating an installer
  384. * for it.
  385. *
  386. * @return true on success
  387. */
  388. protected final boolean buildProduct(BuildSpec buildSpec)
  389. throws BuildException {
  390. Util.iaxIfNull(buildSpec, "buildSpec");
  391. if (!buildSpec.trimTesting) {
  392. buildSpec.trimTesting = true;
  393. handler.log("testing trimmed for " + buildSpec);
  394. }
  395. Util.iaxIfNotCanReadDir(buildSpec.productDir, "productDir");
  396. Util.iaxIfNotCanReadDir(buildSpec.baseDir, "baseDir");
  397. Util.iaxIfNotCanWriteDir(buildSpec.distDir, "distDir");
  398. // ---- discover modules to build, and build them
  399. Modules modules = new Modules(buildSpec.baseDir, buildSpec.jarDir,
  400. handler);
  401. ProductModule[] productModules = discoverModules(buildSpec.productDir,
  402. modules);
  403. for (int i = 0; i < productModules.length; i++) {
  404. if (buildSpec.verbose) {
  405. handler.log("building product module " + productModules[i]);
  406. }
  407. if (!buildProductModule(productModules[i])) {
  408. return false;
  409. }
  410. }
  411. if (buildSpec.verbose) {
  412. handler.log("assembling product module for " + buildSpec);
  413. }
  414. // ---- assemble product distribution
  415. final String productName = buildSpec.productDir.getName();
  416. final File targDir = new File(buildSpec.distDir, productName);
  417. final String targDirPath = targDir.getPath();
  418. if (targDir.canWrite()) {
  419. Util.deleteContents(targDir);
  420. }
  421. if (!targDir.canWrite() && !targDir.mkdirs()) {
  422. if (buildSpec.verbose) {
  423. handler.log("buildProduct unable to create " + targDir);
  424. }
  425. return false;
  426. }
  427. // copy non-binaries (with filter)
  428. File distDir = new File(buildSpec.productDir, "dist");
  429. if (!copyNonBinaries(buildSpec, distDir, targDir)) {
  430. return false;
  431. }
  432. // copy binaries (but not module flag files)
  433. String excludes = null;
  434. {
  435. StringBuffer buf = new StringBuffer();
  436. for (int i = 0; i < productModules.length; i++) {
  437. if (0 < buf.length()) {
  438. buf.append(",");
  439. }
  440. buf.append(productModules[i].relativePath);
  441. }
  442. if (0 < buf.length()) {
  443. excludes = buf.toString();
  444. }
  445. }
  446. if (!copyBinaries(buildSpec, distDir, targDir, excludes)) {
  447. return false;
  448. }
  449. // copy binaries associated with module flag files
  450. for (int i = 0; i < productModules.length; i++) {
  451. final ProductModule product = productModules[i];
  452. final Kind kind = Result.kind(Result.NORMAL, product.assembleAll);
  453. Result result = product.module.getResult(kind);
  454. String targPath = Util.path(targDirPath, product.relativePath);
  455. File jarFile = result.getOutputFile();
  456. copyFile(jarFile, new File(targPath), FILTER_OFF);
  457. }
  458. handler.log("created product in " + targDir);
  459. // ---- create installer
  460. if (buildSpec.createInstaller) {
  461. return buildInstaller(buildSpec, targDirPath);
  462. } else {
  463. return true;
  464. }
  465. }
  466. protected boolean copyBinaries(BuildSpec buildSpec, File distDir,
  467. File targDir, String excludes) {
  468. String includes = Builder.BINARY_SOURCE_PATTERN;
  469. return copyFiles(distDir, targDir, includes, excludes, FILTER_OFF);
  470. }
  471. /**
  472. * filter-copy everything but the binaries
  473. */
  474. protected boolean copyNonBinaries(BuildSpec buildSpec, File distDir,
  475. File targDir) {
  476. String excludes = Builder.BINARY_SOURCE_PATTERN;
  477. String includes = Builder.ALL_PATTERN;
  478. return copyFiles(distDir, targDir, includes, excludes, FILTER_ON);
  479. }
  480. protected final boolean buildProductModule(ProductModule module) {
  481. ArrayList errors = new ArrayList();
  482. try {
  483. Kind productKind = Result.kind(Result.NORMAL, Result.ASSEMBLE);
  484. Result result = module.module.getResult(productKind);
  485. return buildAll(result, errors);
  486. } finally {
  487. for (Iterator iter = errors.iterator(); iter.hasNext();) {
  488. handler.error("error building " + module + ": " + iter.next());
  489. }
  490. }
  491. }
  492. /**
  493. * Discover any modules that might need to be built in order to assemble the
  494. * product distribution. This interprets empty .jar files as module
  495. * deliverables.
  496. */
  497. protected ProductModule[] discoverModules(File productDir, Modules modules) {
  498. final ArrayList<File> found = new ArrayList<File>();
  499. FileFilter filter = new FileFilter() {// empty jar files
  500. public boolean accept(File file) {
  501. if ((null != file) && file.canRead()
  502. && file.getPath().endsWith(".jar") // XXXFileLiteral
  503. && (0l == file.length())) {
  504. found.add(file);
  505. }
  506. return true;
  507. }
  508. };
  509. Util.visitFiles(productDir, filter);
  510. ArrayList<ProductModule> results = new ArrayList<ProductModule>();
  511. for (File file: found) {
  512. String jarName = moduleAliasFor(file.getName().toLowerCase());
  513. if (jarName.endsWith(".jar") || jarName.endsWith(".zip")) { // XXXFileLiteral
  514. jarName = jarName.substring(0, jarName.length() - 4);
  515. } else {
  516. handler.log("can only replace .[jar|zip]: " + file);
  517. // XXX error?
  518. }
  519. boolean assembleAll = jarName.endsWith("-all");
  520. // XXXFileLiteral
  521. String name = (!assembleAll ? jarName : jarName.substring(0,
  522. jarName.length() - 4));
  523. Module module = modules.getModule(name);
  524. if (null == module) {
  525. handler.log("unable to find module for " + file);
  526. } else {
  527. results.add(new ProductModule(productDir, file, module,
  528. assembleAll));
  529. }
  530. }
  531. return (ProductModule[]) results.toArray(new ProductModule[0]);
  532. }
  533. /**
  534. * Subclasses should query whether to include library files in the assembly.
  535. *
  536. * @param module
  537. * the Module being built
  538. * @param libraries
  539. * the List of File path to the jar to consider assembling
  540. * @return true if the jar should be included, false otherwise.
  541. */
  542. protected void removeLibraryFilesToSkip(Module module, List libraries) {
  543. for (ListIterator liter = libraries.listIterator(); liter.hasNext();) {
  544. File library = (File) liter.next();
  545. final String fname = library.getName();
  546. if (null != fname) {
  547. for (Iterator iter = SKIP_LIBRARIES.iterator(); iter.hasNext();) {
  548. String name = (String) iter.next();
  549. if (fname.equals(name)) {
  550. liter.remove();
  551. break;
  552. }
  553. }
  554. }
  555. }
  556. }
  557. /**
  558. * @return String[] names of results to build for this module
  559. */
  560. abstract protected Result[] getAntecedantResults(Result toBuild);
  561. /**
  562. * Compile module classes to classesDir, saving String errors.
  563. *
  564. * @param module
  565. * the Module to compile
  566. * @param classesDir
  567. * the File directory to compile to
  568. * @param useExistingClasses
  569. * if true, don't recompile and ensure classes are available
  570. * @param errors
  571. * the List to add error messages to
  572. */
  573. abstract protected boolean compile(Result result, File classesDir,
  574. boolean useExistingClasses, List<String> errors);
  575. /**
  576. * Assemble the module distribution from the classesDir, saving String
  577. * errors.
  578. *
  579. * @see #removeLibraryFilesToSkip(Module, File)
  580. */
  581. abstract protected boolean assemble(Result result, File classesDir,
  582. List<String> errors);
  583. /**
  584. * Assemble the module distribution from the classesDir and all
  585. * antecendants, saving String errors.
  586. *
  587. * @see #removeLibraryFilesToSkip(Module, File)
  588. */
  589. abstract protected boolean assembleAll(Result result, Messager handler);
  590. /**
  591. * Generate the installer for this product to targDirPath
  592. */
  593. abstract protected boolean buildInstaller(BuildSpec buildSpec,
  594. String targDirPath);
  595. /**
  596. * Copy fromFile to toFile, optionally filtering contents
  597. */
  598. abstract protected boolean copyFile(File fromFile, File toFile,
  599. boolean filter);
  600. /**
  601. * Copy toDir any fromDir included files without any exluded files,
  602. * optionally filtering contents.
  603. *
  604. * @param fromDir
  605. * File dir to read from - error if not readable
  606. * @param toDir
  607. * File dir to write to - error if not writable
  608. * @param included
  609. * String Ant pattern of included files (if null, include all)
  610. * @param excluded
  611. * String Ant pattern of excluded files (if null, exclude none)
  612. * @param filter
  613. * if FILTER_ON, then filter file contents using global
  614. * token/value pairs
  615. */
  616. abstract protected boolean copyFiles(File fromDir, File toDir,
  617. String included, String excluded, boolean filter);
  618. }