Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 439   Methods: 14
NCLOC: 195   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ChangeLogTask.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2002 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 package org.apache.tools.ant.taskdefs.cvslib;
 55   
 
 56   
 import java.io.File;
 57   
 import java.io.FileInputStream;
 58   
 import java.io.FileOutputStream;
 59   
 import java.io.IOException;
 60   
 import java.io.OutputStreamWriter;
 61   
 import java.io.PrintWriter;
 62   
 import java.io.UnsupportedEncodingException;
 63   
 import java.text.SimpleDateFormat;
 64   
 import java.util.Date;
 65   
 import java.util.Enumeration;
 66   
 import java.util.Properties;
 67   
 import java.util.Vector;
 68   
 import org.apache.tools.ant.BuildException;
 69   
 import org.apache.tools.ant.DirectoryScanner;
 70   
 import org.apache.tools.ant.Project;
 71   
 import org.apache.tools.ant.Task;
 72   
 import org.apache.tools.ant.taskdefs.Execute;
 73   
 import org.apache.tools.ant.types.Commandline;
 74   
 import org.apache.tools.ant.types.FileSet;
 75   
 
 76   
 /**
 77   
  * Examines the output of cvs log and group related changes together.
 78   
  *
 79   
  * It produces an XML output representing the list of changes.
 80   
  * <PRE>
 81   
  * <FONT color=#0000ff>&lt;!-- Root element --&gt;</FONT>
 82   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> changelog <FONT color=#ff00ff>(entry</FONT><FONT color=#ff00ff>+</FONT><FONT color=#ff00ff>)</FONT><FONT color=#6a5acd>&gt;</FONT>
 83   
  * <FONT color=#0000ff>&lt;!-- CVS Entry --&gt;</FONT>
 84   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> entry <FONT color=#ff00ff>(date,author,file</FONT><FONT color=#ff00ff>+</FONT><FONT color=#ff00ff>,msg)</FONT><FONT color=#6a5acd>&gt;</FONT>
 85   
  * <FONT color=#0000ff>&lt;!-- Date of cvs entry --&gt;</FONT>
 86   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> date <FONT color=#ff00ff>(#PCDATA)</FONT><FONT color=#6a5acd>&gt;</FONT>
 87   
  * <FONT color=#0000ff>&lt;!-- Author of change --&gt;</FONT>
 88   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> author <FONT color=#ff00ff>(#PCDATA)</FONT><FONT color=#6a5acd>&gt;</FONT>
 89   
  * <FONT color=#0000ff>&lt;!-- List of files affected --&gt;</FONT>
 90   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> msg <FONT color=#ff00ff>(#PCDATA)</FONT><FONT color=#6a5acd>&gt;</FONT>
 91   
  * <FONT color=#0000ff>&lt;!-- File changed --&gt;</FONT>
 92   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> file <FONT color=#ff00ff>(name,revision,prevrevision</FONT><FONT color=#ff00ff>?</FONT><FONT color=#ff00ff>)</FONT><FONT color=#6a5acd>&gt;</FONT>
 93   
  * <FONT color=#0000ff>&lt;!-- Name of the file --&gt;</FONT>
 94   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> name <FONT color=#ff00ff>(#PCDATA)</FONT><FONT color=#6a5acd>&gt;</FONT>
 95   
  * <FONT color=#0000ff>&lt;!-- Revision number --&gt;</FONT>
 96   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> revision <FONT color=#ff00ff>(#PCDATA)</FONT><FONT color=#6a5acd>&gt;</FONT>
 97   
  * <FONT color=#0000ff>&lt;!-- Previous revision number --&gt;</FONT>
 98   
  * <FONT color=#6a5acd>&lt;!ELEMENT</FONT> prevrevision <FONT color=#ff00ff>(#PCDATA)</FONT><FONT color=#6a5acd>&gt;</FONT>
 99   
  * </PRE>
 100   
  *
 101   
  * @author <a href="mailto:jeff.martin@synamic.co.uk">Jeff Martin</a>
 102   
  * @author <a href="mailto:peter@apache.org">Peter Donald</a>
 103   
  * @version $Revision: 1.22 $ $Date: 2003/02/21 00:19:40 $
 104   
  * @since Ant 1.5
 105   
  * @ant.task name="cvschangelog"
 106   
  */
 107   
 public class ChangeLogTask extends Task {
 108   
     /** User list */
 109   
     private File m_usersFile;
 110   
 
 111   
     /** User list */
 112   
     private Vector m_cvsUsers = new Vector();
 113   
 
 114   
     /** Input dir */
 115   
     private File m_dir;
 116   
 
 117   
     /** Output file */
 118   
     private File m_destfile;
 119   
 
 120   
     /** The earliest date at which to start processing entrys.  */
 121   
     private Date m_start;
 122   
 
 123   
     /** The latest date at which to stop processing entrys.  */
 124   
     private Date m_stop;
 125   
 
 126   
     /**
 127   
      * Filesets containting list of files against which the cvs log will be
 128   
      * performed. If empty then all files will in the working directory will
 129   
      * be checked.
 130   
      */
 131   
     private final Vector m_filesets = new Vector();
 132   
 
 133   
 
 134   
     /**
 135   
      * Set the base dir for cvs.
 136   
      *
 137   
      * @param dir The new dir value
 138   
      */
 139  0
     public void setDir(final File dir) {
 140  0
         m_dir = dir;
 141   
     }
 142   
 
 143   
 
 144   
     /**
 145   
      * Set the output file for the log.
 146   
      *
 147   
      * @param destfile The new destfile value
 148   
      */
 149  0
     public void setDestfile(final File destfile) {
 150  0
         m_destfile = destfile;
 151   
     }
 152   
 
 153   
 
 154   
     /**
 155   
      * Set a lookup list of user names & addresses
 156   
      *
 157   
      * @param usersFile The file containing the users info.
 158   
      */
 159  0
     public void setUsersfile(final File usersFile) {
 160  0
         m_usersFile = usersFile;
 161   
     }
 162   
 
 163   
 
 164   
     /**
 165   
      * Add a user to list changelog knows about.
 166   
      *
 167   
      * @param user the user
 168   
      */
 169  0
     public void addUser(final CvsUser user) {
 170  0
         m_cvsUsers.addElement(user);
 171   
     }
 172   
 
 173   
 
 174   
     /**
 175   
      * Set the date at which the changelog should start.
 176   
      *
 177   
      * @param start The date at which the changelog should start.
 178   
      */
 179  0
     public void setStart(final Date start) {
 180  0
         m_start = start;
 181   
     }
 182   
 
 183   
 
 184   
     /**
 185   
      * Set the date at which the changelog should stop.
 186   
      *
 187   
      * @param stop The date at which the changelog should stop.
 188   
      */
 189  0
     public void setEnd(final Date stop) {
 190  0
         m_stop = stop;
 191   
     }
 192   
 
 193   
 
 194   
     /**
 195   
      * Set the number of days worth of log entries to process.
 196   
      *
 197   
      * @param days the number of days of log to process.
 198   
      */
 199  0
     public void setDaysinpast(final int days) {
 200  0
         final long time = System.currentTimeMillis()
 201   
              - (long) days * 24 * 60 * 60 * 1000;
 202   
 
 203  0
         setStart(new Date(time));
 204   
     }
 205   
 
 206   
 
 207   
     /**
 208   
      * Adds a set of files about which cvs logs will be generated.
 209   
      *
 210   
      * @param fileSet a set of files about which cvs logs will be generated.
 211   
      */
 212  0
     public void addFileset(final FileSet fileSet) {
 213  0
         m_filesets.addElement(fileSet);
 214   
     }
 215   
 
 216   
 
 217   
     /**
 218   
      * Execute task
 219   
      *
 220   
      * @exception BuildException if something goes wrong executing the
 221   
      *            cvs command
 222   
      */
 223  0
     public void execute() throws BuildException {
 224  0
         File savedDir = m_dir;// may be altered in validate
 225   
 
 226  0
         try {
 227   
 
 228  0
             validate();
 229   
 
 230  0
             final Properties userList = new Properties();
 231   
 
 232  0
             loadUserlist(userList);
 233   
 
 234  0
             for (Enumeration e = m_cvsUsers.elements();
 235  0
                 e.hasMoreElements();) {
 236  0
                 final CvsUser user = (CvsUser) e.nextElement();
 237   
 
 238  0
                 user.validate();
 239  0
                 userList.put(user.getUserID(), user.getDisplayname());
 240   
             }
 241   
 
 242  0
             final Commandline command = new Commandline();
 243   
 
 244  0
             command.setExecutable("cvs");
 245  0
             command.createArgument().setValue("log");
 246   
 
 247  0
             if (null != m_start) {
 248  0
                 final SimpleDateFormat outputDate =
 249   
                     new SimpleDateFormat("yyyy-MM-dd");
 250   
 
 251   
                 // We want something of the form: -d ">=YYYY-MM-dd"
 252  0
                 final String dateRange = ">=" + outputDate.format(m_start);
 253   
 
 254   
         // Supply '-d' as a separate argument - Bug# 14397
 255  0
                 command.createArgument().setValue("-d");
 256  0
                 command.createArgument().setValue(dateRange);
 257   
             }
 258   
 
 259   
             // Check if list of files to check has been specified
 260  0
             if (!m_filesets.isEmpty()) {
 261  0
                 final Enumeration e = m_filesets.elements();
 262   
 
 263  0
                 while (e.hasMoreElements()) {
 264  0
                     final FileSet fileSet = (FileSet) e.nextElement();
 265  0
                     final DirectoryScanner scanner =
 266   
                         fileSet.getDirectoryScanner(getProject());
 267  0
                     final String[] files = scanner.getIncludedFiles();
 268   
 
 269  0
                     for (int i = 0; i < files.length; i++) {
 270  0
                         command.createArgument().setValue(files[i]);
 271   
                     }
 272   
                 }
 273   
             }
 274   
 
 275  0
             final ChangeLogParser parser = new ChangeLogParser();
 276  0
             final RedirectingStreamHandler handler =
 277   
                 new RedirectingStreamHandler(parser);
 278   
 
 279  0
             log(command.describeCommand(), Project.MSG_VERBOSE);
 280   
 
 281  0
             final Execute exe = new Execute(handler);
 282   
 
 283  0
             exe.setWorkingDirectory(m_dir);
 284  0
             exe.setCommandline(command.getCommandline());
 285  0
             exe.setAntRun(getProject());
 286  0
             try {
 287  0
                 final int resultCode = exe.execute();
 288   
 
 289  0
                 if (0 != resultCode) {
 290  0
                     throw new BuildException("Error running cvs log");
 291   
                 }
 292   
             } catch (final IOException ioe) {
 293  0
                 throw new BuildException(ioe.toString());
 294   
             }
 295   
 
 296  0
             final String errors = handler.getErrors();
 297   
 
 298  0
             if (null != errors) {
 299  0
                 log(errors, Project.MSG_ERR);
 300   
             }
 301   
 
 302  0
             final CVSEntry[] entrySet = parser.getEntrySetAsArray();
 303  0
             final CVSEntry[] filteredEntrySet = filterEntrySet(entrySet);
 304   
 
 305  0
             replaceAuthorIdWithName(userList, filteredEntrySet);
 306   
 
 307  0
             writeChangeLog(filteredEntrySet);
 308   
 
 309   
         } finally {
 310  0
             m_dir = savedDir;
 311   
         }
 312   
     }
 313   
 
 314   
     /**
 315   
      * Validate the parameters specified for task.
 316   
      *
 317   
      * @throws BuildException if fails validation checks
 318   
      */
 319  0
     private void validate()
 320   
          throws BuildException {
 321  0
         if (null == m_dir) {
 322  0
             m_dir = getProject().getBaseDir();
 323   
         }
 324  0
         if (null == m_destfile) {
 325  0
             final String message = "Destfile must be set.";
 326   
 
 327  0
             throw new BuildException(message);
 328   
         }
 329  0
         if (!m_dir.exists()) {
 330  0
             final String message = "Cannot find base dir "
 331   
                  + m_dir.getAbsolutePath();
 332   
 
 333  0
             throw new BuildException(message);
 334   
         }
 335  0
         if (null != m_usersFile && !m_usersFile.exists()) {
 336  0
             final String message = "Cannot find user lookup list "
 337   
                  + m_usersFile.getAbsolutePath();
 338   
 
 339  0
             throw new BuildException(message);
 340   
         }
 341   
     }
 342   
 
 343   
     /**
 344   
      * Load the userlist from the userList file (if specified) and add to
 345   
      * list of users.
 346   
      *
 347   
      * @param userList the file of users
 348   
      * @throws BuildException if file can not be loaded for some reason
 349   
      */
 350  0
     private void loadUserlist(final Properties userList)
 351   
          throws BuildException {
 352  0
         if (null != m_usersFile) {
 353  0
             try {
 354  0
                 userList.load(new FileInputStream(m_usersFile));
 355   
             } catch (final IOException ioe) {
 356  0
                 throw new BuildException(ioe.toString(), ioe);
 357   
             }
 358   
         }
 359   
     }
 360   
 
 361   
     /**
 362   
      * Filter the specified entrys accoridn to an appropriate rule.
 363   
      *
 364   
      * @param entrySet the entry set to filter
 365   
      * @return the filtered entry set
 366   
      */
 367  0
     private CVSEntry[] filterEntrySet(final CVSEntry[] entrySet) {
 368  0
         final Vector results = new Vector();
 369   
 
 370  0
         for (int i = 0; i < entrySet.length; i++) {
 371  0
             final CVSEntry cvsEntry = entrySet[i];
 372  0
             final Date date = cvsEntry.getDate();
 373   
 
 374  0
             if (null != m_start && m_start.after(date)) {
 375   
                 //Skip dates that are too early
 376  0
                 continue;
 377   
             }
 378  0
             if (null != m_stop && m_stop.before(date)) {
 379   
                 //Skip dates that are too late
 380  0
                 continue;
 381   
             }
 382  0
             results.addElement(cvsEntry);
 383   
         }
 384   
 
 385  0
         final CVSEntry[] resultArray = new CVSEntry[results.size()];
 386   
 
 387  0
         results.copyInto(resultArray);
 388  0
         return resultArray;
 389   
     }
 390   
 
 391   
     /**
 392   
      * replace all known author's id's with their maven specified names
 393   
      */
 394  0
     private void replaceAuthorIdWithName(final Properties userList,
 395   
                                          final CVSEntry[] entrySet) {
 396  0
         for (int i = 0; i < entrySet.length; i++) {
 397   
 
 398  0
             final CVSEntry entry = entrySet[ i ];
 399  0
             if (userList.containsKey(entry.getAuthor())) {
 400  0
                 entry.setAuthor(userList.getProperty(entry.getAuthor()));
 401   
             }
 402   
         }
 403   
     }
 404   
 
 405   
     /**
 406   
      * Print changelog to file specified in task.
 407   
      *
 408   
      * @param entrySet the entry set to write.
 409   
      * @throws BuildException if theres an error writing changelog.
 410   
      */
 411  0
     private void writeChangeLog(final CVSEntry[] entrySet)
 412   
          throws BuildException {
 413  0
         FileOutputStream output = null;
 414   
 
 415  0
         try {
 416  0
             output = new FileOutputStream(m_destfile);
 417   
 
 418  0
             final PrintWriter writer =
 419   
                 new PrintWriter(new OutputStreamWriter(output, "UTF-8"));
 420   
 
 421  0
             final ChangeLogWriter serializer = new ChangeLogWriter();
 422   
 
 423  0
             serializer.printChangeLog(writer, entrySet);
 424   
         } catch (final UnsupportedEncodingException uee) {
 425  0
             getProject().log(uee.toString(), Project.MSG_ERR);
 426   
         } catch (final IOException ioe) {
 427  0
             throw new BuildException(ioe.toString(), ioe);
 428   
         } finally {
 429  0
             if (null != output) {
 430  0
                 try {
 431  0
                     output.close();
 432   
                 } catch (final IOException ioe) {
 433   
                 }
 434   
             }
 435   
         }
 436   
     }
 437   
 }
 438   
 
 439