Package net.sourceforge.cruisecontrol.sourcecontrols

Source Code of net.sourceforge.cruisecontrol.sourcecontrols.PVCS$ModificationBuilder

/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2001-2003, ThoughtWorks, Inc.
* 651 W Washington Ave. Suite 600
* Chicago, IL 60661 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*     + Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*
*     + 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.
*
*     + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
*       names of its contributors may be used to endorse or promote
*       products derived from this software without specific prior
*       written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS 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 REGENTS OR
* 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.
********************************************************************************/
package net.sourceforge.cruisecontrol.sourcecontrols;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;

import net.sourceforge.cruisecontrol.CruiseControlException;
import net.sourceforge.cruisecontrol.Modification;
import net.sourceforge.cruisecontrol.SourceControl;
import net.sourceforge.cruisecontrol.util.ValidationHelper;
import net.sourceforge.cruisecontrol.util.StreamPumper;

import org.apache.log4j.Logger;

/**
*  This class implements the SourceControlElement methods for a PVCS
*  repository.
*
@author <a href="mailto:Richard.Wagner@alltel.com">Richard Wagner</a>
*/
public class PVCS implements SourceControl {

    private static final Logger LOG = Logger.getLogger(PVCS.class);
    private static final String DOUBLE_QUOTE = "\"";

    private Hashtable properties = new Hashtable();
    private Date lastBuild;

    private String pvcsbin;
    private String pvcsExecCommand;
    private String pvcsProject;
    // i.e. "esa";
    // i.e. "esa/uihub2";
    private String pvcsSubProject;
    private String pvcsVersionLabel;
    private String loginId;

    /**
     * Date format required by commands passed to PVCS
     */
    private SimpleDateFormat inDateFormat = new SimpleDateFormat("MM/dd/yyyy h:mma");
    private SimpleDateFormat outDateFormatSub = new SimpleDateFormat("dd MMM yyyy HH:mm:ss");

    /**
     * Date format returned in the output of PVCS commands.
     */
    private SimpleDateFormat outDateFormat = new SimpleDateFormat("MMM dd yyyy HH:mm:ss");

    private static final String PVCS_RESULTS_FILE = "vlog.txt";

    /**
     * Get name of the PVCS bin directory
     * @return String
     */
    public String getPvcsbin() {
        return pvcsbin;
    }

    public void setPvcsExecCommand(String command) {
        pvcsExecCommand = command;
    }

    public String getPvcsExecCommand() {
        return pvcsExecCommand;
    }

    /**
     * Specifies the location of the PVCS bin directory
     * @param bin Specifies the location of the PVCS bin directory
     */
    public void setPvcsbin(String bin) {
        this.pvcsbin = bin;
    }

    public void setPvcsproject(String project) {
        pvcsProject = project;
    }

    public void setPvcssubproject(String subproject) {
        pvcsSubProject = subproject;
    }

    public void setPvcsversionlabel(String versionlabel) {
        pvcsVersionLabel = versionlabel;
    }

    public void setInDateFormat(String inDateFormat) {
        this.inDateFormat = new SimpleDateFormat(inDateFormat);
    }

    public void setOutDateFormat(String outDateFormat) {
        this.outDateFormat = new SimpleDateFormat(outDateFormat);
    }

    public Hashtable getProperties() {
        return properties;
    }

    public void validate() throws CruiseControlException {
        ValidationHelper.assertIsSet(pvcsProject, "pvcsproject", this.getClass());
        ValidationHelper.assertIsSet(pvcsSubProject, "pvcssubproject", this.getClass());
    }

    /**
     *  Returns an {@link java.util.List List} of {@link Modification}
     *  detailing all the changes between now and the last build.
     *
     *@param  lastBuild the last build time
     *@param  now time now, or time to check
     *@return  the list of modifications, an empty (not null) list if no
     *      modifications or if developer had checked in files since quietPeriod seconds ago.
     *
     *  Note:  Internally uses external filesystem for files CruiseControlPVCS.pcli, files.tmp, vlog.txt
     */
    public List getModifications(Date lastBuild, Date now) {
        this.lastBuild = lastBuild;
        // build file of PVCS command line instructions
        String lastBuildDate = inDateFormat.format(lastBuild);
        String nowDate = inDateFormat.format(now);

        try {
            setPvcsExecCommand(getExecutable("pcli") + " " +  buildExecCommand(lastBuildDate, nowDate));
            exec(pvcsExecCommand);
        } catch (Exception e) {
            LOG.error("Error in executing the PVCS command : ", e);
            return new ArrayList();
        }
        List modifications = makeModificationsList();

        return modifications;
    }

    String getExecutable(String exe) {
        StringBuffer correctedExe = new StringBuffer();
        if (getPvcsbin() != null) {
            if (getPvcsbin().endsWith(File.separator)) {
                correctedExe.append(getPvcsbin());
            } else {
                correctedExe.append(getPvcsbin()).append(File.separator);
            }
        }
        return correctedExe.append(exe).toString();
    }

    private void exec(String command) throws IOException, InterruptedException {
        LOG.debug("Command to execute: " + command);
        Process p = Runtime.getRuntime().exec(command);
        StreamPumper errorPumper = new StreamPumper(p.getErrorStream());
        new Thread(errorPumper).start();
        p.getInputStream();
        p.waitFor();
        p.getOutputStream();
        p.getInputStream();
        p.getErrorStream();
    }

