diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java
new file mode 100644
index 000000000..c622d2e88
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CVSEntry.java
@@ -0,0 +1,114 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.cvslib;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+/**
+ * CVS Entry.
+ *
+ * @author Jeff Martin
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ */
+class CVSEntry
+{
+ private Date m_date;
+ private final String m_author;
+ private final String m_comment;
+ private final ArrayList m_files = new ArrayList();
+
+ public CVSEntry( Date date, String author, String comment )
+ {
+ m_date = date;
+ m_author = author;
+ m_comment = comment;
+ }
+
+ public void addFile( String file, String revision )
+ {
+ m_files.add( new RCSFile( file, revision ) );
+ }
+
+ public void addFile( String file, String revision, String previousRevision )
+ {
+ m_files.add( new RCSFile( file, revision, previousRevision ) );
+ }
+
+ Date getDate()
+ {
+ return m_date;
+ }
+
+ String getAuthor()
+ {
+ return m_author;
+ }
+
+ String getComment()
+ {
+ return m_comment;
+ }
+
+ ArrayList getFiles()
+ {
+ return m_files;
+ }
+
+ public String toString()
+ {
+ return getAuthor() + "\n" + getDate() + "\n" + getFiles() + "\n" + getComment();
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java
new file mode 100644
index 000000000..6c6b2a3b0
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogParser.java
@@ -0,0 +1,281 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.cvslib;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Properties;
+
+/**
+ * A class used to parse the output of the CVS log command.
+ *
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ */
+class ChangeLogParser
+{
+ //private static final int GET_ENTRY = 0;
+ private static final int GET_FILE = 1;
+ private static final int GET_DATE = 2;
+ private static final int GET_COMMENT = 3;
+ private static final int GET_REVISION = 4;
+ private static final int GET_PREVIOUS_REV = 5;
+
+ /** input format for dates read in from cvs log */
+ private static final SimpleDateFormat c_inputDate = new SimpleDateFormat( "yyyy/MM/dd" );
+
+ //The following is data used while processing stdout of CVS command
+ private String m_file;
+ private String m_date;
+ private String m_author;
+ private String m_comment;
+ private String m_revision;
+ private String m_previousRevision;
+
+ private int m_status = GET_FILE;
+
+ /** rcs entries */
+ private final Hashtable m_entries = new Hashtable();
+
+ private final Properties m_userList;
+
+ /**
+ * Construct a parser that uses specified user list.
+ *
+ * @param userList the userlist
+ */
+ public ChangeLogParser( Properties userList )
+ {
+ m_userList = userList;
+ }
+
+ /**
+ * Get a list of rcs entrys as an array.
+ *
+ * @return a list of rcs entrys as an array
+ */
+ CVSEntry[] getEntrySetAsArray()
+ {
+ final CVSEntry[] array = new CVSEntry[ m_entries.values().size() ];
+ return (CVSEntry[])m_entries.values().toArray( array );
+ }
+
+ /**
+ * Receive notification about the process writing
+ * to standard output.
+ */
+ public void stdout( final String line )
+ {
+ switch( m_status )
+ {
+ case GET_FILE:
+ processFile( line );
+ break;
+ case GET_REVISION:
+ processRevision( line );
+ //Was a fall through ....
+ //break;
+ case GET_DATE:
+ processDate( line );
+ break;
+
+ case GET_COMMENT:
+ processComment( line );
+ break;
+
+ case GET_PREVIOUS_REV:
+ processGetPreviousRevision( line );
+ break;
+ }
+ }
+
+ /**
+ * Process a line while in "GET_COMMENT" state.
+ *
+ * @param line the line
+ */
+ private void processComment( final String line )
+ {
+ final String lineSeparator = System.getProperty( "line.separator" );
+ if( line.startsWith( "======" ) || line.startsWith( "------" ) )
+ {
+ final int end = m_comment.length() - lineSeparator.length(); //was -1
+ m_comment = m_comment.substring( 0, end );
+ m_comment = "";
+ m_status = GET_PREVIOUS_REV;
+ }
+ else
+ {
+ m_comment += line + lineSeparator;
+ }
+ }
+
+ /**
+ * Process a line while in "GET_FILE" state.
+ *
+ * @param line the line
+ */
+ private void processFile( final String line )
+ {
+ if( line.startsWith( "Working file:" ) )
+ {
+ m_file = line.substring( 14, line.length() );
+ m_status = GET_REVISION;
+ }
+ }
+
+ /**
+ * Process a line while in "REVISION" state.
+ *
+ * @param line the line
+ */
+ private void processRevision( final String line )
+ {
+ if( line.startsWith( "revision" ) )
+ {
+ m_revision = line.substring( 9 );
+ m_status = GET_DATE;
+ }
+ }
+
+ /**
+ * Process a line while in "DATE" state.
+ *
+ * @param line the line
+ */
+ private void processDate( final String line )
+ {
+ if( line.startsWith( "date:" ) )
+ {
+ m_date = line.substring( 6, 16 );
+ String lineData = line.substring( line.indexOf( ";" ) + 1 );
+ m_author = lineData.substring( 10, lineData.indexOf( ";" ) );
+
+ if( m_userList.containsKey( m_author ) )
+ {
+ m_author = "";
+ }
+
+ m_status = GET_COMMENT;
+
+ //Reset comment to empty here as we can accumulate multiple lines
+ //in the processComment method
+ m_comment = "";
+ }
+ }
+
+ /**
+ * Process a line while in "GET_PREVIOUS_REVISION" state.
+ *
+ * @param line the line
+ */
+ private void processGetPreviousRevision( final String line )
+ {
+ final String entryKey = m_date + m_author + m_comment;
+ if( line.startsWith( "revision" ) )
+ {
+ m_previousRevision = line.substring( 9 );
+ m_status = GET_FILE;
+
+ CVSEntry entry;
+ if( !m_entries.containsKey( entryKey ) )
+ {
+ entry = new CVSEntry( parseDate( m_date ), m_author, m_comment );
+ m_entries.put( entryKey, entry );
+ }
+ else
+ {
+ entry = (CVSEntry)m_entries.get( entryKey );
+ }
+ entry.addFile( m_file, m_revision, m_previousRevision );
+ }
+ else if( line.startsWith( "======" ) )
+ {
+ m_status = GET_FILE;
+ CVSEntry entry;
+ if( !m_entries.containsKey( entryKey ) )
+ {
+ entry = new CVSEntry( parseDate( m_date ), m_author, m_comment );
+ m_entries.put( entryKey, entry );
+ }
+ else
+ {
+ entry = (CVSEntry)m_entries.get( entryKey );
+ }
+ entry.addFile( m_file, m_revision );
+ }
+ }
+
+ /**
+ * Parse date out from expected format.
+ *
+ * @param date the string holding dat
+ * @return the date object or null if unknown date format
+ */
+ private Date parseDate( final String date )
+ {
+ try
+ {
+ return c_inputDate.parse( date );
+ }
+ catch( ParseException e )
+ {
+ //final String message = REZ.getString( "changelog.bat-date.error", date );
+ //getContext().error( message );
+ return null;
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java
new file mode 100644
index 000000000..7788d9fe4
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogTask.java
@@ -0,0 +1,353 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+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.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.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Execute;
+import org.apache.tools.ant.types.Commandline;
+
+/**
+ * Change log task.
+ * The task will examine the output of cvs log and group related changes together.
+ * It produces an XML output representing the list of changes.
+ *
+ * <!-- Root element -->
+ * <!ELEMENT changelog (entry+)>
+ * <!-- CVS Entry -->
+ * <!ELEMENT entry (date,author,file+,msg)>
+ * <!-- Date of cvs entry -->
+ * <!ELEMENT date (#PCDATA)>
+ * <!-- Author of change -->
+ * <!ELEMENT author (#PCDATA)>
+ * <!-- List of files affected -->
+ * <!ELEMENT msg (#PCDATA)>
+ * <!-- File changed -->
+ * <!ELEMENT file (name,revision,prevrevision?)>
+ * <!-- Name of the file -->
+ * <!ELEMENT name (#PCDATA)>
+ * <!-- Revision number -->
+ * <!ELEMENT revision (#PCDATA)>
+ * <!-- Previous revision number -->
+ * <!ELEMENT prevrevision (#PCDATA)>
+ *
+ *
+ * @author Jeff Martin
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ * @ant.task name="changelog"
+ */
+public class ChangeLogTask
+ extends Task
+{
+ /** User list */
+ private File m_usersFile;
+
+ /** User list */
+ private Vector m_cvsUsers = new Vector();
+
+ /** Input dir */
+ private File m_basedir;
+
+ /** Output file */
+ private File m_destfile;
+
+ /**
+ * The earliest date at which to start processing entrys.
+ */
+ private Date m_start;
+
+ /**
+ * The latest date at which to stop processing entrys.
+ */
+ private Date m_stop;
+
+ /**
+ * Set the base dir for cvs.
+ */
+ public void setBasedir( final File basedir )
+ {
+ m_basedir = basedir;
+ }
+
+ /**
+ * Set the output file for the log.
+ */
+ public void setDestfile( final File destfile )
+ {
+ m_destfile = destfile;
+ }
+
+ /**
+ * Set a lookup list of user names & addresses
+ */
+ public void setUsersfile( final File usersFile )
+ {
+ m_usersFile = usersFile;
+ }
+
+ /**
+ * Add a user to list changelog knows about.
+ *
+ * @param user the user
+ */
+ public void addUser( final CvsUser user )
+ {
+ m_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 )
+ {
+ m_start = start;
+ }
+
+ /**
+ * Set the date at which the changelog should stop.
+ *
+ * @param stop The date at which the changelog should stop.
+ */
+ public void setEnd( final Date stop )
+ {
+ m_stop = stop;
+ }
+
+ /**
+ * Execute task
+ */
+ public void execute() throws BuildException
+ {
+ validate();
+
+ final Properties userList = new Properties();
+
+ loadUserlist( userList );
+
+ for( Enumeration e = m_cvsUsers.elements(); e.hasMoreElements(); )
+ {
+ final CvsUser user = (CvsUser)e.nextElement();
+ user.validate();
+ userList.put( user.getUserID(), user.getDisplayname() );
+ }
+
+ final Commandline command = new Commandline();
+ command.setExecutable( "cvs" );
+ command.createArgument().setValue( "log" );
+
+ final ChangeLogParser parser = new ChangeLogParser( userList );
+ final RedirectingStreamHandler handler =
+ new RedirectingStreamHandler( parser );
+ final Execute exe = new Execute( handler );
+ exe.setWorkingDirectory( m_basedir );
+ exe.setCommandline( command.getCommandline() );
+ exe.setAntRun( getProject() );
+ try
+ {
+ final int resultCode = exe.execute();
+ if( 0 != resultCode )
+ {
+ throw new BuildException( "Error running cvs log" );
+ }
+ }
+ catch( final IOException ioe )
+ {
+ throw new BuildException( ioe.toString() );
+ }
+
+ final CVSEntry[] entrySet = parser.getEntrySetAsArray();
+ final CVSEntry[] filteredEntrySet = filterEntrySet( entrySet );
+ writeChangeLog( filteredEntrySet );
+ }
+
+ /**
+ * Validate the parameters specified for task.
+ *
+ * @throws BuildException if fails validation checks
+ */
+ private void validate()
+ throws BuildException
+ {
+ if( null == m_basedir )
+ {
+ final String message = "Basedir must be set.";
+ throw new BuildException( message );
+ }
+ if( null == m_destfile )
+ {
+ final String message = "Destfile must be set.";
+ throw new BuildException( message );
+ }
+ if( !m_basedir.exists() )
+ {
+ final String message = "Cannot find base dir " + m_basedir.getAbsolutePath();
+ throw new BuildException( message );
+ }
+ if( null != m_usersFile && !m_usersFile.exists() )
+ {
+ final String message = "Cannot find user lookup list " + m_usersFile.getAbsolutePath();
+ throw new BuildException( message );
+ }
+ }
+
+ /**
+ * Load the userli4st from the userList file (if specified) and
+ * add to list of users.
+ *
+ * @throws BuildException if file can not be loaded for some reason
+ */
+ private void loadUserlist( final Properties userList )
+ throws BuildException
+ {
+ if( null != m_usersFile )
+ {
+ try
+ {
+ userList.load( new FileInputStream( m_usersFile ) );
+ }
+ catch( final IOException ioe )
+ {
+ throw new BuildException( ioe.toString(), ioe );
+ }
+ }
+ }
+
+ /**
+ * Filter the specified entrys accoridn 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();
+ if( null != m_start && m_start.after( date ) )
+ {
+ //Skip dates that are too early
+ continue;
+ }
+ if( null != m_stop && m_stop.before( date ) )
+ {
+ //Skip dates that are too late
+ continue;
+ }
+ results.add( cvsEntry );
+ }
+
+ final CVSEntry[] resultArray = new CVSEntry[ results.size() ];
+ results.copyInto( resultArray );
+ return resultArray;
+ }
+
+ /**
+ * Print changelog to file specified in task.
+ *
+ * @throws BuildException if theres an error writing changelog
+ */
+ private void writeChangeLog( final CVSEntry[] entrySet )
+ throws BuildException
+ {
+ FileOutputStream output = null;
+ try
+ {
+ output = new FileOutputStream( m_destfile );
+ final PrintWriter writer =
+ new PrintWriter( new OutputStreamWriter( output, "UTF-8" ) );
+
+ final ChangeLogWriter serializer = new ChangeLogWriter();
+ serializer.printChangeLog( writer, entrySet );
+ }
+ catch( final UnsupportedEncodingException uee )
+ {
+ getProject().log( uee.toString(), Project.MSG_ERR );
+ }
+ catch( final IOException ioe )
+ {
+ throw new BuildException( ioe.toString(), ioe );
+ }
+ finally
+ {
+ if( null != output )
+ {
+ try
+ {
+ output.close();
+ }
+ catch( final IOException ioe )
+ {
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java
new file mode 100644
index 000000000..29591df0d
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/ChangeLogWriter.java
@@ -0,0 +1,121 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.cvslib;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Iterator;
+
+/**
+ * Class used to generate an XML changelog.
+ *
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ */
+class ChangeLogWriter
+{
+ /** output format for dates writtn to xml file */
+ private static final SimpleDateFormat c_outputDate = new SimpleDateFormat( "yyyy-MM-dd" );
+ /** output format for times writtn to xml file */
+ private static final SimpleDateFormat c_outputTime = new SimpleDateFormat( "hh:mm" );
+
+ /**
+ * Print out the specifed entrys.
+ */
+ public void printChangeLog( final PrintWriter output,
+ final CVSEntry[] entries )
+ {
+ output.println( "" );
+ for( int i = 0; i < entries.length; i++ )
+ {
+ final CVSEntry entry = entries[ i ];
+ printEntry( output, entry );
+ }
+ output.println( "" );
+ output.flush();
+ output.close();
+ }
+
+ /**
+ * Print out an individual entry in changelog.
+ *
+ * @param entry the entry to print
+ */
+ private void printEntry( final PrintWriter output, final CVSEntry entry )
+ {
+ output.println( "\t" );
+ output.println( "\t\t" + c_outputDate.format( entry.getDate() ) + "" );
+ output.println( "\t\t" );
+ output.println( "\t\t" + entry.getAuthor() + "" );
+
+ final Iterator iterator = entry.getFiles().iterator();
+ while( iterator.hasNext() )
+ {
+ final RCSFile file = (RCSFile)iterator.next();
+ output.println( "\t\t" );
+ output.println( "\t\t\t" + file.getName() + "" );
+ output.println( "\t\t\t" + file.getRevision() + "" );
+
+ final String previousRevision = file.getPreviousRevision();
+ if( previousRevision != null )
+ {
+ output.println( "\t\t\t" + previousRevision + "" );
+ }
+
+ output.println( "\t\t" );
+ }
+ output.println( "\t\t" + entry.getComment() + "" );
+ output.println( "\t" );
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java
new file mode 100644
index 000000000..ce33fb3ad
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/CvsUser.java
@@ -0,0 +1,105 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.cvslib;
+
+import org.apache.tools.ant.BuildException;
+
+/**
+ * Represents a CVS user with a userID and a full name.
+ *
+ * @author Peter Donald
+ * @author Jeff Martin
+ * @version $Revision$ $Date$
+ */
+public class CvsUser
+{
+ private String m_userID;
+ private String m_displayName;
+
+ public void setDisplayname( final String displayName )
+ {
+ m_displayName = displayName;
+ }
+
+ public void setUserid( final String userID )
+ {
+ m_userID = userID;
+ }
+
+ String getUserID()
+ {
+ return m_userID;
+ }
+
+ String getDisplayname()
+ {
+ return m_displayName;
+ }
+
+ void validate()
+ throws BuildException
+ {
+ if( null == m_userID )
+ {
+ final String message = "Username attribute must be set.";
+ throw new BuildException( message );
+ }
+ if( null == m_displayName )
+ {
+ final String message =
+ "Displayname attribute must be set for userID " + m_userID;
+ throw new BuildException( message );
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java
new file mode 100644
index 000000000..2ab4cb2d1
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/RCSFile.java
@@ -0,0 +1,100 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Ant", and "Apache Software
+ * Foundation" must not be used to endorse or promote products derived
+ * from this software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ * nor may "Apache" appear in their names without prior written
+ * permission of the Apache Group.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.tools.ant.taskdefs.cvslib;
+
+/**
+ * Represents a RCS File cheange.
+ *
+ * @author Peter Donald
+ * @author Jeff Martin
+ * @version $Revision$ $Date$
+ */
+class RCSFile
+{
+ private final String m_name;
+ private final String m_revision;
+ private String m_previousRevision;
+
+ RCSFile( final String name, final String rev )
+ {
+ this( name, rev, null );
+ }
+
+ RCSFile( final String name,
+ final String revision,
+ final String previousRevision )
+ {
+ m_name = name;
+ m_revision = revision;
+ if( !revision.equals( previousRevision ) )
+ {
+ m_previousRevision = previousRevision;
+ }
+ }
+
+ String getName()
+ {
+ return m_name;
+ }
+
+ String getRevision()
+ {
+ return m_revision;
+ }
+
+ String getPreviousRevision()
+ {
+ return m_previousRevision;
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
new file mode 100644
index 000000000..0478fafdc
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/cvslib/RedirectingStreamHandler.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software License
+ * version 1.1, a copy of which has been included with this distribution in
+ * the LICENSE.txt file.
+ */
+package org.apache.tools.ant.taskdefs.cvslib;
+
+import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+
+/**
+ * A dummy stream handler that just passes stuff to the parser.
+ *
+ * @author Peter Donald
+ * @version $Revision$ $Date$
+ */
+class RedirectingStreamHandler
+ implements ExecuteStreamHandler
+{
+ private final ChangeLogParser m_parser;
+ private BufferedReader m_reader;
+
+ public RedirectingStreamHandler( final ChangeLogParser parser )
+ {
+ m_parser = parser;
+ }
+
+ /**
+ * Install a handler for the input stream of the subprocess.
+ *
+ * @param os output stream to write to the standard input stream of the
+ * subprocess
+ */
+ public void setProcessInputStream( OutputStream os ) throws IOException
+ {
+ //ignore
+ }
+
+ /**
+ * Install a handler for the error stream of the subprocess.
+ *
+ * @param is input stream to read from the error stream from the subprocess
+ */
+ public void setProcessErrorStream( InputStream is ) throws IOException
+ {
+ //ignore
+ }
+
+ /**
+ * Install a handler for the output stream of the subprocess.
+ *
+ * @param is input stream to read from the error stream from the subprocess
+ */
+ public void setProcessOutputStream( InputStream is ) throws IOException
+ {
+ m_reader = new BufferedReader(new InputStreamReader(is));
+ }
+
+ /**
+ * Start handling of the streams.
+ */
+ public void start() throws IOException
+ {
+ String line = m_reader.readLine();
+ while( null != line )
+ {
+ m_parser.stdout( line );
+ line = m_reader.readLine();
+ }
+ }
+
+ /**
+ * Stop handling of the streams - will not be restarted.
+ */
+ public void stop()
+ {
+ }
+}