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

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. }