KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > antmod > descriptor > ReleaseTask


1 package org.antmod.descriptor;
2
3 import java.io.File JavaDoc;
4 import java.net.MalformedURLException JavaDoc;
5 import java.net.URL JavaDoc;
6 import java.text.ParseException JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.List JavaDoc;
9
10 import org.antmod.buildplugin.BuildPluginFactory;
11 import org.antmod.conf.AntmodProperties;
12 import org.antmod.scm.ScmSystem;
13 import org.antmod.scm.ScmSystemFactory;
14 import org.antmod.scm.ScmUrl;
15 import org.antmod.scm.ScmVersion;
16 import org.antmod.tasks.ConditionalAnt;
17 import org.antmod.util.ProcessLauncher;
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.commons.lang.SystemUtils;
20 import org.apache.tools.ant.BuildException;
21 import org.apache.tools.ant.Project;
22 import org.apache.tools.ant.Task;
23 import org.apache.tools.ant.taskdefs.Ant;
24 import org.apache.tools.ant.taskdefs.Copy;
25 import org.apache.tools.ant.taskdefs.Delete;
26 import org.apache.tools.ant.taskdefs.FixCRLF;
27 import org.apache.tools.ant.taskdefs.Get;
28 import org.apache.tools.ant.taskdefs.Input;
29 import org.apache.tools.ant.taskdefs.Property;
30 import org.apache.tools.ant.types.EnumeratedAttribute;
31 import org.apache.tools.ant.types.FileSet;
32 import org.apache.tools.ant.types.FilterSet;
33
34 /**
35  * Task for running various types of actions against the modules of
36  * a given {@link ReleaseDescriptor}.
37  * <p/>
38  *
39  * Note: Based on original "org.antmod.tasks.Release" class by Herko ter Horst and Klaas Waslander.
40  *
41  * @author Klaas Waslander
42  */

