diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java | 489 |
1 files changed, 489 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java new file mode 100644 index 00000000..b4b51ced --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java @@ -0,0 +1,489 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.tools.ant.taskdefs.cvslib; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Enumeration; +import java.util.Properties; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.AbstractCvsTask; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.util.FileUtils; + +/** + * Examines the output of cvs log and group related changes together. + * + * It produces an XML output representing the list of changes. + * <pre> + * <font color=#0000ff><!-- Root element --></font> + * <font color=#6a5acd><!ELEMENT</font> changelog <font color=#ff00ff> + * (entry</font><font color=#ff00ff>+</font><font color=#ff00ff>) + * </font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- CVS Entry --></font> + * <font color=#6a5acd><!ELEMENT</font> entry <font color=#ff00ff> + * (date,author,file</font><font color=#ff00ff>+</font><font color=#ff00ff>,msg) + * </font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- Date of cvs entry --></font> + * <font color=#6a5acd><!ELEMENT</font> date <font color=#ff00ff>(#PCDATA) + * </font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- Author of change --></font> + * <font color=#6a5acd><!ELEMENT</font> author <font color=#ff00ff>(#PCDATA) + * </font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- List of files affected --></font> + * <font color=#6a5acd><!ELEMENT</font> msg <font color=#ff00ff>(#PCDATA) + * </font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- File changed --></font> + * <font color=#6a5acd><!ELEMENT</font> file <font color=#ff00ff> + * (name,revision,prevrevision</font><font color=#ff00ff>?</font> + * <font color=#ff00ff>)</font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- Name of the file --></font> + * <font color=#6a5acd><!ELEMENT</font> name <font color=#ff00ff>(#PCDATA) + * </font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- Revision number --></font> + * <font color=#6a5acd><!ELEMENT</font> revision <font color=#ff00ff> + * (#PCDATA)</font><font color=#6a5acd>></font> + * <font color=#0000ff><!-- Previous revision number --></font> + * <font color=#6a5acd><!ELEMENT</font> prevrevision <font color=#ff00ff> + * (#PCDATA)</font><font color=#6a5acd>></font> + * </pre> + * + * @since Ant 1.5 + * @ant.task name="cvschangelog" category="scm" + */ +public class ChangeLogTask extends AbstractCvsTask { + /** User list */ + private File usersFile; + + /** User list */ + private Vector cvsUsers = new Vector(); + + /** Input dir */ + private File inputDir; + + /** Output file */ + private File destFile; + + /** The earliest date at which to start processing entries. */ + private Date startDate; + + /** The latest date at which to stop processing entries. */ + private Date endDate; + + /** Determines whether log (false) or rlog (true) is used */ + private boolean remote = false; + + /** Start tag when doing tag ranges. */ + private String startTag; + + /** End tag when doing tag ranges. */ + private String endTag; + + /** + * Filesets containing list of files against which the cvs log will be + * performed. If empty then all files in the working directory will + * be checked. + */ + private final Vector filesets = new Vector(); + + + /** + * Set the base dir for cvs. + * + * @param inputDir The new dir value + */ + public void setDir(final File inputDir) { + this.inputDir = inputDir; + } + + + /** + * Set the output file for the log. + * + * @param destFile The new destfile value + */ + public void setDestfile(final File destFile) { + this.destFile = destFile; + } + + + /** + * Set a lookup list of user names & addresses + * + * @param usersFile The file containing the users info. + */ + public void setUsersfile(final File usersFile) { + this.usersFile = usersFile; + } + + + /** + * Add a user to list changelog knows about. + * + * @param user the user + */ + public void addUser(final CvsUser user) { + cvsUsers.addElement(user); + } + + + /** + * Set the date at which the changelog should start. + * + * @param start The date at which the changelog should start. + */ + public void setStart(final Date start) { + this.startDate = start; + } + + + /** + * Set the date at which the changelog should stop. + * + * @param endDate The date at which the changelog should stop. + */ + public void setEnd(final Date endDate) { + this.endDate = endDate; + } + + + /** + * Set the number of days worth of log entries to process. + * + * @param days the number of days of log to process. + */ + public void setDaysinpast(final int days) { + // CheckStyle:MagicNumber OFF + final long time = System.currentTimeMillis() + - (long) days * 24 * 60 * 60 * 1000; + // CheckStyle:MagicNumber ON + + setStart(new Date(time)); + } + + /** + * Whether to use rlog against a remote repository instead of log + * in a working copy's directory. + * + * @since Ant 1.8.0 + */ + public void setRemote(final boolean remote) { + this.remote = remote; + } + + /** + * Set the tag at which the changelog should start. + * + * @param start The date at which the changelog should start. + */ + public void setStartTag(final String start) { + this.startTag = start; + } + + + /** + * Set the tag at which the changelog should stop. + * + * @param end The date at which the changelog should stop. + */ + public void setEndTag(final String end) { + this.endTag = end; + } + + /** + * Adds a set of files about which cvs logs will be generated. + * + * @param fileSet a set of files about which cvs logs will be generated. + */ + public void addFileset(final FileSet fileSet) { + filesets.addElement(fileSet); + } + + + /** + * 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; + } + } + + /** + * Validate the parameters specified for task. + * + * @throws BuildException if fails validation checks + */ + private void validate() + throws BuildException { + if (null == inputDir) { + inputDir = getProject().getBaseDir(); + } + if (null == destFile) { + final String message = "Destfile must be set."; + + throw new BuildException(message); + } + if (!inputDir.exists()) { + final String message = "Cannot find base dir " + + inputDir.getAbsolutePath(); + + throw new BuildException(message); + } + if (null != usersFile && !usersFile.exists()) { + final String message = "Cannot find user lookup list " + + usersFile.getAbsolutePath(); + + throw new BuildException(message); + } + if ((null != startTag || null != endTag) + && (null != startDate || null != endDate)) { + final String message = "Specify either a tag or date range," + + " not both"; + throw new BuildException(message); + } + } + + /** + * Load the userlist from the userList file (if specified) and add to + * list of users. + * + * @param userList the file of users + * @throws BuildException if file can not be loaded for some reason + */ + private void loadUserlist(final Properties userList) + throws BuildException { + if (null != usersFile) { + try { + userList.load(new FileInputStream(usersFile)); + } catch (final IOException ioe) { + throw new BuildException(ioe.toString(), ioe); + } + } + } + + /** + * Filter the specified entries according to an appropriate rule. + * + * @param entrySet the entry set to filter + * @return the filtered entry set + */ + private CVSEntry[] filterEntrySet(final CVSEntry[] entrySet) { + final Vector results = new Vector(); + + for (int i = 0; i < entrySet.length; i++) { + final CVSEntry cvsEntry = entrySet[i]; + final Date date = cvsEntry.getDate(); + + //bug#30471 + //this is caused by Date.after throwing a NullPointerException + //for some reason there's no date set in the CVSEntry + //Java 1.3.1 API + //http://java.sun.com/j2se/1.3/docs/api/java/util/Date.html#after(java.util.Date) + //doesn't throw NullPointerException + //Java 1.4.2 + 1.5 API + //http://java.sun.com/j2se/1.4.2/docs/api/java/util/Date.html#after(java.util.Date) + //according to the docs it doesn't throw, according to the bug report it does + //http://java.sun.com/j2se/1.5.0/docs/api/java/util/Date.html#after(java.util.Date) + //according to the docs it does throw + + //for now skip entries which are missing a date + if (null == date) { + continue; + } + + if (null != startDate && startDate.after(date)) { + //Skip dates that are too early + continue; + } + if (null != endDate && endDate.before(date)) { + //Skip dates that are too late + continue; + } + results.addElement(cvsEntry); + } + + final CVSEntry[] resultArray = new CVSEntry[results.size()]; + + results.copyInto(resultArray); + return resultArray; + } + + /** + * replace all known author's id's with their maven specified names + */ + private void replaceAuthorIdWithName(final Properties userList, + final CVSEntry[] entrySet) { + for (int i = 0; i < entrySet.length; i++) { + + final CVSEntry entry = entrySet[ i ]; + if (userList.containsKey(entry.getAuthor())) { + entry.setAuthor(userList.getProperty(entry.getAuthor())); + } + } + } + + /** + * Print changelog to file specified in task. + * + * @param entrySet the entry set to write. + * @throws BuildException if there is an error writing changelog. + */ + private void writeChangeLog(final CVSEntry[] entrySet) + throws BuildException { + FileOutputStream output = null; + + try { + output = new FileOutputStream(destFile); + + final PrintWriter writer = + new PrintWriter(new OutputStreamWriter(output, "UTF-8")); + + final ChangeLogWriter serializer = new ChangeLogWriter(); + + serializer.printChangeLog(writer, entrySet); + + if (writer.checkError()) { + throw new IOException("Encountered an error writing changelog"); + } + } catch (final UnsupportedEncodingException uee) { + getProject().log(uee.toString(), Project.MSG_ERR); + } catch (final IOException ioe) { + throw new BuildException(ioe.toString(), ioe); + } finally { + FileUtils.close(output); + } + } +} + |