public void testCvs112Format() throws Exception {
   parser.stdout("Working file: build.xml");
   parser.stdout("revision 1.475");
   parser.stdout("date: 2004-06-05 16:10:32 +0000; author: somebody; state: Exp;  lines: +2 -2");
   parser.stdout("I have done something. I swear.");
   parser.stdout("=============================================================================");
   CVSEntry[] entries = parser.getEntrySetAsArray();
   assertEquals("somebody", entries[0].getAuthor());
   Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US);
   cal.set(Calendar.MILLISECOND, 0);
   cal.set(2004, Calendar.JUNE, 5, 16, 10, 32);
   Date date = cal.getTime();
   assertEquals(date, entries[0].getDate());
 }
  /**
   * Execute task
   *
   * @exception BuildException if something goes wrong executing the cvs command
   */
  public void execute() throws BuildException {
    File savedDir = inputDir; // may be altered in validate

    try {

      validate();
      final Properties userList = new Properties();

      loadUserlist(userList);

      final int size = cvsUsers.size();
      for (int i = 0; i < size; i++) {
        final CvsUser user = (CvsUser) cvsUsers.get(i);
        user.validate();
        userList.put(user.getUserID(), user.getDisplayname());
      }

      if (!remote) {
        setCommand("log");

        if (getTag() != null) {
          CvsVersion myCvsVersion = new CvsVersion();
          myCvsVersion.setProject(getProject());
          myCvsVersion.setTaskName("cvsversion");
          myCvsVersion.setCvsRoot(getCvsRoot());
          myCvsVersion.setCvsRsh(getCvsRsh());
          myCvsVersion.setPassfile(getPassFile());
          myCvsVersion.setDest(inputDir);
          myCvsVersion.execute();
          if (myCvsVersion.supportsCvsLogWithSOption()) {
            addCommandArgument("-S");
          }
        }
      } else {
        // supply 'rlog' as argument instead of command
        setCommand("");
        addCommandArgument("rlog");
        // Do not print name/header if no revisions
        // selected. This is quicker: less output to parse.
        addCommandArgument("-S");
        // Do not list tags. This is quicker: less output to
        // parse.
        addCommandArgument("-N");
      }
      if (null != startTag || null != endTag) {
        // man, do I get spoiled by C#'s ?? operator
        String startValue = startTag == null ? "" : startTag;
        String endValue = endTag == null ? "" : endTag;
        addCommandArgument("-r" + startValue + "::" + endValue);
      } else if (null != startDate) {
        final SimpleDateFormat outputDate = new SimpleDateFormat("yyyy-MM-dd");

        // We want something of the form: -d ">=YYYY-MM-dd"
        final String dateRange = ">=" + outputDate.format(startDate);

        // Supply '-d' as a separate argument - Bug# 14397
        addCommandArgument("-d");
        addCommandArgument(dateRange);
      }

      // Check if list of files to check has been specified
      if (!filesets.isEmpty()) {
        final Enumeration e = filesets.elements();

        while (e.hasMoreElements()) {
          final FileSet fileSet = (FileSet) e.nextElement();
          final DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject());
          final String[] files = scanner.getIncludedFiles();

          for (int i = 0; i < files.length; i++) {
            addCommandArgument(files[i]);
          }
        }
      }

      final ChangeLogParser parser = new ChangeLogParser(remote, getPackage(), getModules());
      final RedirectingStreamHandler handler = new RedirectingStreamHandler(parser);

      log(getCommand(), Project.MSG_VERBOSE);

      setDest(inputDir);
      setExecuteStreamHandler(handler);
      try {
        super.execute();
      } finally {
        final String errors = handler.getErrors();

        if (null != errors) {
          log(errors, Project.MSG_ERR);
        }
      }
      final CVSEntry[] entrySet = parser.getEntrySetAsArray();
      final CVSEntry[] filteredEntrySet = filterEntrySet(entrySet);

      replaceAuthorIdWithName(userList, filteredEntrySet);

      writeChangeLog(filteredEntrySet);

    } finally {
      inputDir = savedDir;
    }
  }