43 public final class ReleaseTask extends Task {
44
45     /*-------------------+
46     | Constants |
47     +-------------------*/

48
49     /**
50      * The name of Eclipse's bin directory.
51      */

52     public final static String JavaDoc ECLIPSE_BIN_DIRNAME = "bin";
53
54     /**
55      * The postfix for a library's license file.
56      */

57     public final static String JavaDoc LIB_LICENSE_POSTFIX = "-license.txt";
58
59     /*-------------------+
60     | Variables |
61     +-------------------*/

62
63     /** counter for generating unique property names for ask results */
64     private static int askCounter;
65
66     // release specific subdir of checkout.dir
67
private File JavaDoc releaseDir;
68     // the default name build.xml master file
69
private File JavaDoc defaultModuleBuildFile;
70     // the release build.xml file master file
71
private File JavaDoc releaseBuildFile;
72     // the default cvs ignore file for a module
73
private File JavaDoc defaultModuleCvsIgnoreFile;
74
75     private ReleaseDescriptor descriptor;
76
77     // the javalib scm url
78
private ScmUrl javalibScmUrl;
79     private String JavaDoc javalibUrl;
80     // the local javalib export directory within the release directory
81
private File JavaDoc javalibExportDir;
82
83     /**
84      * The Action attribute of this release (set by Ant)
85      */

86     private Action action;
87
88     /**
89      * The descriptor (set by Ant)
90      */

91     private String JavaDoc descriptorName;
92
93     /**
94      * The property attribute which is the name of the property that can be set by this task (set by Ant)
95      */

96     private String JavaDoc property;
97
98     /*-------------------+
99     | Constructors |
100     +-------------------*/

101
102     /**
103      * Construct a new Release task.
104      */

105     public ReleaseTask() {
106     }
107
108     /*-------------------+
109     | Methods |
110     +-------------------*/

111
112     /**
113      * Retrieve the base name of a release, without any version information.
114      *
115      * @param releaseName the fully qualified name of the release, e.g. afserver-dev.
116      * @return the base name of a release, e.g. afserver
117      */

118     public static String JavaDoc getBaseName(String JavaDoc releaseName) {
119         String JavaDoc result = releaseName;
120
121         int lastIndexOfDash = releaseName.lastIndexOf("-");
122         if (lastIndexOfDash >= 1) {
123             result = releaseName.substring(0, lastIndexOfDash);
124         }
125
126         return result;
127     }
128
129     private void _initCheckoutFiles() {
130         String JavaDoc ANTMOD_HOME = getProject().getProperty("env.ANTMOD_HOME");
131
132         if (defaultModuleBuildFile == null) {
133             defaultModuleBuildFile = new File JavaDoc(AntmodProperties.getProperty("antmod.module.antfile.source"));
134         }
135
136         if (releaseBuildFile == null) {
137             releaseBuildFile = new File JavaDoc(AntmodProperties.getProperty("antmod.release.antfile.source"));
138         }
139
140         if (defaultModuleCvsIgnoreFile == null) {
141             defaultModuleCvsIgnoreFile = new File JavaDoc(ANTMOD_HOME, "resources/scm/module.cvsignore");
142         }
143     }
144
145     private void _init() throws BuildException {
146         this.javalibExportDir = new File JavaDoc(this.releaseDir, getProject().getProperty("antmod.release.dirs.javalib"));
147         try {
148             this.javalibUrl = getProject().getProperty("antmod.javalib.url");
149             /*
150             if (this.javalibUrl == null) {
151                 // backwards compatibility with old property name
152                 this.javalibUrl = getProject().getProperty("antmod.javalib.repos.url");
153             }
154             */

155
156             if (this.javalibUrl.startsWith("scm:")) {
157                 this.javalibScmUrl = new ScmUrl(this.javalibUrl);
158             }
159         } catch (ParseException JavaDoc pe) {
160             throw new BuildException(pe);
161         } catch (IllegalArgumentException JavaDoc iae) {
162             throw new BuildException("Javalib Url \"antmod.javalib.url\" invalid: " + iae);
163         }
164
165         // retrieve descriptor
166
this.descriptor = DescriptorStoreFactory.getConfiguredDescriptorStore().getReleaseDescriptor(this.descriptorName);
167     }
168
169     /**
170      * To-be-set in the release descriptor, indicating what action to execute on each module.
171      * @param action
172      */

173     public void setAction(Action action) {
174         this.action = action;
175     }
176
177     /**
178      * The descriptor that defines the modules that the action should work against.
179      */

180     public void setDescriptor(String JavaDoc descriptor) {
181         if (descriptor != null) {
182             this.descriptorName = descriptor.trim().replace('/', '-').replace(' ', '-');
183         }
184     }
185
186     /**
187      * Name of the property that can be set in the Ant project.
188      */

189     public void setProperty(String JavaDoc property) {
190         this.property = property;
191     }
192     
193     public static File JavaDoc getReleaseDir(Project antProject) {
194         String JavaDoc checkout = antProject.getProperty("antmod.checkoutdir");
195         if (!StringUtils.isBlank(checkout)) {
196             File JavaDoc checkoutDir = new File JavaDoc(checkout);
197             if (checkoutDir.exists() && checkoutDir.isDirectory()) {
198                 // directory "releasename-version".
199
String JavaDoc releaseDirName = antProject.getProperty("antmod.release.dir.name");
200                 if (releaseDirName != null) {
201                     releaseDirName = releaseDirName.replace('/', '-').replace(' ', '-');
202
203                     // fix 'antmod.release.dir.name' value with properly replaced '-' for the rest of the build.xml
204
antProject.setProperty("antmod.release.dir.name", releaseDirName);
205
206                     return new File JavaDoc(checkoutDir, releaseDirName);
207                 }
208             } else {
209                 throw new BuildException("Check-out directory " + checkoutDir.getPath() + " does not exist or is not a directory.");
210             }
211         } else {
212             throw new BuildException("\"antmod.checkoutdir\" property in '${HOME}/.antmodrc' not set.");
213         }
214         return null;
215     }
216
217     /**
218      * Execute the 'action' on each module of this release.
219      * @throws BuildException
220      */

221     public void execute() throws BuildException {
222         this.releaseDir = getReleaseDir(getProject());
223         if (this.releaseDir != null) {
224             _init();
225             if (this.descriptor != null) {
226                 this.releaseDir.mkdirs();
227             }
228
229             // "switch" depending on the value of action
230
String JavaDoc actionValue = action.getValue();
231             if (actionValue.equals(Action.ISAVAILABLE)) {
232                 if (this.descriptor != null) {
233                     getProject().setProperty(this.property, "true");
234                 }
235             } else if (actionValue.equals(Action.CHECKOUT)) {
236                 doCheckout();
237             } else if (actionValue.equals(Action.UPDATE_ANT)) {
238                 doUpdateAnt();
239             } else if (actionValue.equals(Action.DISTMODULES)) {
240                 doDistModules();
241             } else if (actionValue.equals(Action.LIST)) {
242                 doList();
243             }
244         }
245     }
246
247     /**
248      * Check-out a release.
249      */

250     private void doCheckout() throws BuildException {
251         assert releaseDir != null;
252
253         log("", Project.MSG_WARN);
254         log("-- Checking out to: \"" + releaseDir.getAbsolutePath() + "\"", Project.MSG_WARN);
255         log("", Project.MSG_WARN);
256
257         _initCheckoutFiles();
258
259         //
260
// Delete the modules no longer being referenced
261
//
262
File JavaDoc[] moduleDirs = releaseDir.listFiles();
263         for (int i = 0; i < moduleDirs.length; i++) {
264             File JavaDoc moduleDir = moduleDirs[i];
265             if (!moduleDir.isDirectory()
266                 || moduleDir.getName().startsWith("_")
267                 || moduleDir.getName().startsWith(".")
268                 || moduleDir.getName().equals(this.javalibExportDir.getName())
269                 || moduleDir.getName().equals(ECLIPSE_BIN_DIRNAME)
270                 || moduleDir.getName().equals(getProject().getProperty("antmod.release.dirs.build"))) {
271                 continue;
272             }
273
274             // check if a module with that name still exists in the release descriptor
275
if (!this.descriptor.containsModule(moduleDir.getName())) {
276                 if (isOkayToDelete("antmod.delete.unusedmodules", "unused module " + moduleDir.getPath())) {
277                     log("-- DELETING UNUSED MODULE: " + moduleDir.getPath(), Project.MSG_WARN);
278                     deleteDir(moduleDir);
279                 }
280             }
281         }
282
283         // Use a Copy task to copy the default build files.
284
Copy copyTask = createBuildfileCopyTask();
285         /*
286         Copy copyTask = new Copy();
287         copyTask.setProject(getProject());
288         copyTask.setTaskName(getTaskName());
289         */

290
291         Get getTask = new Get();
292         getTask.setProject(getProject());
293         getTask.setTaskName(getTaskName());
294         String JavaDoc javalibUser = getProject().getProperty("antmod.javalib.url.username");
295         if (javalibUser != null) {
296             //log("Using GET username: \"" + javalibUser + "\"", Project.MSG_WARN);
297
getTask.setUsername(javalibUser);
298         }
299         String JavaDoc javalibPassword = getProject().getProperty("antmod.javalib.url.password");
300         if (javalibPassword != null) {
301             //log("Using GET password: \"" + javalibPassword + "\"", Project.MSG_WARN);
302
getTask.setPassword(javalibPassword);
303         }
304
305         StringBuffer JavaDoc allPackages = new StringBuffer JavaDoc(); // used for deleting unused ones
306
StringBuffer JavaDoc allLicenses = new StringBuffer JavaDoc(); // used for deleting unused ones
307
File JavaDoc libExportDir = this.javalibExportDir;
308
309         List JavaDoc javalibList = this.descriptor.getJavaLibs();
310         if (javalibList.size() > 0) {
311             log("", Project.MSG_WARN);
312             log("-- Placing " + javalibList.size() + " java libraries", Project.MSG_WARN);
313
314             if (this.javalibScmUrl != null) {
315                 //
316
// JAVALIB SCM RETRIEVAL
317
//
318

319                 // update locally cached javalibs first
320
ScmSystem javalibScm = ScmSystemFactory.getScmSystemByUrl(this.javalibScmUrl);
321                 File JavaDoc localJavalibDir = new File JavaDoc(getProject().getProperty("antmod.javalib.localdir"));
322                 localJavalibDir.mkdirs();
323                 javalibScm.doCheckoutOrUpdate(this.javalibScmUrl.getModule(), localJavalibDir, null, false);
324
325                 //
326
// Copy only those libraries and licenses that are specified in release descriptor
327
//
328
// DON'T use the copyTask initialized above, it uses filters which means all files
329
// are processed as text, which corrupts binary file, such as... libraries
330
Copy libCopyTask = new Copy();
331                 libCopyTask.setProject(getProject());
332                 libCopyTask.setOverwrite(true);
333
334                 Iterator JavaDoc lit = javalibList.iterator();
335                 while (lit.hasNext()) {
336                     ReleaseDescriptor.JavaLib lib = (ReleaseDescriptor.JavaLib) lit.next();
337                     String JavaDoc libname = lib.getName().trim().replace('\\', '/');
338                     allPackages.append(libname);
339                     allPackages.append(' ');
340
341                     // only add library if not copied before
342
if (!new File JavaDoc(libExportDir, libname).exists()) {
343                         libCopyTask.setFile(new File JavaDoc(localJavalibDir, libname));
344                         libCopyTask.setTofile(new File JavaDoc(libExportDir, libname));
345                         libCopyTask.execute();
346                     }
347
348                     // add to license list
349
String JavaDoc licenseName;
350                     int dashIndex = libname.lastIndexOf("-");
351                     int dotIndex = libname.lastIndexOf(".");
352                     if (dashIndex > 0) {
353                         licenseName = libname.substring(0, dashIndex) + LIB_LICENSE_POSTFIX;
354                     } else if (dotIndex > 0) {
355                         licenseName = libname.substring(0, dotIndex) + LIB_LICENSE_POSTFIX;
356                     } else {
357                         licenseName = libname + LIB_LICENSE_POSTFIX;
358                     }
359                     allLicenses.append(licenseName);
360                     allLicenses.append(' ');
361
362                     // only add license if not copied before
363
if (!new File JavaDoc(libExportDir, licenseName).exists()) {
364                         File JavaDoc localLicenseFile = new File JavaDoc(localJavalibDir, licenseName);
365                         if (localLicenseFile.exists()) {
366                             libCopyTask.setFile(localLicenseFile);
367                             libCopyTask.setTofile(new File JavaDoc(libExportDir, licenseName));
368                             libCopyTask.execute();
369                         }
370                     }
371                 }
372             } else {
373                 //
374
// JAVALIB GET RETRIEVAL (http, ftp, etc...)
375
//
376
libExportDir.mkdirs();
377
378                 // let's try to fetch javalibs using Ant's "get" task
379
Iterator JavaDoc lit = javalibList.iterator();
380                 while (lit.hasNext()) {
381                     ReleaseDescriptor.JavaLib lib = (ReleaseDescriptor.JavaLib) lit.next();
382                     String JavaDoc libname = lib.getName().trim().replace('\\', '/');
383                     allPackages.append(libname);
384                     allPackages.append(' ');
385
386                     // only add library if not copied before
387
if (!new File JavaDoc(libExportDir, libname).exists()) {
388                         try {
389                             getTask.setSrc(new URL JavaDoc(this.javalibUrl + "/" + libname));
390                         } catch (MalformedURLException JavaDoc e) {
391                             e.printStackTrace();
392                         }
393                         getTask.setDest(new File JavaDoc(libExportDir, libname));
394                         getTask.execute();
395                     }
396
397                     // TODO: add license file retrieval for non-scm javalib url handling
398
}
399             }
400         }
401
402         //
403
// Delete library files no longer being referenced
404
//
405
File JavaDoc[] exportedLibFiles = libExportDir.listFiles();
406         if (exportedLibFiles != null) {
407             for (int i = 0; i < exportedLibFiles.length; i++) {
408                 File JavaDoc exportedLibFile = exportedLibFiles[i];
409                 if (allLicenses.indexOf(exportedLibFile.getName()) < 0 && allPackages.indexOf(exportedLibFile.getName()) < 0) {
410                     String JavaDoc libname = exportedLibFile.getName();
411
412                     if (libname.startsWith(".") || libname.startsWith("_")) {
413                         // leave some files around
414
log("-- Leaving non-javalib file around: " + libname, Project.MSG_WARN);
415                     } else if (exportedLibFile.isDirectory()) {
416                         // if a directory (like "CVS"), delete silently
417
deleteDir(exportedLibFile);
418                     } else if (isOkayToDelete("antmod.delete.unusedjavalibs", "unused javalib: " + libname)) {
419                         // library file not used, delete it
420
log("-- Delete unused library file: " + libname, Project.MSG_WARN);
421                         if (!exportedLibFile.delete()) {
422                             log("-- FAILURE: could not delete unused library file: " + libname, Project.MSG_WARN);
423                         }
424                     }
425                 }
426             }
427         }
428
429         // Copy the default release build file.
430
copyReleaseBuildFile(copyTask);
431         /*
432         copyTask.setFile(releaseBuildFile);
433         copyTask.setTofile(new File(releaseDir, AntmodProperties.getProperty("antmod.release.antfile")));
434         copyTask.execute();
435         */

436
437         //
438
// Checkout the includes
439
//
440
Iterator JavaDoc it = this.descriptor.getIncludes().iterator();
441         while (it.hasNext()) {
442             ReleaseDescriptor.Include include = (ReleaseDescriptor.Include) it.next();
443
444             log("", Project.MSG_WARN);
445             log("--", Project.MSG_WARN);
446             log("-- CHECKOUT INCLUDE: " + include.getReleaseName(), Project.MSG_WARN);
447             log("--", Project.MSG_WARN);
448
449             // checkout the included release
450

451             Ant antTask = createAnt(Action.CHECKOUT);
452             antTask.setInheritAll(false);
453             antTask.setTaskName("include-" + getOwningTarget());
454             antTask.setDir(new File JavaDoc(getProject().getProperty("env.ANTMOD_HOME")));
455             Property prop = antTask.createProperty();
456             prop.setName("antmod.release");
457             prop.setValue(include.getReleaseName());
458             antTask.execute();
459
460             //antOnInclude(include, "update");
461

462             antOnInclude(include, "dist");
463             include(include, false);
464
465             log("", Project.MSG_WARN);
466             log("--", Project.MSG_WARN);
467             log("-- END INCLUDE: " + include.getReleaseName(), Project.MSG_WARN);
468             log("--", Project.MSG_WARN);
469         }
470
471         //
472
// Checkout the modules
473
//
474
/*Iterator*/
475         it = this.descriptor.getModules().iterator();
476         while (it.hasNext()) {
477             // Check-out the name.
478
ReleaseDescriptor.Module module = (ReleaseDescriptor.Module) it.next();
479             log("", Project.MSG_WARN);
480             log("-- Checking out module: " + module.getName() + " [" + module.getVersion() + "]", Project.MSG_WARN);
481             ScmSystem scm = ScmSystemFactory.getScmSystemByName(module.getRepos());
482             if (scm == null) {
483                 throw new BuildException(
484                     "SCM rsepository \""
485                         + module.getRepos()
486                         + "\" undefined, while trying to checkout module \""
487                         + module.getName()
488                         + "\"");
489             }
490             File JavaDoc moduleDir = new File JavaDoc(releaseDir, module.getName());
491             File JavaDoc moduleBuildFile = new File JavaDoc(moduleDir, AntmodProperties.getProperty("antmod.module.antfile"));
492             moduleBuildFile.delete();
493
494             scm.doCheckoutOrUpdate(module.getName(), moduleDir, new ScmVersion(module.getName(), module.getVersion()), false);
495
496             // Fail if module already has a build.xml
497
if (moduleBuildFile.exists()) {
498                 throw new BuildException(
499                     "Module \""
500                         + module.getName()
501                         + "\" has a '"
502                         + moduleBuildFile.getName()
503                         + "' checked into SCM - delete it first from the repository, as it is a read-only Antmod file!");
504             }
505
506             // Copy the default name build file.
507
copyModuleBuildFile(copyTask, module);
508             /*
509             copyTask.setFile(defaultModuleBuildFile);
510             copyTask.setTofile(moduleBuildFile);
511             copyTask.execute();
512             */

513
514             // Copy the default ".cvsignore" file if CVS
515
if (scm.getUrl().getType().equals("cvs")) {
516                 // copy only if none exists yet
517
File JavaDoc cvsIgnoreFile = new File JavaDoc(new File JavaDoc(releaseDir, module.getName()), ".cvsignore");
518                 if (!cvsIgnoreFile.exists()) {
519                     copyTask.setFile(defaultModuleCvsIgnoreFile);
520                     copyTask.setTofile(cvsIgnoreFile);
521                     copyTask.execute();
522                 }
523             }
524         }
525     }
526
527     /**
528      * Updates Ant buildfiles insides the release.
529      */

530     private void doUpdateAnt() throws BuildException {
531         _initCheckoutFiles();
532         setTaskName("update-ant");
533         Copy copyTask = createBuildfileCopyTask();
534
535         // copy release build file
536
copyReleaseBuildFile(copyTask);
537
538         // copy module build file
539
Iterator JavaDoc iter = this.descriptor.getModules().iterator();
540         while (iter.hasNext()) {
541             ReleaseDescriptor.Module module = (ReleaseDescriptor.Module) iter.next();
542             copyModuleBuildFile(copyTask, module);
543         }
544     }
545
546     private Copy createBuildfileCopyTask() {
547         Copy copyTask = new Copy();
548         copyTask.setProject(getProject());
549         copyTask.setTaskName("update-ant");
550         copyTask.setOverwrite(true);
551
552         FilterSet copyTokens = copyTask.createFilterSet();
553         copyTokens.addFilter("antmod.plugins.injectrelease.contents", BuildPluginFactory.getInjectReleaseContents(getProject()));
554         copyTokens.addFilter("antmod.plugins.injectmodule.contents", BuildPluginFactory.getInjectModuleContents(getProject()));
555         copyTokens.addFilter("antmod.target", AntmodProperties.getProperty("antmod.target"));
556         copyTokens.addFilter("antmod.release.metadata.file", AntmodProperties.getProperty("antmod.release.metadata.file"));
557         return copyTask;
558     }
559
560     private void copyReleaseBuildFile(Copy copyTask) {
561         copyTask.setFile(this.releaseBuildFile);
562         File JavaDoc releaseTofile = new File JavaDoc(releaseDir, AntmodProperties.getProperty("antmod.release.antfile"));
563         copyTask.setTofile(releaseTofile);
564         log(releaseTofile.getName(), Project.MSG_WARN);
565         copyTask.execute();
566
567         // let Ant fix possible newline issues which have popped up magically occasionally
568
FixCRLF fixCrlfTask = new FixCRLF();
569         fixCrlfTask.setProject(getProject());
570         fixCrlfTask.setSrcdir(releaseTofile.getParentFile());
571         fixCrlfTask.setIncludes(releaseTofile.getName());
572         fixCrlfTask.execute();
573     }
574     
575     private void copyModuleBuildFile(Copy copyTask, ReleaseDescriptor.Module module) {
576         File JavaDoc moduleDir = new File JavaDoc(releaseDir, module.getName());
577         copyTask.setFile(defaultModuleBuildFile);
578         File JavaDoc moduleTofile = new File JavaDoc(moduleDir, AntmodProperties.getProperty("antmod.module.antfile"));
579         copyTask.setTofile(moduleTofile);
580         log(moduleDir.getName() + File.separator + AntmodProperties.getProperty("antmod.module.antfile"), Project.MSG_WARN);
581         copyTask.execute();
582
583         // let Ant fix possible newline issues which have popped up magically occasionally
584
FixCRLF fixCrlfTask = new FixCRLF();
585         fixCrlfTask.setProject(getProject());
586         fixCrlfTask.setSrcdir(moduleTofile.getParentFile());
587         fixCrlfTask.setIncludes(moduleTofile.getName());
588         fixCrlfTask.execute();
589     }
590
591     /**
592      * Run dist or build on each module, and handle includes.
593      * @throws BuildException
594      */

595     private void doDistModules() throws BuildException {
596         assert releaseDir != null;
597
598         // Handle includes
599
Iterator JavaDoc it = this.descriptor.getIncludes().iterator();
600         while (it.hasNext()) {
601             ReleaseDescriptor.Include include = (ReleaseDescriptor.Include) it.next();
602             log("-- DIST INCLUDE: " + include.getReleaseName(), Project.MSG_WARN);
603             antOnInclude(include, "dist");
604             include(include, true);
605             log("-- END INCLUDE: " + include.getReleaseName(), Project.MSG_WARN);
606         }
607
608         // Calls the "build" target when the type is "library",
609
// calls the "dist" target when the type is "dist", "main" or "buildrelease".
610
//
611
// Each module can override "dist" to include interesting
612
// files in its own "build/dist" directory, if they are
613
// included in a release as type 'dist'.
614

615         String JavaDoc typeValue;
616         Iterator JavaDoc moduleIter = this.descriptor.getModules().iterator();
617         while (moduleIter.hasNext()) {
618             ReleaseDescriptor.Module module = (ReleaseDescriptor.Module) moduleIter.next();
619
620             //
621
// let module fill its "build/lib" and/or "build/dist" directories
622
//
623
typeValue = module.getType();
624             if (typeValue != null
625                 && (typeValue.equals(ReleaseDescriptor.Module.TYPE_DIST)
626                     || typeValue.equals(ReleaseDescriptor.Module.TYPE_MAIN)
627                     || typeValue.equals(ReleaseDescriptor.Module.TYPE_BUILDRELEASE))) {
628                 String JavaDoc checkChangesDir = "";
629                 antOnModule(module, "dist", checkChangesDir);
630             } else {
631                 // invoke 'build' by default
632
String JavaDoc checkChangesDir = "";
633                 antOnModule(module, "build", checkChangesDir);
634             }
635         }
636     }
637
638     /**
639      * Lists all modules, with current versions and whether developer is working on it.
640      * @throws BuildException
641      */

642     private void doList() throws BuildException {
643         assert releaseDir != null;
644
645         log("RELEASE: " + this.descriptorName, Project.MSG_WARN);
646         log("", Project.MSG_WARN);
647         log("MODULENAME RELEASE VERSION LOCAL VERSION LATEST VERSION TYPE INFO", Project.MSG_WARN);
648         log("-------------- ---------------- -------------- -------------- ------ --------------", Project.MSG_WARN);
649
650         Iterator JavaDoc moduleIter = this.descriptor.getModules().iterator();
651         while (moduleIter.hasNext()) {
652             ReleaseDescriptor.Module module = (ReleaseDescriptor.Module) moduleIter.next();
653             File JavaDoc moduleDir = new File JavaDoc(releaseDir, module.getName());
654             ScmVersion moduleVersion = new ScmVersion(module.getName(), module.getVersion());
655
656             StringBuffer JavaDoc msg = new StringBuffer JavaDoc();
657
658             // module name
659
msg.append(module.getName());
660             msg.append(' ');
661             while (msg.length() < 16) {
662                 msg.append(' ');
663             }
664
665             // release version
666
msg.append(moduleVersion.toString());
667             while (msg.length() < 34) {
668                 msg.append(' ');
669             }
670
671             // read local version from CVS checkout
672
ScmSystem scm = ScmSystemFactory.getScmSystemByName(module.getRepos());
673             ScmVersion localVersion = scm.getLocalVersion(moduleDir);
674
675             // display local version if <> release version
676
if (localVersion == null) {
677                 msg.append("unknown");
678             } else if (!localVersion.equals(moduleVersion)) {
679                 msg.append(localVersion.toString());
680             } else {
681                 msg.append('-');
682             }
683
684             while (msg.length() < 50) {
685                 msg.append(' ');
686             }
687
688             // display latest version
689
ScmVersion latestVersion = null;
690             if (localVersion != null && !localVersion.isTag()) {
691                 latestVersion = scm.getLatestVersion(moduleDir);
692                 if (latestVersion == null) {
693                     msg.append("unknown");
694                 } else if (!latestVersion.equals(moduleVersion)) {
695                     msg.append(latestVersion.toString());
696                 } else {
697                     msg.append('-');
698                 }
699             } else {
700                 msg.append("n/a");
701             }
702
703             while (msg.length() < 66) {
704                 msg.append(' ');
705             }
706
707             // type
708
if (localVersion == null) {
709                 msg.append("unknown");
710             } else if (localVersion.isTrunk()) {
711                 msg.append("trunk");
712             } else {
713                 if (localVersion.isBranch()) {
714                     msg.append("branch");
715                 } else {
716                     msg.append("tag");
717                 }
718             }
719             while (msg.length() < 74) {
720                 msg.append(' ');
721             }
722
723             // more info
724
if (localVersion == null || !localVersion.equals(moduleVersion)) {
725                 msg.append("Update needed");
726             } else if (localVersion.isTrunk()) {
727                 msg.append("-");
728             } else if (localVersion.isBranch()) {
729                 msg.append("-");
730             } else {
731                 msg.append("Read-only (needs 'startwork')");
732             }
733
734             // log at warning level
735
log(msg.toString(), Project.MSG_WARN);
736         }
737     }
738
739     /**
740      * Include another release.
741      *
742      * @param include the included release to distribute
743      * @param copyDistResults if true, copy the dist results of the included
744      * release to the including release, otherwise
745      * copy libraries only
746      */

747     private void include(ReleaseDescriptor.Include include, boolean copyDistResults) {
748         String JavaDoc distDirName = getProject().getProperty("antmod.release.dirs.dist");
749         File JavaDoc releaseDistDir = new File JavaDoc(releaseDir, distDirName);
750         File JavaDoc includedReleaseDir = new File JavaDoc(getProject().getProperty("antmod.checkoutdir"), include.getReleaseName());
751         File JavaDoc includedReleaseDistDir = new File JavaDoc(includedReleaseDir, distDirName);
752
753         // Define resources for next few tasks
754
String JavaDoc libsAndLicenses = "lib/**/* license/**/*";
755
756         // Copy all generated libs and their licenses to the enveloping release lib dir
757
File JavaDoc srcDir = includedReleaseDistDir;
758         File JavaDoc destDir = this.javalibExportDir;
759         destDir.mkdirs();
760
761         Copy libCopyTask = new Copy();
762         libCopyTask.setProject(getProject());
763         libCopyTask.setTaskName("include-dist");
764
765         FileSet distLibs = new FileSet();
766         distLibs.setDir(srcDir);
767         distLibs.setIncludes(libsAndLicenses);
768         libCopyTask.addFileset(distLibs);
769         libCopyTask.setFlatten(true);
770         libCopyTask.setTodir(destDir);
771
772         libCopyTask.execute();
773
774         if (copyDistResults) {
775             // Copy all remaining dist results to _dist/<included-release-basename>
776
srcDir = includedReleaseDistDir;
777             destDir = new File JavaDoc(releaseDistDir, ReleaseTask.getBaseName(include.getReleaseName()));
778             destDir.mkdirs();
779
780             Copy resourcesCopyTask = new Copy();
781             resourcesCopyTask.setProject(getProject());
782             resourcesCopyTask.setTaskName("include-dist");
783
784             FileSet distResources = new FileSet();
785             distResources.setDir(srcDir);
786             distResources.setIncludes("**/*");
787             distResources.setExcludes(libsAndLicenses);
788             resourcesCopyTask.addFileset(distResources);
789             resourcesCopyTask.setIncludeEmptyDirs(false);
790             resourcesCopyTask.setTodir(destDir);
791
792             resourcesCopyTask.execute();
793         }
794     }
795
796     /**
797      * Perform an ant task on all included releases.
798      *
799      * @param target the action to perform
800      */

801     private void antOnIncludes(String JavaDoc target) {
802         Iterator JavaDoc it = this.descriptor.getIncludes().iterator();
803         while (it.hasNext()) {
804             ReleaseDescriptor.Include include = (ReleaseDescriptor.Include) it.next();
805             antOnInclude(include, target);
806         }
807     }
808
809     /**
810      * Perform an ant task on an included release. The task will be executed
811      * from the included release dir.
812      *
813      * @param include the included release to checkout
814      * @param target the action to perform
815      */

816     private void antOnInclude(ReleaseDescriptor.Include include, String JavaDoc target) {
817         File JavaDoc includedReleaseDir = new File JavaDoc(getProject().getProperty("antmod.checkoutdir"), include.getReleaseName());
818
819         String JavaDoc execName = "ant";
820         if (SystemUtils.IS_OS_WINDOWS) {
821             execName += ".bat";
822         }
823
824         // REMIND: not respecting 'antmod.release.antfile' property here yet, need to do so...
825
ProcessLauncher launcher = new ProcessLauncher(execName + " " + target, includedReleaseDir);
826         launcher.addOutputListener(new ProcessLauncher.OutputListener() {
827             public void standardOutput(char[] output) {
828                 doLog(output);
829             }
830             public void errorOutput(char[] output) {
831                 doLog(output);
832             }
833             private void doLog(char[] output) {
834                 if (output != null) {
835                     String JavaDoc str = new String JavaDoc(output).trim();
836                     if (str.length() > 0) {
837                         log(str, Project.MSG_WARN);
838                     }
839                 }
840             }
841         });
842
843         // launch and wait until done...
844
int resultCode = launcher.launch();
845         if (resultCode != 0) {
846             throw new BuildException("Included build has FAILED");
847         }
848     }
849
850     /*
851      * Execute the specified Ant target in each of the module directories,
852      * in the order of their specification in the definition file.
853      *
854      * @param target the target to call
855      *
856      * @throws BuildException
857     private void antOnModules(String target) throws BuildException {
858         antOnModules(target, null);
859     }
860     private void antOnModules(String target, String checkChangesDir) throws BuildException {
861         Iterator moduleIter = this.descriptor.getModules().iterator();
862         while (moduleIter.hasNext()) {
863             ReleaseDescriptor.Module module = (ReleaseDescriptor.Module) moduleIter.next();
864             antOnModule(module, target, checkChangesDir);
865             getProject().log("", Project.MSG_WARN);
866         }
867     }
868     */

869
870
871     /**
872      * @param module
873      * @param target
874      */

875     private void antOnModule(ReleaseDescriptor.Module module, String JavaDoc target) {
876         antOnModule(module, target, null);
877     }
878     private void antOnModule(ReleaseDescriptor.Module module, String JavaDoc target, String JavaDoc checkChangesDir) {
879         // optionally check for changes in directory
880
if (checkChangesDir != null) {
881             if (ConditionalAnt.isExecuteNotNeeded(new File JavaDoc(releaseDir, module.getName()), target, target + "default")) {
882                 log("No changes for '" + target + "' in module: '" + module.getName() + "'", Project.MSG_WARN);
883                 return;
884             }
885         }
886
887         // do the actual antOnModule
888
Ant antTask = createAnt(target);
889         antTask.setDir(new File JavaDoc(releaseDir, module.getName()));
890         antTask.setAntfile(AntmodProperties.getProperty("antmod.module.antfile"));
891         if (module.equals(this.descriptor.getMainModule())) {
892             Property prop = antTask.createProperty();
893             prop.setName("antmod.ismainmodule");
894             prop.setValue("true");
895         }
896         if (module.equals(this.descriptor.getBuildReleaseModule())) {
897             Property prop = antTask.createProperty();
898             prop.setName("antmod.isbuildreleasemodule");
899             prop.setValue("true");
900         }
901
902         Property prop = antTask.createProperty();
903         prop.setName("antmod.release.mainmodule.name");
904         prop.setValue(this.descriptor.getMainModule().getName());
905
906         prop = antTask.createProperty();
907         prop.setName("antmod.release.mainmodule.dir");
908         prop.setValue(new File JavaDoc(releaseDir, this.descriptor.getMainModule().getName()).getPath());
909
910         //long start = System.currentTimeMillis();
911
antTask.execute();
912         //System.err.println("Time taken for 1 module: " + (System.currentTimeMillis() - start) + " ms");
913
}
914
915     /**
916      * Utility to create an empty task.
917      */

918     private Ant createAnt(String JavaDoc target) {
919         Ant antTask = new Ant();
920         antTask.setProject(getProject());
921         antTask.setTaskName(getTaskName() + "-" + target);
922         antTask.setInheritAll(true);
923         antTask.setInheritRefs(true);
924         antTask.setTarget(target);
925
926         Property prop = antTask.createProperty();
927         prop.setName("antmod.release.name");
928         prop.setValue(this.descriptor.getName());
929
930         prop = antTask.createProperty();
931         prop.setName("antmod.release.version");
932         prop.setValue(this.descriptor.getVersionString());
933
934         return antTask;
935     }
936
937     /**
938      * Deletes the given directory.
939      */

940     private void deleteDir(File JavaDoc dirFile) {
941         if (dirFile == null || !dirFile.exists()) {
942             // nothing to delete, ignore this
943
return;
944         }
945         Delete deleteTask = new Delete();
946         deleteTask.setProject(getProject());
947         deleteTask.setTaskName(getTaskName());
948         deleteTask.setDir(dirFile);
949         deleteTask.execute();
950     }
951     
952     /**
953      * Ask user whether it is okay to delete something.
954      */

955     private boolean isOkayToDelete(String JavaDoc propertyName, String JavaDoc endOfMessage) {
956         String JavaDoc deleteMode = getProject().getProperty(propertyName);
957         if ("auto".equals(deleteMode)) {
958             return true;
959         } else if ("never".equals(deleteMode)) {
960             return false;
961         } else {
962             String JavaDoc isOkay = ask("Is it okay to delete " + endOfMessage + "? ", "y,n");
963             return "y".equalsIgnoreCase(isOkay);
964         }
965     }
966
967     /**
968      * Helper method for asking a question.
969      * @param question The question to be shown to the user
970      * @param validArgs Command separated list with valid responses.
971      * @return The response to the question, matching one of the validArgs.
972      */

973     private String JavaDoc ask(String JavaDoc question, String JavaDoc validArgs) throws BuildException {
974         String JavaDoc askProperty = "org.antmod.releasetask.input.ask.internal." + (askCounter++);
975
976         Input in = new Input();
977         in.setProject(getProject());
978         in.setTaskName("input");
979         in.setMessage(question);
980         in.setValidargs(validArgs);
981         in.setAddproperty(askProperty);
982         in.execute();
983
984         return getProject().getProperty(askProperty);
985     }
986
987
988     /**
989      * Action represent an action to be performed by this task.
990      *
991      * @author Herko ter Horst
992      */

993     public static class Action extends EnumeratedAttribute {
994
995         public static String JavaDoc ISAVAILABLE = "isavailable";
996         public static String JavaDoc CHECKOUT = "checkout";
997         public static String JavaDoc UPDATE_ANT = "update-ant";
998         public static String JavaDoc DISTMODULES = "distmodules";
999         public static String JavaDoc LIST = "list";
1000
1001        private static String JavaDoc[] values =
1002            new String JavaDoc[] {
1003                ISAVAILABLE,
1004                CHECKOUT,
1005                UPDATE_ANT,
1006                DISTMODULES,
1007                LIST };
1008
1009        public String JavaDoc[] getValues() {
1010            return Action.values;
1011        }
1012    }
1013}
1014
Popular Tags