View Javadoc

1   /* -*- mode: JDE; c-basic-offset: 2; indent-tabs-mode: nil -*-
2    *
3    * $Id: SourceForgePublish.java,v 1.10 2003/07/12 16:13:24 ljnelson Exp $
4    *
5    * Copyright (c) 2003 Laird Jarrett Nelson.
6    *
7    * Permission is hereby granted, free of charge, to any person obtaining a copy
8    * of this software and associated documentation files (the "Software"), to deal
9    * in the Software without restriction, including without limitation the rights
10   * to use, copy, modify, merge, publish, distribute, sublicense and/or sell
11   * copies of the Software, and to permit persons to whom the Software is
12   * furnished to do so, subject to the following conditions:
13   *
14   * The above copyright notice and this permission notice shall be included in
15   * all copies or substantial portions of the Software.
16   *
17   * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23   * SOFTWARE.
24   *
25   * The original copy of this license is available at
26   * http://www.opensource.org/license/mit-license.html.
27   */
28  package org.apache.tools.ant.taskdefs.optional.sourceforge;
29  
30  import java.io.File;
31  
32  import java.util.Date;
33  import java.util.Enumeration;
34  import java.util.NoSuchElementException;
35  import java.util.Vector;
36  
37  import org.apache.tools.ant.BuildException;
38  import org.apache.tools.ant.Task;
39  
40  import sfutils.Administrator;
41  import sfutils.Project;
42  
43  import sfutils.frs.FileRelease;
44  import sfutils.frs.FileSpecification;
45  import sfutils.frs.Package;
46  
47  import sfutils.frs.web.HttpUnitPublisher;
48  
49  /***
50   * An <a href="http://ant.apache.org/">Ant</a> {@link Task} that makes a file
51   * release available on <a href="http://sourceforge.net/">SourceForge</a>.
52   *
53   * @author     <a href="mailto:ljnelson94@alumni.amherst.edu">Laird Nelson</a>
54   * @version    $Revision: 1.10 $ $Date: 2003/07/12 16:13:24 $
55   * @since      July 1, 2003
56   */
57  public class SourceForgePublish extends Task {
58  
59    /***
60     * The {@link FileRelease} this {@link SourceForgePublish} {@link Task} will
61     * publish.  This field will never be <code>null</code>.
62     */
63    private final FileRelease release;
64  
65    /***
66     * The {@link FileSpec}s contained by this {@link SourceForgePublish} {@link
67     * Task}.  This field will never be <code>null</code>.
68     */
69    private final Vector fileSpecs;
70  
71    /***
72     * Creates a new {@link SourceForgePublish} {@link Task}.
73     */
74    public SourceForgePublish() {
75      super();
76      this.fileSpecs = new Vector();
77      this.release = createFileReleaseShell();
78      assertNotNull(this.release);
79    }
80  
81    /***
82     * Creates a {@link FileRelease} with its associated {@link Package}, {@link
83     * Project} and {@link Administrator} set.  The resulting {@link FileRelease}
84     * is in an illegal state until it is fully configured.  This method never
85     * returns <code>null</code>.
86     *
87     * @return     a {@link FileRelease} "shell"; never <code>null</code>
88     * @see        FileRelease
89     */
90    private static final FileRelease createFileReleaseShell() {
91      final Package pkg = new Package();
92      final Project project = new Project();
93      final Administrator administrator = new Administrator();
94      final FileRelease fileRelease = new FileRelease();
95      project.setAdministrator(administrator);
96      pkg.setProject(project);
97      fileRelease.setPackage(pkg);
98      return fileRelease;
99    }
100 
101   /***
102    * Called when the <code>releasename</code> XML attribute is encountered.
103    * Sets the {@link FileRelease}'s {@linkplain FileRelease#setName(String)
104    * name}.
105    *
106    * @param      releaseName
107    *               the name for the {@link FileRelease} that will be published;
108    *               may be <code>null</code>
109    */
110   public void setReleaseName(final String releaseName) {
111     assertNotNull(this.release);
112     this.log("Setting releasename: " + releaseName);
113     this.release.setName(releaseName);
114   }
115 
116   /***
117    * Called when the <code>hidden</code> XML attribute is encountered.  Sets
118    * whether the {@link FileRelease} that will be published will be active or
119    * hidden.
120    *
121    * @param      hidden
122    *               if <code>true</code>, then the {@link FileRelease} that will
123    *               be published will not be visible
124    */
125   public void setHidden(final boolean hidden) {
126     assertNotNull(this.release);
127     this.log("Setting hidden: " + hidden);
128     this.release.setHidden(hidden);
129   }
130 
131   /***
132    * Called when the <code>packagename</code> XML attribute is encountered.
133    * Sets the {@linkplain Package#setName(String) <code>Package</code> name}.
134    *
135    * @param      packageName
136    *               the name for the {@link Package} to which the {@link
137    *               FileRelease} that will be published belongs; may be
138    *               <code>null</code>
139    */
140   publicg> void setPackageName(final String packageName) {
141     assertNotNull(this.release);
142     final Package pkg = this.release.getPackage();
143     assertNotNull(pkg);
144     this.log("Setting packagename: " + packageName);
145     pkg.setName(packageName);
146   }
147 
148   /***
149    * Called when the <code>packagehidden</code> XML attribute is encountered.
150    * Sets the {@linkplain Package#setHidden(boolean) visibility of the
151    * <code>Package</code>}.
152    *
153    * @param      hidden
154    *               if <code>true</code>, then the {@link Package} to which the
155    *               {@link FileRelease} that will be published belongs will be
156    *               marked as invisible
157    */
158   public void setPackageHidden(final boolean hidden) {
159     assertNotNull(this.release);
160     final Package pkg = this.release.getPackage();
161     assertNotNull(pkg);
162     this.log("Setting packagehidden: " + hidden);
163     pkg.setHidden(hidden);
164   }
165 
166   /***
167    * Called when the <code>projectshortname</code> XML attribute is encountered.
168    * Sets the {@linkplain Project#setShortName(String) short name of the
169    * <code>Project</code>} to which the {@link FileRelease} that will be
170    * published belongs.
171    *
172    * @param      shortName
173    *               the short name of the {@link Project} to which the {@link
174    *               FileRelease} that will be published belongs; may be
175    *               <code>null</code>
176    */
177   public void setProjectShortName(final String shortName) {
178     assertNotNull(this.release);
179     final Package pkg = this.release.getPackage();
180     assertNotNull(pkg);
181     final Project project = pkg.getProject();
182     assertNotNull(project);
183     this.log("Setting projectshortname: " + shortName);
184     project.setShortName(shortName);
185   }
186 
187   /***
188    * Called if a <code>projectlongname</code> XML attribute is encountered.
189    * Calls the {@link #setProjectName(String)} method.
190    *
191    * @param      name
192    *               the human-readable name for the {@link Project} to which the
193    *               {@link FileRelease} that will be published belongs; may be
194    *               <code>null</code>
195    */
196   public final void setProjectLongName(final String name) {
197     this.setProjectName(name);
198   }
199 
200   /***
201    * Called when the <code>projectname</code> XML attribute is encountered.
202    * Sets the human-readable {@linkplain Project#setName(String) name of the
203    * <code>Project</code>} to which the {@link FileRelease} that will be
204    * published belongs.
205    *
206    * @param      name
207    *               the human-readable {@linkplain Project#setName(String) name
208    *               of the <code>Project</code>} to which the {@link FileRelease}
209    *               that will be published belongs; may be <code>null</code>
210    */
211   public void setProjectName(final String name) {
212     assertNotNull(this.release);
213     final Package pkg = this.release.getPackage();
214     assertNotNull(pkg);
215     final Project project = pkg.getProject();
216     assertNotNull(project);
217     this.log("Setting projectname: " + name);
218     project.setName(name);
219   }
220 
221   /***
222    * Called when the <code>username</code> XML attribute is encountered.  Sets
223    * the {@linkplain Administrator#setName(String) username of the
224    * <code>Administrator</code>} that governs the {@link Project} to which the
225    * {@link FileRelease} to be published belongs.
226    *
227    * @param      userName
228    *               the name for the associated {@link Administrator}; must not
229    *               be <code>null</code>
230    * @exception  BuildException
231    *               if the supplied user name is <code>null</code>, equal to the
232    *               empty {@link String}, or consists solely of whitespace
233    */
234   public void setUserName(final String userName)
235     throws BuildException {
236     assertNotNull(this.release);
237     final Package pkg = this.release.getPackage();
238     assertNotNull(pkg);
239     final Project project = pkg.getProject();
240     assertNotNull(project);
241     final Administrator admin = project.getAdministrator();
242     assertNotNull(admin);
243     this.log("Setting username: " + userName);
244     try {
245       admin.setName(userName);
246     } catch (final IllegalArgumentException kaboom) {
247       throw new BuildException(kaboom);
248     }
249   }
250 
251   /***
252    * Called when the <code>password</code> XML attribute is encountered.  Sets
253    * the {@linkplain Administrator#setPassword(String) password of the
254    * <code>Administrator</code>} that governs the {@link Project} to which the
255    * {@link FileRelease} to be published belongs.
256    *
257    * @param      password
258    *               the name for the associated {@link Administrator}; may be
259    *               <code>null</code>
260    */
261   public void setPassword(final String password) {
262     assertNotNull(this.release);
263     final Package pkg = this.release.getPackage();
264     assertNotNull(pkg);
265     final Project project = pkg.getProject();
266     assertNotNull(project);
267     final Administrator admin = project.getAdministrator();
268     assertNotNull(admin);
269     this.log("Setting password: " + password);
270     admin.setPassword(password);
271   }
272 
273   /***
274    * Called when the <code>releasedate</code> XML attribute is encountered.
275    * Sets the {@linkplain FileRelease#setReleaseDate(Date) release date for the
276    * <code>FileRelease</code>} that will be published.
277    *
278    * @param      date
279    *               the new release {@link Date}; may be <code>null</code> in
280    *               which case the current {@link Date} will be used instead
281    */
282   public void setReleaseDate(final Date date) {
283     assertNotNull(this.release);
284     final Date actualDate;
285     if (date == null) {
286       actualDate = new Date();
287     } else {
288       actualDate = date;
289     }
290     this.log("Setting releasedate: " + actualDate);
291     this.release.setReleaseDate(actualDate);
292   }
293 
294   /***
295    * Called when the <code>notify</code> XML attribute is encountered.  Sets
296    * whether <a href="http://sourceforge.net/">SourceForge</a> users are
297    * notified when the {@link FileRelease} to be published actually is
298    * published.
299    *
300    * @param      notify
301    *               if <code>true</code>, then <a
302    *               href="http://sourceforge.net/">SourceForge</a> users will be
303    *               notified when the {@link FileRelease} to be published
304    *               actually is published 
305    */
306   public void setNotify(final boolean notify) {
307     assertNotNull(this.release);
308     this.log("Setting notify: " + notify);
309     this.release.setNotifyOthers(notify);
310   }
311 
312   /***
313    * Called when the <code>changelog</code> XML attribute is encountered.  Sets
314    * the changelog {@link File} associated with the {@link FileRelease} to be
315    * published.
316    *
317    * @param      changeLogFile
318    *               the changelog {@link File} to be associated with the {@link
319    *               FileRelease} to be published; may be <code>null</code>
320    */
321   public void setChangeLog(final File changeLogFile) {
322     assertNotNull(this.release);
323     this.log("Setting changelog: " + changeLogFile);
324     this.release.setChangeLogFile(changeLogFile);
325   }
326 
327   /***
328    * Called when the <code>releasenotes</code> XML attribute is encountered.
329    * Sets the release notes {@link File} associated with the {@link FileRelease}
330    * to be published.
331    *
332    * @param      releaseNotesFile
333    *               the release notes {@link File} to be associated with the
334    *               {@link FileRelease} to be published; may be <code>null</code>
335    */
336   public void setReleaseNotes(final File releaseNotesFile) {
337     assertNotNull(this.release);
338     this.log("Setting releasenotes: " + releaseNotesFile);
339     this.release.setReleaseNotesFile(releaseNotesFile);
340   }
341 
342   /***
343    * Called when a nested <code>filespec</code> XML element is encountered.
344    * Creates a new, unconfigured {@link FileSpec} object.  This method never
345    * returns <code>null</code>.
346    *
347    * @return     a new {@link FileSpec} object; never <code>null</code>
348    */
349   public FileSpec createFilespec() {
350     final FileSpec spec = new FileSpec();
351     this.fileSpecs.addElement(spec);
352     return spec;
353   }
354 
355   /***
356    * Ensures that the supplied {@link Administrator} is not <code>null</code>.
357    *
358    * @param      admin
359    *               the {@link Administrator} to test; may be <code>null</code>
360    *               in which case a {@link BuildException} will be thrown
361    * @exception  BuildException
362    *               if the supplied {@link Administrator} is <code>null</code>
363    */
364   private static final void assertNotNull(final Administrator admin)
365     throws BuildException {
366     if (admin == null) {
367       throw new BuildException("admin == null");
368     }
369   }
370 
371   /***
372    * Ensures that the supplied {@link Project} is not <code>null</code>.
373    *
374    * @param      project
375    *               the {@link Project} to test; may be <code>null</code> in 
376    *               which case a {@link BuildException} will be thrown
377    * @exception  BuildException
378    *               if the supplied {@link Project} is <code>null</code>
379    */
380   private static final void assertNotNull(final Project project)
381     throws BuildException {
382     if (project == null) {
383       throw new BuildException("project == null");
384     }
385   }
386 
387   /***
388    * Ensures that the supplied {@link Package} is not <code>null</code>.
389    *
390    * @param      pkg
391    *               the {@link Package} to test; may be <code>null</code> in
392    *               which case a {@link BuildException} will be thrown
393    * @exception  BuildException
394    *               if the supplied {@link Package} is <code>null</code>
395    */
396   private static final void assertNotNull(final Package pkg)
397     throws BuildException {
398     if (pkg == null) {
399       throw new BuildException("pkg == null");
400     }
401   }
402 
403   /***
404    * Ensures that the supplied {@link FileRelease} is not <code>null</code>.
405    *
406    * @param      release
407    *               the {@link FileRelease} to test; may be <code>null</code> in
408    *               which case a {@link BuildException} will be thrown
409    * @exception  BuildException
410    *               if the supplied {@link FileRelease} is <code>null</code>
411    */
412   private static final void assertNotNull(final FileRelease release)
413     throws BuildException {
414     if (release == null) {
415       throw new BuildException("release == null");
416     }
417   }
418 
419   /***
420    * Called by the <a href="http://ant.apache.org/">Ant</a> framework to execute
421    * this {@link SourceForgePublish} {@link Task}.  {@linkplain
422    * FileRelease#publish() Publishes} the {@link FileRelease} that has been
423    * configured behind the scenes by this task.
424    *
425    * @exception  BuildException
426    *               if an error occurs
427    */
428   public void execute() throws BuildException {
429     // We use Vectors and Enumerations here instead of ArrayLists and Iterators
430     // because Ant 1.5 and earlier require only JDK 1.1, which didn't have the
431     // collections classes.
432     final Vector specs = new Vector();
433     final Enumeration e = this.fileSpecs.elements();
434     if (e != null) {
435       FileSpec fileSpec;
436       FileSpecification spec;
437       while (e.hasMoreElements()) {
438         try {
439           fileSpec = (FileSpec)e.nextElement();
440           if (fileSpec == null) {
441             continue;
442           }
443         } catch (final NoSuchElementException ignore) {
444           continue;
445         } catch (final ClassCastException wontHappen) {
446           continue;
447         }
448         spec = fileSpec.getFileSpecification();
449         if (spec != null) {
450           specs.addElement(spec);
451         }
452       }
453       final FileSpecification[] specsArray = 
454         new FileSpecification[specs.size()];
455       specs.copyInto(specsArray);
456       this.release.setFileSpecifications(specsArray);
457       this.release.setPublisher(new HttpUnitPublisher());
458       try {
459         this.release.publish();
460       } catch (final Exception everything) {
461         throw new BuildException(everything);
462       }
463     }
464   }
465 }