    /**
     * Read the file produced by PCLI listing all changes to the source repository
     * Once we've read the file, produce a list of changes.
     */
    private List makeModificationsList() {
        List theList;
        File inputFile = new File(PVCS_RESULTS_FILE);
        BufferedReader brIn;
        ModificationBuilder modificationBuilder = new ModificationBuilder(pvcsProject);
        try {
            brIn = new BufferedReader(new FileReader(inputFile));
            String line;
            while ((line = brIn.readLine()) != null) {
                modificationBuilder.addLine(line);
            }
            brIn.close();
        } catch (IOException e) {
            LOG.error("Error in reading vlog file of PVCS modifications : ", e);
        }
        theList = modificationBuilder.getList();

        if (theList == null) {
            theList = new ArrayList();
        }

        return theList;
    }

    /**
     *  Returns the command to be ran to check for repository changes
     *  run -ns -q -xo"vlog.txt" -xe"vlog.txt" vlog -id"SomeUser"
     *  -ds"11/23/2004 8:00AM"-de"11/23/2004 1:00PM" -pr"C:/PVCS-Repos/TestProject"
     *  -v"Test Version Label" -z /TestProject
     *
     *  @return the command to be executed to check for repository changes
     */
    String buildExecCommand(String lastBuild, String now) {
        String command =
            "run -ns -q -xo" + DOUBLE_QUOTE + PVCS_RESULTS_FILE + DOUBLE_QUOTE
            + " -xe" + DOUBLE_QUOTE + PVCS_RESULTS_FILE + DOUBLE_QUOTE
            + " vlog ";
       
        if (loginId != null && !loginId.trim().equals("")) {
            command += "-id" + DOUBLE_QUOTE + loginId + DOUBLE_QUOTE + " ";
        }
       
        command += "-ds" + DOUBLE_QUOTE + lastBuild + DOUBLE_QUOTE
            + " -de" + DOUBLE_QUOTE + now + DOUBLE_QUOTE
            + " -pr" + DOUBLE_QUOTE + pvcsProject + DOUBLE_QUOTE;

        if (pvcsVersionLabel != null && !pvcsVersionLabel.equals("")) {
            command += " -v" + DOUBLE_QUOTE + pvcsVersionLabel + DOUBLE_QUOTE;
         }

        command += " -z " + pvcsSubProject;
        return command;
    }

    /**
     * Inner class to build Modifications and verify the order of the lines
     * used to build them.
     */
    class ModificationBuilder {
        private String proj;
        private Modification modification;
        private ArrayList modificationList;
        private boolean firstModifiedTime = true;
        private boolean firstUserName = true;
        private boolean nextLineIsComment = false;
        private boolean waitingForNextValidStart = false;

        public ModificationBuilder(String proj) {
            this.proj = proj;
        }

        public ArrayList getList() {
            return modificationList;
        }

        private void initializeModification() {
            if (modificationList == null) {
                modificationList = new ArrayList();
            }
            modification = new Modification("pvcs");
            firstModifiedTime = true;
            firstUserName = true;
            nextLineIsComment = false;
            waitingForNextValidStart = false;
        }

        public void addLine(String line) {
            if (line.startsWith("Archive:")) {
                initializeModification();
                String fileName;

                fileName = line.substring((line.indexOf(proj) + proj.length()),  line.indexOf("-arc"));
                if (fileName.startsWith("/") || fileName.startsWith("\\")) {
                     fileName = fileName.substring(1);
                }
                if (fileName.startsWith("archives")) {
                     fileName = fileName.substring("archives".length());
                }


                modification.createModifiedFile(fileName, null);

            } else if (waitingForNextValidStart) {
                // we're in this state after we've got the last useful line
                // from the previous item, but haven't yet started a new one
                // -- we should just skip these lines till we start a new one
                return;
            } else if (line.startsWith("Workfile:")) {
                modification.createModifiedFile(line.substring(18), null);
            } else if (line.startsWith("Archive created:")) {
                try {
                    String createdDate = line.substring(18);
                    Date createTime;
                    try {
                        createTime = outDateFormat.parse(createdDate);
                    } catch (ParseException e) {
                        createTime = outDateFormatSub.parse(createdDate);
                    }
                    if (createTime.after(lastBuild)) {
                        modification.type = "added";
                    } else {
                        modification.type = "modified";
                    }
                } catch (ParseException e) {
                    LOG.error("Error parsing create date: " + e.getMessage(), e);
                }
            } else if (line.startsWith("Last modified:")) {
                // if this is the newest revision...
                if (firstModifiedTime) {
                    firstModifiedTime = false;
                    String lastMod = null;
                    try {
                        lastMod = line.substring(16);
                        modification.modifiedTime = outDateFormat.parse(lastMod);
                    } catch (ParseException e) {
                        try {
                            modification.modifiedTime = outDateFormatSub.parse(lastMod);
                        } catch (ParseException pe) {
                            modification.modifiedTime = null;
                            LOG.error("Error parsing modification time : ", e);
                          }
                    }
                }
            } else if (nextLineIsComment) {
                // used boolean because don't know what comment will startWith....
                modification.comment = line;
                // comment is last line we need, so add this mod to list,
                //  then set indicator to ignore future lines till next new item
                modificationList.add(modification);
                waitingForNextValidStart = true;
            } else if (line.startsWith("Author id:")) {
                // if this is the newest revision...
                if (firstUserName) {
                    String sub = line.substring(11);
                    StringTokenizer st = new StringTokenizer(sub, " ");
                    String username = st.nextToken().trim();
                    modification.userName = username;
                    firstUserName = false;
                    nextLineIsComment = true;
                }
            } // end of Author id

        } // end of addLine

    } // end of class ModificationBuilder

   /**
    * @return loginId
    */
   public String getLoginid() {
      return loginId;
   }

   /**
    * @param loginId
    */
   public void setLoginid(String loginId) {
      this.loginId = loginId;
   }

} // end class PVCSElement
TOP

Related Classes of net.sourceforge.cruisecontrol.sourcecontrols.PVCS$ModificationBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.