diff --git a/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogFactory.java b/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogFactory.java
new file mode 100644
index 00000000..46e0d848
--- /dev/null
+++ b/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogFactory.java
@@ -0,0 +1,119 @@
+package org.apache.maven.perforcelib;
+
+/* ====================================================================
+ * 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 acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache Maven" 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",
+ * "Apache Maven", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * 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
+ * .
+ *
+ * ====================================================================
+ */
+
+import org.apache.maven.changelog.ChangeLogFactory;
+import org.apache.maven.changelog.ChangeLogGenerator;
+import org.apache.maven.changelog.ChangeLogParser;
+
+/**
+ * Provides Perforce specific instances of the ChangeLogGenerator and
+ * ChangeLogParser interfaces.
+ *
+ * It expects the repository connection element in the POM to be of
+ * this form: scm:perforce[:P4PORT]:FILESPEC. If
+ * the P4PORT is omitted, the corresponding environment variable will
+ * be used. The FILESPEC should use the appropriate Perforce
+ * wildcards to represent all of the project's files. For example,
+ *
+ *
+ *
+ * The repository url element should reference the root context of a p4web
+ * instance.
+ *
+ * @author Jim Crossley
+ * @version $Id:
+ */
+public class PerforceChangeLogFactory implements ChangeLogFactory
+{
+ /**
+ * Default no-arg constructor.
+ */
+ public PerforceChangeLogFactory()
+ {
+ }
+
+ /**
+ * Create a Perforce specific ChangeLogGenerator.
+ *
+ * @return a Perforce specific ChangeLogGenerator.
+ */
+ public ChangeLogGenerator createGenerator()
+ {
+ return new PerforceChangeLogGenerator();
+ }
+
+ /**
+ * Create a Perforce specific ChangeLogParser.
+ *
+ * @return a Perforce specific ChangeLogParser.
+ */
+ public ChangeLogParser createParser()
+ {
+ return new PerforceChangeLogParser();
+ }
+}
\ No newline at end of file
diff --git a/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogGenerator.java b/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogGenerator.java
new file mode 100644
index 00000000..2c31757c
--- /dev/null
+++ b/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogGenerator.java
@@ -0,0 +1,151 @@
+package org.apache.maven.perforcelib;
+
+/* ====================================================================
+ * 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 acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache Maven" 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",
+ * "Apache Maven", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * 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
+ * .
+ *
+ * ====================================================================
+ */
+
+import java.io.IOException;
+import java.util.Date;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.maven.changelog.AbstractChangeLogGenerator;
+import org.apache.tools.ant.types.Commandline;
+
+/**
+ * A Perforce implementation of the {@link org.apache.maven.changelog.ChangeLog}
+ * interface.
+ *
+ * @author Jim Crossley
+ * @version $Id:
+ */
+class PerforceChangeLogGenerator extends AbstractChangeLogGenerator
+{
+ /** The position after the connection prefix, 'scm:perforce:' */
+ private static final int POS_PARAMS = 13;
+
+ /** Log */
+ private static final Log LOG = LogFactory.getLog(PerforceChangeLogGenerator.class);
+
+ /**
+ * Constructs the appropriate command line to execute the perforce
+ * log command whose output is then later parsed.
+ *
+ * Repository connection syntax:
+ * scm:perforce[:host:port]://depot/projects/name/...
+ *
+ * @return the cvs command line to be executed.
+ */
+ protected Commandline getScmLogCommand()
+ {
+ String conn = getConnection();
+ if (!conn.startsWith("scm:perforce:"))
+ {
+ throw new IllegalArgumentException(
+ "repository connection string"
+ + " does not specify 'perforce' as the scm");
+ }
+ int lastColon = conn.lastIndexOf(':');
+ String fileSpec = conn.substring(lastColon+1);
+ String p4port = (POS_PARAMS>lastColon) ? null : conn.substring(POS_PARAMS, lastColon);
+
+ Commandline command = new Commandline();
+ command.setExecutable("p4");
+ if (p4port != null) {
+ command.createArgument().setValue("-p");
+ command.createArgument().setValue(p4port);
+ }
+ command.createArgument().setValue("filelog");
+ command.createArgument().setValue("-tl");
+ command.createArgument().setValue(fileSpec);
+
+ return command;
+ }
+
+ /**
+ * The Perforce filelog doesn't support a revision, i.e. date,
+ * range
+ *
+ * @param before The starting point.
+ * @param to The ending point.
+ * @return An empty string
+ */
+ protected String getScmDateArgument(Date before, Date to)
+ {
+ return "";
+ }
+
+ /**
+ * Handle ChangeLogParser IOExceptions.
+ *
+ * @param ioe The IOException thrown.
+ * @throws IOException If the handler doesn't wish to handle the
+ * exception.
+ */
+ protected void handleParserException(IOException ioe)
+ throws IOException
+ {
+ if (ioe.getMessage().indexOf("CreateProcess") != -1
+ || ioe.getMessage().indexOf("p4: not found") != -1)
+ {
+ // can't find p4 on Win32 or Linux...
+ LOG.error(
+ "Unable to find p4 executable. Changelog will be empty");
+ }
+ else
+ {
+ throw ioe;
+ }
+ }
+}
diff --git a/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogParser.java b/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogParser.java
new file mode 100644
index 00000000..18dda647
--- /dev/null
+++ b/changelog/src/main/org/apache/maven/perforcelib/PerforceChangeLogParser.java
@@ -0,0 +1,305 @@
+package org.apache.maven.perforcelib;
+
+/* ====================================================================
+ * 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 acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache Maven" 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",
+ * "Apache Maven", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * 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
+ * .
+ *
+ * ====================================================================
+ */
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+import java.util.ArrayList;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.maven.changelog.ChangeLog;
+import org.apache.maven.changelog.ChangeLogParser;
+import org.apache.maven.changelog.ChangeLogEntry;
+import org.apache.maven.changelog.ChangeLogFile;
+import org.apache.regexp.RE;
+import org.apache.regexp.RESyntaxException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A class to parse the log output from the Perforce 'filelog'
+ * command.
+ *
+ * @author Jim Crossley
+ * @version $Id:
+ */
+class PerforceChangeLogParser implements ChangeLogParser
+{
+ /** Date formatter for perforce timestamp */
+ private static final SimpleDateFormat PERFORCE_TIMESTAMP =
+ new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+ /** Log */
+ private static final Log LOG = LogFactory.getLog (PerforceChangeLogParser.class);
+
+ /**
+ * RCS entries, in reverse changelist number order
+ */
+ private Map entries = new TreeMap(Collections.reverseOrder());
+
+ /** State machine constant: expecting revision and/or file information */
+ private static final int GET_REVISION = 1;
+
+ /** State machine constant: eat the first blank line */
+ private static final int GET_COMMENT_BEGIN = 2;
+
+ /** State machine constant: expecting comments */
+ private static final int GET_COMMENT = 3;
+
+ /** The comment section ends with a blank line */
+ private static final String COMMENT_DELIMITER = "";
+
+ /** A file line begins with two slashes */
+ private static final String FILE_BEGIN_TOKEN = "//";
+
+ /** Current status of the parser */
+ private int status = GET_REVISION;
+
+ /** The current log entry being processed by the parser */
+ private ChangeLogEntry currentLogEntry;
+
+ /** the current file being processed by the parser */
+ private String currentFile;
+
+ /** The regular expression used to match header lines */
+ private RE revisionRegexp;
+
+ /** The invoking changelog controller (useful to log messages) */
+ private ChangeLog changeLog;
+
+ /** the before date */
+ private Date beforeDate;
+
+ private static final String pattern =
+ "^\\.\\.\\. #(\\d+) " + // revision number
+ "change (\\d+) .* " + // changelist number
+ "on (.*) " + // date
+ "by (.*)@"; // author
+
+ /**
+ * Default constructor.
+ */
+ public PerforceChangeLogParser()
+ {
+ try {
+ revisionRegexp = new RE(pattern);
+ } catch (RESyntaxException ignored) {
+ LOG.error("Could not create regexp to parse perforce log file", ignored);
+ }
+ }
+
+ /**
+ * Initialize the parser from the change log.
+ *
+ * @param changeLog The controlling task
+ * @see ChangeLogParser#init(ChangeLog)
+ */
+ public void init(ChangeLog changeLog)
+ {
+ this.changeLog = changeLog;
+ setDateRange();
+ }
+
+ /**
+ * Clean up any parser resources.
+ *
+ * @see ChangeLogParser#cleanup()
+ */
+ public void cleanup()
+ {
+ }
+
+ /**
+ * Parse the input stream into a collection of entries
+ *
+ * @param anInputStream An input stream containing perforce log output
+ * @return A collection of ChangeLogEntry's
+ * @throws IOException When there are errors reading the provided stream
+ */
+ public Collection parse(InputStream anInputStream) throws IOException
+ {
+ BufferedReader stream = new BufferedReader(new InputStreamReader(anInputStream));
+
+ String line = null;
+ while ((line = stream.readLine()) != null)
+ {
+ switch (status)
+ {
+ case GET_REVISION:
+ processGetRevision(line);
+ break;
+ case GET_COMMENT_BEGIN:
+ status = GET_COMMENT;
+ break;
+ case GET_COMMENT:
+ processGetComment(line);
+ break;
+ default:
+ throw new IllegalStateException("Unknown state: " + status);
+ }
+ }
+ return entries.values();
+ }
+
+ /**
+ * Add a change log entry to the list (if it's not already there)
+ * with the given file.
+ * @param entry a {@link ChangeLogEntry} to be added to the list if another
+ * with the same key (p4 change number) doesn't exist already.
+ * @param file a {@link ChangeLogFile} to be added to the entry
+ */
+ private void addEntry(ChangeLogEntry entry, ChangeLogFile file)
+ {
+ System.out.println();
+ System.out.println(entry.toXML());
+ if (beforeDate != null) {
+ if (entry.getDate().before(beforeDate)) {
+ return;
+ }
+ }
+ Integer key = new Integer(revisionRegexp.getParen(2));
+ if (!entries.containsKey(key)) {
+ entry.addFile(file);
+ entries.put(key, entry);
+ } else {
+ ChangeLogEntry existingEntry = (ChangeLogEntry) entries.get(key);
+ existingEntry.addFile(file);
+ }
+ }
+
+ /**
+ * Most of the relevant info is on the revision line matching the
+ * 'pattern' string.
+ *
+ * @param line A line of text from the perforce log output
+ */
+ private void processGetRevision(String line)
+ {
+ if (line.startsWith(FILE_BEGIN_TOKEN)) {
+ currentFile = line;
+ return;
+ }
+
+ if (!revisionRegexp.match(line)) {
+ return;
+ }
+
+ currentLogEntry = new ChangeLogEntry();
+ currentLogEntry.setDate(parseDate(revisionRegexp.getParen(3)));
+ currentLogEntry.setAuthor(revisionRegexp.getParen(4));
+
+ status = GET_COMMENT_BEGIN;
+ }
+
+ /**
+ * Process the current input line in the GET_COMMENT state. This
+ * state gathers all of the comments that are part of a log entry.
+ *
+ * @param line a line of text from the perforce log output
+ */
+ private void processGetComment(String line)
+ {
+ if (line.equals(COMMENT_DELIMITER)) {
+ addEntry(currentLogEntry, new ChangeLogFile(currentFile, revisionRegexp.getParen(1)));
+ status = GET_REVISION;
+ } else {
+ currentLogEntry.setComment(currentLogEntry.getComment() + line + "\n");
+ }
+ }
+
+ /**
+ * Converts the date timestamp from the perforce output into a date
+ * object.
+ *
+ * @return A date representing the timestamp of the log entry.
+ */
+ private Date parseDate(String date)
+ {
+ try {
+ return PERFORCE_TIMESTAMP.parse(date);
+ } catch (ParseException e) {
+ LOG.error("ParseException Caught", e);
+ return null;
+ }
+ }
+
+ /**
+ * Set the beforeDate member based on the number of days obtained
+ * from the ChangeLog.
+ *
+ * @param numDaysString The number of days of log output to
+ * generate.
+ */
+ private void setDateRange()
+ {
+ if (this.changeLog == null ||
+ this.changeLog.getRange() == null ||
+ this.changeLog.getRange().length() == 0)
+ {
+ return;
+ }
+ int days = Integer.parseInt(this.changeLog.getRange());
+ beforeDate = new Date(System.currentTimeMillis() - (long) days * 24 * 60 * 60 * 1000);
+ }
+}
diff --git a/changelog/src/plugin-resources/changelog.jsl b/changelog/src/plugin-resources/changelog.jsl
index 342573f1..062c727a 100644
--- a/changelog/src/plugin-resources/changelog.jsl
+++ b/changelog/src/plugin-resources/changelog.jsl
@@ -60,8 +60,17 @@
+
+
+ ${name}
+ v${revision}
+
+ ${name}v${revision}
+
+
+
diff --git a/changelog/src/test-resources/perforcelib/perforcelog.txt b/changelog/src/test-resources/perforcelib/perforcelog.txt
new file mode 100644
index 00000000..a500d8ff
--- /dev/null
+++ b/changelog/src/test-resources/perforcelib/perforcelog.txt
@@ -0,0 +1,47 @@
+//depot/test/demo/demo.c
+... #4 change 7 edit on 2003/10/01 16:24:20 by jim@cpt-jcrossley (text)
+
+ Backing out my test changes
+
+ Updating a description
+
+... #3 change 4 edit on 2003/10/01 08:35:08 by jim@cpt-jcrossley (text)
+
+ Another test
+
+... #2 change 3 edit on 2003/10/01 08:29:15 by jim@cpt-jcrossley (text)
+
+ Testing review daemon
+
+ Updating description
+
+... #1 change 1 add on 2003/08/07 17:21:57 by mcronin@mcronin (text)
+
+ demonstration of Perforce on Windows, Unix and VMS.
+
+... ... branch into //depot/releases/test-1/demo/demo.c#1
+//depot/test/demo/dictcalls.txt
+... #1 change 1 add on 2003/08/07 17:21:57 by mcronin@mcronin (text)
+
+ demonstration of Perforce on Windows, Unix and VMS.
+
+... ... branch into //depot/releases/test-1/demo/dictcalls.txt#1
+//depot/test/demo/dictwords.txt
+... #1 change 1 add on 2003/08/07 17:21:57 by mcronin@mcronin (text)
+
+ demonstration of Perforce on Windows, Unix and VMS.
+
+... ... branch into //depot/releases/test-1/demo/dictwords.txt#1
+//depot/test/junk/linefeed.txt
+... #3 change 13 edit on 2003/10/15 13:38:40 by jim@cpt-jcrossley (text)
+
+ Where's my change #
+
+... #2 change 10 edit on 2003/10/15 07:14:46 by jim@jcrossley (text)
+
+ Added a linefeed at the end to see if the [noeol] descriptor goes away in vim.
+
+... #1 change 9 add on 2003/10/15 07:01:59 by jim@cpt-jcrossley (text)
+
+ Testing CR/LF resolution on different platforms
+
diff --git a/changelog/src/test/org/apache/maven/perforcelib/PerforceChangeLogGeneratorTest.java b/changelog/src/test/org/apache/maven/perforcelib/PerforceChangeLogGeneratorTest.java
new file mode 100644
index 00000000..be031f86
--- /dev/null
+++ b/changelog/src/test/org/apache/maven/perforcelib/PerforceChangeLogGeneratorTest.java
@@ -0,0 +1,150 @@
+package org.apache.maven.perforcelib;
+
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2003 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 acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache Maven" 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",
+ * "Apache Maven", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * 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
+ * .
+ *
+ * ====================================================================
+ */
+
+
+import org.apache.maven.project.Repository;
+import org.apache.maven.util.EnhancedStringTokenizer;
+import org.apache.tools.ant.types.Commandline;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Jim Crossley
+ * @author Ben Walding
+ * @version $Id:
+ */
+public class PerforceChangeLogGeneratorTest extends TestCase
+{
+ class Test
+ {
+ String conn;
+ String args;
+ Class throwable;
+
+ public Test(String conn, String args, Class throwable)
+ {
+ this.conn = conn;
+ this.args = args;
+ this.throwable = throwable;
+ }
+
+ }
+
+ Test[] tests =
+ {
+ new Test(null, "", NullPointerException.class),
+ new Test("asd:asd", "", IllegalArgumentException.class),
+ new Test("scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-turbine-maven",
+ "",
+ IllegalArgumentException.class),
+ new Test("scm:perforce:host:port://depot/projects/name/...",
+ "p4|-p|host:port|filelog|-tl|//depot/projects/name/...",
+ null),
+ new Test("scm:perforce:port://depot/projects/name/...",
+ "p4|-p|port|filelog|-tl|//depot/projects/name/...",
+ null),
+ new Test("scm:perforce://depot/projects/name/...",
+ "p4|filelog|-tl|//depot/projects/name/...",
+ null),
+ };
+
+ public void testParse() throws Throwable
+ {
+ for (int i = 0; i < tests.length; i++)
+ {
+ Test t = tests[i];
+ testParse(t);
+ }
+ }
+
+ public void testParse(Test test) throws Throwable
+ {
+ String[] expected = Repository.tokenizerToArray(new EnhancedStringTokenizer(test.args, "|"));
+
+ PerforceChangeLogGenerator eg = new PerforceChangeLogGenerator();
+ try {
+ eg.setConnection(test.conn);
+ Commandline cl = eg.getScmLogCommand();
+ String[] clArgs = cl.getCommandline();
+ if (test.throwable == null)
+ {
+ assertEquals("clArgs.length", expected.length, clArgs.length);
+ for (int i = 0; i < expected.length; i++)
+ {
+ assertEquals("clArgs[" + i + "]", expected[i], clArgs[i]);
+ }
+ }
+ else
+ {
+ fail("Failed to throw :" + test.throwable.getName());
+ }
+
+ }
+ catch (Throwable t)
+ {
+ if (test.throwable != null && test.throwable.isAssignableFrom(t.getClass()))
+ {
+ //Success
+ }
+ else
+ {
+ throw new RuntimeException("Caught unexpected exception \"" + t.getLocalizedMessage() + "\" testing " + test.conn);
+ }
+ }
+ }
+}
diff --git a/changelog/src/test/org/apache/maven/perforcelib/PerforceChangeLogParserTest.java b/changelog/src/test/org/apache/maven/perforcelib/PerforceChangeLogParserTest.java
new file mode 100644
index 00000000..2c12041c
--- /dev/null
+++ b/changelog/src/test/org/apache/maven/perforcelib/PerforceChangeLogParserTest.java
@@ -0,0 +1,167 @@
+package org.apache.maven.perforcelib;
+
+/* ====================================================================
+ * 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 acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ * "Apache Maven" 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",
+ * "Apache Maven", nor may "Apache" appear in their name, without
+ * prior written permission of the Apache Software Foundation.
+ *
+ * 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
+ * .
+ */
+
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.apache.maven.changelog.ChangeLogEntry;
+
+/**
+ * Test cases for {@link PerforceChangeLogParser}
+ * @author Jim Crossley
+ * @version $Id:
+ */
+public class PerforceChangeLogParserTest extends TestCase
+{
+ /** The {@link PerforceChangeLogParser} used for testing */
+ private PerforceChangeLogParser parser;
+
+ /** File with test results to check against */
+ private String testFile;
+
+ /**
+ * Create a test with the given name.
+ *
+ * @param testName the name of the test.
+ */
+ public PerforceChangeLogParserTest(String testName)
+ {
+ super(testName);
+ }
+
+ /**
+ * Initialize per test data.
+ *
+ * @throws Exception when there is an unexpected problem.
+ */
+ public void setUp() throws Exception
+ {
+ String baseDir = System.getProperty("basedir");
+ assertNotNull("The system property basedir was not defined.", baseDir);
+ testFile = baseDir + "/src/test-resources/perforcelib/perforcelog.txt";
+ parser = new PerforceChangeLogParser();
+ }
+
+ /**
+ * Test the Perforce parser.
+ *
+ * @throws Exception when there is an unexpected problem
+ */
+ public void testParse() throws Exception
+ {
+ FileInputStream fis = new FileInputStream(testFile);
+ List entries = new ArrayList(parser.parse(fis));
+
+ assertEquals("Wrong number of entries returned", 7, entries.size());
+
+ ChangeLogEntry entry = (ChangeLogEntry) entries.get(0);
+ assertEquals("Entry 0 was parsed incorrectly",
+ "\t\n" +
+ "\t\t2003-10-15\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\t//depot/test/junk/linefeed.txt\n" +
+ "\t\t\t3\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\n",
+ entry.toXML());
+
+ entry = (ChangeLogEntry) entries.get(3);
+ assertEquals("Entry 3 was parsed incorrectly",
+ "\t\n" +
+ "\t\t2003-10-01\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\t//depot/test/demo/demo.c\n" +
+ "\t\t\t4\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\n",
+ entry.toXML());
+
+ entry = (ChangeLogEntry) entries.get(6);
+ assertEquals("Entry 6 was parsed incorrectly",
+ "\t\n" +
+ "\t\t2003-08-07\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\t//depot/test/demo/demo.c\n" +
+ "\t\t\t1\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\t//depot/test/demo/dictcalls.txt\n" +
+ "\t\t\t1\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\t\t//depot/test/demo/dictwords.txt\n" +
+ "\t\t\t1\n" +
+ "\t\t\n" +
+ "\t\t\n" +
+ "\t\n",
+ entry.toXML());
+ }
+}
diff --git a/changelog/xdocs/changes.xml b/changelog/xdocs/changes.xml
index 9110daf1..97f91817 100644
--- a/changelog/xdocs/changes.xml
+++ b/changelog/xdocs/changes.xml
@@ -12,6 +12,9 @@
Added java based CVS library using cvslib. Removed
requirement for cvs executable.
+
+ MAVEN-963. Add support for Perforce SCM and cleaned up some docs.
+
diff --git a/changelog/xdocs/index.xml b/changelog/xdocs/index.xml
index 49d08447..5af8f107 100644
--- a/changelog/xdocs/index.xml
+++ b/changelog/xdocs/index.xml
@@ -10,10 +10,11 @@
- This plugin produces a nicely formatted changelog report so project
- team members can see at a glance what changes have been made
- recently to the project. Currently, there are three supported
- source control systems: CVS, StarTeam, IBM Rational ClearCase and Subversion.
+ This plugin produces a nicely formatted changelog report so
+ project team members can see at a glance what changes have
+ been made recently to the project. Currently, there are five
+ supported source control systems: CVS, Perforce, StarTeam, IBM
+ Rational ClearCase and Subversion.
For more information on the functionality provided by this plugin,
diff --git a/changelog/xdocs/navigation.xml b/changelog/xdocs/navigation.xml
index 8abfd65e..db225b6e 100644
--- a/changelog/xdocs/navigation.xml
+++ b/changelog/xdocs/navigation.xml
@@ -7,7 +7,9 @@
+
+