You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ol...@apache.org on 2011/08/27 14:39:22 UTC

svn commit: r1162334 [2/4] - in /maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity: ./ src/main/java/org/apache/maven/scm/provider/integrity/ src/main/java/org/apache/maven/scm/provider/integrity/command/add/ src/main/java/org/apache/mav...

Modified: maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Project.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Project.java?rev=1162334&r1=1162333&r2=1162334&view=diff
==============================================================================
--- maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Project.java (original)
+++ maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Project.java Sat Aug 27 12:39:21 2011
@@ -18,368 +18,396 @@ package org.apache.maven.scm.provider.in
  * specific language governing permissions and limitations
  * under the License.
  */
- 
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.NoSuchElementException;
 
 import com.mks.api.Command;
 import com.mks.api.MultiValue;
 import com.mks.api.Option;
 import com.mks.api.response.APIException;
+import com.mks.api.response.Field;
 import com.mks.api.response.Response;
 import com.mks.api.response.WorkItem;
-import com.mks.api.response.Field;
 import com.mks.api.response.WorkItemIterator;
 import com.mks.api.si.SIModelTypeName;
 
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.NoSuchElementException;
+
 /**
  * This class represents a MKS Integrity Configuration Management Project
  * <br>Provides metadata information about a Project
- * @version $Id: Project.java 1.6 2011/08/22 13:06:48EDT Cletus D'Souza (dsouza) Exp  $
+ *
  * @author <a href="mailto:cletus@mks.com">Cletus D'Souza</a>
+ * @version $Id: Project.java 1.6 2011/08/22 13:06:48EDT Cletus D'Souza (dsouza) Exp  $
+ * @since 1.6
  */
 public class Project
 {
-	public static final String NORMAL_PROJECT = "Normal";
-	public static final String VARIANT_PROJECT = "Variant";
-	public static final String BUILD_PROJECT = "Build";
-		
-	private String projectName;
-	private String projectType;
-	private String projectRevision;
-	private String fullConfigSyntax;
-	private Date lastCheckpoint;
-	private APISession api;
-		
+    public static final String NORMAL_PROJECT = "Normal";
+
+    public static final String VARIANT_PROJECT = "Variant";
+
+    public static final String BUILD_PROJECT = "Build";
+
+    private String projectName;
+
+    private String projectType;
+
+    private String projectRevision;
+
+    private String fullConfigSyntax;
+
+    private Date lastCheckpoint;
+
+    private APISession api;
+
     // Create a custom comparator to compare project members
     public static final Comparator<Member> FILES_ORDER = new Comparator<Member>()
-    { 
-    	public int compare(Member cmm1, Member cmm2) 
-    	{
-    		return cmm1.getMemberName().compareToIgnoreCase(cmm2.getMemberName());
-    	}
-    };	
-	
-	/**
-	 * Checks if the given value is a valid MKS Integrity Label.
-	 * <br>If it's invalid, this method throws an exception providing the reason as string.
-	 * @param tagName The checkpoint label name
-	 * @return the error message, or null if label is valid
-	 */
-	public static void validateTag(String tagName) throws Exception
-	{
-		if (tagName == null || tagName.length() == 0)
-		{
-			throw new Exception("The checkpoint label string is empty!");
-		}
-
-		char ch = tagName.charAt(0);
-		if (!(('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z')))
-		{
-			throw new Exception("The checkpoint label must start with an alpha character!");
-		}
-
-		for (char invalid : "$,.:;/\\@".toCharArray())
-		{
-			if (tagName.indexOf(invalid) >= 0)
-			{
-				throw new Exception("The checkpoint label may cannot contain one of the following characters: $ , . : ; / \\ @");
-			}
-		}
-	}
-
-	/**
-	 * Creates an instance of an Integrity SCM Project
-	 * @param api MKS API Session object
-	 * @param configPath Configuration path for the MKS Integrity SCM Project
-	 * @throws APIException
-	 */
-	public Project(APISession api, String configPath) throws APIException
-	{
-		// Initialize our local APISession
-		this.api = api;
-		try
-		{
-			// Get the project information for this project
-			Command siProjectInfoCmd = new Command(Command.SI, "projectinfo");
-			siProjectInfoCmd.addOption(new Option("project", configPath));	
-			api.getLogger().info("Preparing to execute si projectinfo for " + configPath);
-			Response infoRes = api.runCommand(siProjectInfoCmd);
-			// Get the only work item from the response
-			WorkItem wi = infoRes.getWorkItems().next();
-			// Get the metadata information about the project 
-			Field pjNameFld = wi.getField("projectName");
-			Field pjTypeFld = wi.getField("projectType");
-			Field pjCfgPathFld = wi.getField("fullConfigSyntax");
-			Field pjChkptFld = wi.getField("lastCheckpoint");
-			
-			// Convert to our class fields
-			// First obtain the project name field
-			if( null != pjNameFld && null != pjNameFld.getValueAsString() )
-			{
-				projectName = pjNameFld.getValueAsString();
-			}
-			else
-			{
-				api.getLogger().warn("Project info did not provide a value for the 'projectName' field!");
-				projectName = "";
-			}
-			// Next, we'll need to know the project type
-			if( null != pjTypeFld && null != pjTypeFld.getValueAsString() )
-			{
-				projectType = pjTypeFld.getValueAsString();
-				if( isBuild() )
-				{
-					// Next, we'll need to know the current build checkpoint for this configuration
-					Field pjRevFld = wi.getField("revision");
-					if( null != pjRevFld && null != pjRevFld.getItem() )
-					{
-						projectRevision = pjRevFld.getItem().getId();
-					}
-					else
-					{
-						projectRevision = "";
-						api.getLogger().warn("Project info did not provide a vale for the 'revision' field!");
-					}
-				}				
-			}
-			else
-			{
-				api.getLogger().warn("Project info did not provide a value for the 'projectType' field!");
-				projectType = "";
-			}
-			// Most important is the configuration path
-			if( null != pjCfgPathFld && null != pjCfgPathFld.getValueAsString() )
-			{
-				fullConfigSyntax = pjCfgPathFld.getValueAsString();
-			}
-			else
-			{
-				api.getLogger().error("Project info did not provide a value for the 'fullConfigSyntax' field!");
-				fullConfigSyntax = "";				
-			}
-			// Finally, we'll need to store the last checkpoint to figure out differences, etc.
-			if( null != pjChkptFld && null != pjChkptFld.getDateTime() )
-			{
-				lastCheckpoint = pjChkptFld.getDateTime();
-			}
-			else
-			{
-				api.getLogger().warn("Project info did not provide a value for the 'lastCheckpoint' field!");
-				lastCheckpoint = Calendar.getInstance().getTime();				
-			}			
-		}
-		catch(NoSuchElementException nsee)
-		{
-			api.getLogger().error("Project info did not provide a value for field " + nsee.getMessage());
-		}
-	}
-
-	/**
-	 * Returns the project path for this Integrity SCM Project
-	 * @return
-	 */
-	public String getProjectName()
-	{
-		return projectName;
-	}
-
-	/**
-	 * Returns the project revision for this Integrity SCM Project
-	 * @return
-	 */
-	public String getProjectRevision()
-	{
-		return projectRevision;
-	}
-	
-	/**
-	 * Returns true is this is a Normal Project
-	 * @return
-	 */
-	public boolean isNormal()
-	{
-		if( projectType.equalsIgnoreCase(NORMAL_PROJECT) )
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-	
-	/**
-	 * Returns true if this is a Variant Project
-	 * @return
-	 */
-	public boolean isVariant()
-	{
-		if( projectType.equalsIgnoreCase(VARIANT_PROJECT) )
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-	
-	/**
-	 * Returns true if this is a Build Project
-	 * @return
-	 */
-	public boolean isBuild()
-	{
-		if( projectType.equalsIgnoreCase(BUILD_PROJECT) )
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}	
-
-	/**
-	 * Returns the Full Configuration Path for this Integrity SCM Project
-	 * @return
-	 */
-	public String getConfigurationPath()
-	{
-		return fullConfigSyntax;
-	}
-	
-	/**
-	 * Returns the date when the last checkpoint was performed on this Project
-	 * @return
-	 */
-	public Date getLastCheckpointDate()
-	{
-		return lastCheckpoint;
-	}
-	
-	/**
-	 * Parses the output from the si viewproject command to get a list of members
-	 * @param workspaceDir The current workspace directory, which is required for an export
-	 * @return The list of Member objects for this project 
-	 * @throws APIException 
-	 */
-	public List<Member> listFiles(String workspaceDir) throws APIException
-	{
-		// Re-initialize the member list for this project
-		List<Member> memberList = new ArrayList<Member>();
-		// Initialize the project config hash
-		Hashtable<String, String> pjConfigHash = new Hashtable<String, String>();
-		// Add the mapping for this project
-		pjConfigHash.put(projectName, fullConfigSyntax);
-		// Compute the project root directory
-		String projectRoot = projectName.substring(0, projectName.lastIndexOf('/'));
-		
-		// Now, lets parse this project
-		Command siViewProjectCmd = new Command(Command.SI, "viewproject");
-		siViewProjectCmd.addOption(new Option("recurse"));
-		siViewProjectCmd.addOption(new Option("project", fullConfigSyntax));
-		MultiValue mvFields = new MultiValue(",");
-		mvFields.add("name");
-		mvFields.add("context");
-		mvFields.add("memberrev");
-		mvFields.add("membertimestamp");
-		mvFields.add("memberdescription");
-		siViewProjectCmd.addOption(new Option("fields", mvFields));
-		api.getLogger().info("Preparing to execute si viewproject for " + fullConfigSyntax);
-		Response viewRes = api.runCommand(siViewProjectCmd);
-		
-		// Iterate through the list of members returned by the API
-		WorkItemIterator wit = viewRes.getWorkItems();
-		while( wit.hasNext() )
-		{
-			WorkItem wi = wit.next();
-			if( wi.getModelType().equals(SIModelTypeName.SI_SUBPROJECT) )
-			{
-				// Save the configuration path for the current subproject, using the canonical path name
-				pjConfigHash.put(wi.getField("name").getValueAsString(), wi.getId());
-			}
-			else if( wi.getModelType().equals(SIModelTypeName.MEMBER) )
-			{
-				// Figure out this member's parent project's canonical path name
-				String parentProject = wi.getField("parent").getValueAsString();
-				// Instantiate our Integrity CM Member object
-				Member iCMMember = new Member(wi, pjConfigHash.get(parentProject), projectRoot, workspaceDir);
-				// Add this to the full list of members in this project
-				memberList.add(iCMMember);
-			}
-			else
-			{
-				api.getLogger().warn("View project output contains an invalid model type: " + wi.getModelType());
-			}
-		}
-		
-		// Sort the files list...
-		Collections.sort(memberList, FILES_ORDER);
-		return memberList;
-	}
-	
-	/**
-	 * Performs a checkpoint on the Integrity SCM Project
-	 * @param message Checkpoint description
-	 * @param tag Checkpoint label
-	 * @return MKS API Response object
-	 * @throws APIException
-	 */
-    public Response checkpoint(String message, String tag) throws APIException
-    {
-		// Setup the checkpoint command
-		api.getLogger().debug("Checkpointing project " + fullConfigSyntax + " with label '" + tag + "'");
-		// Construct the checkpoint command
-		Command siCheckpoint = new Command(Command.SI, "checkpoint");
-		siCheckpoint.addOption(new Option("recurse"));		
-		// Set the project name
-		siCheckpoint.addOption(new Option("project", fullConfigSyntax));
-		// Set the label
-		siCheckpoint.addOption(new Option("label", tag));
-		// Set the description, if specified
-		if( null != message && message.length() > 0 )
-		{
-			siCheckpoint.addOption(new Option("description", message));
-		}
-		// Run the checkpoint command
-		return api.runCommand(siCheckpoint);
-    }	
-    
+    {
+        public int compare( Member cmm1, Member cmm2 )
+        {
+            return cmm1.getMemberName().compareToIgnoreCase( cmm2.getMemberName() );
+        }
+    };
+
+    /**
+     * Checks if the given value is a valid MKS Integrity Label.
+     * <br>If it's invalid, this method throws an exception providing the reason as string.
+     *
+     * @param tagName The checkpoint label name
+     * @return the error message, or null if label is valid
+     */
+    public static void validateTag( String tagName )
+        throws Exception
+    {
+        if ( tagName == null || tagName.length() == 0 )
+        {
+            throw new Exception( "The checkpoint label string is empty!" );
+        }
+
+        char ch = tagName.charAt( 0 );
+        if ( !( ( 'A' <= ch && ch <= 'Z' ) || ( 'a' <= ch && ch <= 'z' ) ) )
+        {
+            throw new Exception( "The checkpoint label must start with an alpha character!" );
+        }
+
+        for ( char invalid : "$,.:;/\\@".toCharArray() )
+        {
+            if ( tagName.indexOf( invalid ) >= 0 )
+            {
+                throw new Exception(
+                    "The checkpoint label may cannot contain one of the following characters: $ , . : ; / \\ @" );
+            }
+        }
+    }
+
+    /**
+     * Creates an instance of an Integrity SCM Project
+     *
+     * @param api        MKS API Session object
+     * @param configPath Configuration path for the MKS Integrity SCM Project
+     * @throws APIException
+     */
+    public Project( APISession api, String configPath )
+        throws APIException
+    {
+        // Initialize our local APISession
+        this.api = api;
+        try
+        {
+            // Get the project information for this project
+            Command siProjectInfoCmd = new Command( Command.SI, "projectinfo" );
+            siProjectInfoCmd.addOption( new Option( "project", configPath ) );
+            api.getLogger().info( "Preparing to execute si projectinfo for " + configPath );
+            Response infoRes = api.runCommand( siProjectInfoCmd );
+            // Get the only work item from the response
+            WorkItem wi = infoRes.getWorkItems().next();
+            // Get the metadata information about the project
+            Field pjNameFld = wi.getField( "projectName" );
+            Field pjTypeFld = wi.getField( "projectType" );
+            Field pjCfgPathFld = wi.getField( "fullConfigSyntax" );
+            Field pjChkptFld = wi.getField( "lastCheckpoint" );
+
+            // Convert to our class fields
+            // First obtain the project name field
+            if ( null != pjNameFld && null != pjNameFld.getValueAsString() )
+            {
+                projectName = pjNameFld.getValueAsString();
+            }
+            else
+            {
+                api.getLogger().warn( "Project info did not provide a value for the 'projectName' field!" );
+                projectName = "";
+            }
+            // Next, we'll need to know the project type
+            if ( null != pjTypeFld && null != pjTypeFld.getValueAsString() )
+            {
+                projectType = pjTypeFld.getValueAsString();
+                if ( isBuild() )
+                {
+                    // Next, we'll need to know the current build checkpoint for this configuration
+                    Field pjRevFld = wi.getField( "revision" );
+                    if ( null != pjRevFld && null != pjRevFld.getItem() )
+                    {
+                        projectRevision = pjRevFld.getItem().getId();
+                    }
+                    else
+                    {
+                        projectRevision = "";
+                        api.getLogger().warn( "Project info did not provide a vale for the 'revision' field!" );
+                    }
+                }
+            }
+            else
+            {
+                api.getLogger().warn( "Project info did not provide a value for the 'projectType' field!" );
+                projectType = "";
+            }
+            // Most important is the configuration path
+            if ( null != pjCfgPathFld && null != pjCfgPathFld.getValueAsString() )
+            {
+                fullConfigSyntax = pjCfgPathFld.getValueAsString();
+            }
+            else
+            {
+                api.getLogger().error( "Project info did not provide a value for the 'fullConfigSyntax' field!" );
+                fullConfigSyntax = "";
+            }
+            // Finally, we'll need to store the last checkpoint to figure out differences, etc.
+            if ( null != pjChkptFld && null != pjChkptFld.getDateTime() )
+            {
+                lastCheckpoint = pjChkptFld.getDateTime();
+            }
+            else
+            {
+                api.getLogger().warn( "Project info did not provide a value for the 'lastCheckpoint' field!" );
+                lastCheckpoint = Calendar.getInstance().getTime();
+            }
+        }
+        catch ( NoSuchElementException nsee )
+        {
+            api.getLogger().error( "Project info did not provide a value for field " + nsee.getMessage() );
+        }
+    }
+
+    /**
+     * Returns the project path for this Integrity SCM Project
+     *
+     * @return
+     */
+    public String getProjectName()
+    {
+        return projectName;
+    }
+
+    /**
+     * Returns the project revision for this Integrity SCM Project
+     *
+     * @return
+     */
+    public String getProjectRevision()
+    {
+        return projectRevision;
+    }
+
+    /**
+     * Returns true is this is a Normal Project
+     *
+     * @return
+     */
+    public boolean isNormal()
+    {
+        if ( projectType.equalsIgnoreCase( NORMAL_PROJECT ) )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if this is a Variant Project
+     *
+     * @return
+     */
+    public boolean isVariant()
+    {
+        if ( projectType.equalsIgnoreCase( VARIANT_PROJECT ) )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if this is a Build Project
+     *
+     * @return
+     */
+    public boolean isBuild()
+    {
+        if ( projectType.equalsIgnoreCase( BUILD_PROJECT ) )
+        {
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the Full Configuration Path for this Integrity SCM Project
+     *
+     * @return
+     */
+    public String getConfigurationPath()
+    {
+        return fullConfigSyntax;
+    }
+
+    /**
+     * Returns the date when the last checkpoint was performed on this Project
+     *
+     * @return
+     */
+    public Date getLastCheckpointDate()
+    {
+        return lastCheckpoint;
+    }
+
+    /**
+     * Parses the output from the si viewproject command to get a list of members
+     *
+     * @param workspaceDir The current workspace directory, which is required for an export
+     * @return The list of Member objects for this project
+     * @throws APIException
+     */
+    public List<Member> listFiles( String workspaceDir )
+        throws APIException
+    {
+        // Re-initialize the member list for this project
+        List<Member> memberList = new ArrayList<Member>();
+        // Initialize the project config hash
+        Hashtable<String, String> pjConfigHash = new Hashtable<String, String>();
+        // Add the mapping for this project
+        pjConfigHash.put( projectName, fullConfigSyntax );
+        // Compute the project root directory
+        String projectRoot = projectName.substring( 0, projectName.lastIndexOf( '/' ) );
+
+        // Now, lets parse this project
+        Command siViewProjectCmd = new Command( Command.SI, "viewproject" );
+        siViewProjectCmd.addOption( new Option( "recurse" ) );
+        siViewProjectCmd.addOption( new Option( "project", fullConfigSyntax ) );
+        MultiValue mvFields = new MultiValue( "," );
+        mvFields.add( "name" );
+        mvFields.add( "context" );
+        mvFields.add( "memberrev" );
+        mvFields.add( "membertimestamp" );
+        mvFields.add( "memberdescription" );
+        siViewProjectCmd.addOption( new Option( "fields", mvFields ) );
+        api.getLogger().info( "Preparing to execute si viewproject for " + fullConfigSyntax );
+        Response viewRes = api.runCommand( siViewProjectCmd );
+
+        // Iterate through the list of members returned by the API
+        WorkItemIterator wit = viewRes.getWorkItems();
+        while ( wit.hasNext() )
+        {
+            WorkItem wi = wit.next();
+            if ( wi.getModelType().equals( SIModelTypeName.SI_SUBPROJECT ) )
+            {
+                // Save the configuration path for the current subproject, using the canonical path name
+                pjConfigHash.put( wi.getField( "name" ).getValueAsString(), wi.getId() );
+            }
+            else if ( wi.getModelType().equals( SIModelTypeName.MEMBER ) )
+            {
+                // Figure out this member's parent project's canonical path name
+                String parentProject = wi.getField( "parent" ).getValueAsString();
+                // Instantiate our Integrity CM Member object
+                Member iCMMember = new Member( wi, pjConfigHash.get( parentProject ), projectRoot, workspaceDir );
+                // Add this to the full list of members in this project
+                memberList.add( iCMMember );
+            }
+            else
+            {
+                api.getLogger().warn( "View project output contains an invalid model type: " + wi.getModelType() );
+            }
+        }
+
+        // Sort the files list...
+        Collections.sort( memberList, FILES_ORDER );
+        return memberList;
+    }
+
+    /**
+     * Performs a checkpoint on the Integrity SCM Project
+     *
+     * @param message Checkpoint description
+     * @param tag     Checkpoint label
+     * @return MKS API Response object
+     * @throws APIException
+     */
+    public Response checkpoint( String message, String tag )
+        throws APIException
+    {
+        // Setup the checkpoint command
+        api.getLogger().debug( "Checkpointing project " + fullConfigSyntax + " with label '" + tag + "'" );
+        // Construct the checkpoint command
+        Command siCheckpoint = new Command( Command.SI, "checkpoint" );
+        siCheckpoint.addOption( new Option( "recurse" ) );
+        // Set the project name
+        siCheckpoint.addOption( new Option( "project", fullConfigSyntax ) );
+        // Set the label
+        siCheckpoint.addOption( new Option( "label", tag ) );
+        // Set the description, if specified
+        if ( null != message && message.length() > 0 )
+        {
+            siCheckpoint.addOption( new Option( "description", message ) );
+        }
+        // Run the checkpoint command
+        return api.runCommand( siCheckpoint );
+    }
+
     /**
      * Creates a Development Path (project branch) for the MKS Integrity SCM Project
+     *
      * @param devPath Development Path Name
      * @return MKS API Response object
      * @throws APIException
      */
-    public Response createDevPath(String devPath) throws APIException
+    public Response createDevPath( String devPath )
+        throws APIException
     {
-    	// First we need to obtain a checkpoint from the current configuration (normal or variant)
-    	String chkpt = projectRevision;
-    	if( ! isBuild() )
-    	{
-    		Response chkptRes = checkpoint("Pre-checkpoint for development path " + devPath, devPath + " Baseline");
-    		WorkItem wi = chkptRes.getWorkItem(fullConfigSyntax);
-    		chkpt = wi.getResult().getField("resultant").getItem().getId();
-    	}
-    	
-    	// Now lets setup the create development path command
-    	api.getLogger().debug("Creating development path '" + devPath + "' for project " + projectName + " at revision '" + chkpt + "'");
-		Command siCreateDevPath = new Command(Command.SI, "createdevpath");
-		siCreateDevPath.addOption(new Option("devpath", devPath));		
-		// Set the project name
-		siCreateDevPath.addOption(new Option("project", projectName));
-		// Set the checkpoint we want to create the development path from
-		siCreateDevPath.addOption(new Option("projectRevision", chkpt));
-		// Run the create development path command
-		return api.runCommand(siCreateDevPath);    	
+        // First we need to obtain a checkpoint from the current configuration (normal or variant)
+        String chkpt = projectRevision;
+        if ( !isBuild() )
+        {
+            Response chkptRes = checkpoint( "Pre-checkpoint for development path " + devPath, devPath + " Baseline" );
+            WorkItem wi = chkptRes.getWorkItem( fullConfigSyntax );
+            chkpt = wi.getResult().getField( "resultant" ).getItem().getId();
+        }
+
+        // Now lets setup the create development path command
+        api.getLogger().debug(
+            "Creating development path '" + devPath + "' for project " + projectName + " at revision '" + chkpt + "'" );
+        Command siCreateDevPath = new Command( Command.SI, "createdevpath" );
+        siCreateDevPath.addOption( new Option( "devpath", devPath ) );
+        // Set the project name
+        siCreateDevPath.addOption( new Option( "project", projectName ) );
+        // Set the checkpoint we want to create the development path from
+        siCreateDevPath.addOption( new Option( "projectRevision", chkpt ) );
+        // Run the create development path command
+        return api.runCommand( siCreateDevPath );
     }
 }
 

Modified: maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Sandbox.java
URL: http://svn.apache.org/viewvc/maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Sandbox.java?rev=1162334&r1=1162333&r2=1162334&view=diff
==============================================================================
--- maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Sandbox.java (original)
+++ maven/scm/trunk/maven-scm-providers/maven-scm-provider-integrity/src/main/java/org/apache/maven/scm/provider/integrity/Sandbox.java Sat Aug 27 12:39:21 2011
@@ -18,17 +18,23 @@ package org.apache.maven.scm.provider.in
  * specific language governing permissions and limitations
  * under the License.
  */
- 
+
 import com.mks.api.Command;
-import com.mks.api.Option;
 import com.mks.api.MultiValue;
+import com.mks.api.Option;
+import com.mks.api.response.APIException;
 import com.mks.api.response.Field;
+import com.mks.api.response.Item;
 import com.mks.api.response.Response;
-import com.mks.api.response.WorkItemIterator;
 import com.mks.api.response.WorkItem;
-import com.mks.api.response.Item;
+import com.mks.api.response.WorkItemIterator;
 import com.mks.api.si.SIModelTypeName;
-import com.mks.api.response.APIException;
+import org.apache.maven.scm.ChangeFile;
+import org.apache.maven.scm.ChangeSet;
+import org.apache.maven.scm.ScmFile;
+import org.apache.maven.scm.ScmFileStatus;
+import org.apache.maven.scm.command.changelog.ChangeLogSet;
+import org.codehaus.plexus.util.StringUtils;
 
 import java.io.File;
 import java.text.SimpleDateFormat;
@@ -38,35 +44,32 @@ import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 
-import org.apache.maven.scm.ChangeFile;
-import org.apache.maven.scm.ChangeSet;
-import org.apache.maven.scm.ScmFile;
-import org.apache.maven.scm.ScmFileStatus;
-import org.apache.maven.scm.command.changelog.ChangeLogSet;
-import org.codehaus.plexus.util.StringUtils;
-
 /**
  * This class represents an MKS Integrity Sandbox and provides an encapsulation
  * for executing typical Sandbox operations
- * @version $Id: Sandbox.java 1.11 2011/08/22 13:06:50EDT Cletus D'Souza (dsouza) Exp  $
+ *
  * @author <a href="mailto:cletus@mks.com">Cletus D'Souza</a>
- */ 
+ * @version $Id: Sandbox.java 1.11 2011/08/22 13:06:50EDT Cletus D'Souza (dsouza) Exp  $
+ * @since 1.6
+ */
 public class Sandbox
 {
-	// Our date format
-	public static final SimpleDateFormat RLOG_DATEFORMAT = new SimpleDateFormat("MMMMM d, yyyy - h:mm:ss a");
-	
-	// File Separator
-	private String fs = System.getProperty("file.separator");
-	
+    // Our date format
+    public static final SimpleDateFormat RLOG_DATEFORMAT = new SimpleDateFormat( "MMMMM d, yyyy - h:mm:ss a" );
+
+    // File Separator
+    private String fs = System.getProperty( "file.separator" );
+
     // MKS API Session Object
     private APISession api;
 
     // Other sandbox specific class variables
     private Project siProject;
+
     private String sandboxDir;
+
     private String cpid;
-    
+
     // Flag to indicate the overall add operation was successful
     private boolean addSuccess;
 
@@ -75,700 +78,774 @@ public class Sandbox
 
     /**
      * Fixes the default includes/excludes patterns for compatibility with MKS Integrity's 'si viewnonmembers' command
+     *
      * @param pattern String pattern representing the includes/excludes file/directory list
      */
-	public static String formatFilePatterns(String pattern)
-	{
-		StringBuilder sb = new StringBuilder();
-		if( null != pattern && pattern.length() > 0 )
-		{
-			String[] tokens = StringUtils.split(pattern, ",");
-			for( int i = 0; i < tokens.length; i++ )
-			{
-				String tkn = tokens[i].trim();
-				if( tkn.indexOf("file:") != 0 && tkn.indexOf("dir:") != 0 )
-				{
-					sb.append(tkn.indexOf('.') > 0 ? StringUtils.replaceOnce(tkn, "**/", "file:") : 
-													StringUtils.replaceOnce(tkn, "**/", "dir:"));
-				}
-				else
-				{
-					sb.append(tkn);
-				}
-				sb.append(i < tokens.length ? "," : "");
-			}
-		}
-		return sb.toString();
-	}
-    
-	/**
-	 * The Sandbox constructor 
-	 * @param api MKS API Session object
-	 * @param cmProject Project object
-	 * @param dir Absolute path to the location for the Sandbox directory
-	 */
-    public Sandbox(APISession api, Project cmProject, String dir)
+    public static String formatFilePatterns( String pattern )
+    {
+        StringBuilder sb = new StringBuilder();
+        if ( null != pattern && pattern.length() > 0 )
+        {
+            String[] tokens = StringUtils.split( pattern, "," );
+            for ( int i = 0; i < tokens.length; i++ )
+            {
+                String tkn = tokens[i].trim();
+                if ( tkn.indexOf( "file:" ) != 0 && tkn.indexOf( "dir:" ) != 0 )
+                {
+                    sb.append( tkn.indexOf( '.' ) > 0
+                                   ? StringUtils.replaceOnce( tkn, "**/", "file:" )
+                                   : StringUtils.replaceOnce( tkn, "**/", "dir:" ) );
+                }
+                else
+                {
+                    sb.append( tkn );
+                }
+                sb.append( i < tokens.length ? "," : "" );
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * The Sandbox constructor
+     *
+     * @param api       MKS API Session object
+     * @param cmProject Project object
+     * @param dir       Absolute path to the location for the Sandbox directory
+     */
+    public Sandbox( APISession api, Project cmProject, String dir )
     {
         siProject = cmProject;
         sandboxDir = dir;
         this.api = api;
-        cpid = System.getProperty("maven.scm.integrity.cpid");
-        cpid = ((null == cpid || cpid.length() == 0) ? ":none" : cpid);
+        cpid = System.getProperty( "maven.scm.integrity.cpid" );
+        cpid = ( ( null == cpid || cpid.length() == 0 ) ? ":none" : cpid );
         addSuccess = true;
         ciSuccess = true;
     }
-    
+
     /**
      * Attempts to figure out if the current sandbox already exists and is valid
+     *
      * @param sandbox The client-side fully qualified path to the sandbox pj
      * @return true/false depending on whether or not this location has a valid sandbox
      * @throws APIException
      */
-    private boolean isValidSandbox(String sandbox) throws APIException
+    private boolean isValidSandbox( String sandbox )
+        throws APIException
     {
-        Command cmd = new Command(Command.SI, "sandboxinfo");
-        cmd.addOption(new Option("sandbox", sandbox));
+        Command cmd = new Command( Command.SI, "sandboxinfo" );
+        cmd.addOption( new Option( "sandbox", sandbox ) );
 
-        api.getLogger().debug("Validating existing sandbox: " + sandbox);
-        Response res = api.runCommand(cmd);
+        api.getLogger().debug( "Validating existing sandbox: " + sandbox );
+        Response res = api.runCommand( cmd );
         WorkItemIterator wit = res.getWorkItems();
         try
         {
-	        WorkItem wi = wit.next();
-	        return wi.getField("fullConfigSyntax").getValueAsString().equalsIgnoreCase(siProject.getConfigurationPath());
+            WorkItem wi = wit.next();
+            return wi.getField( "fullConfigSyntax" ).getValueAsString().equalsIgnoreCase(
+                siProject.getConfigurationPath() );
         }
-        catch(APIException aex)
+        catch ( APIException aex )
         {
-        	ExceptionHandler eh = new ExceptionHandler(aex);
-        	api.getLogger().error("MKS API Exception: " + eh.getMessage());
-        	api.getLogger().debug(eh.getCommand() + " completed with exit code " + eh.getExitCode());
-        	return false;
+            ExceptionHandler eh = new ExceptionHandler( aex );
+            api.getLogger().error( "MKS API Exception: " + eh.getMessage() );
+            api.getLogger().debug( eh.getCommand() + " completed with exit code " + eh.getExitCode() );
+            return false;
         }
     }
-    
+
     /**
      * Inspects the MKS API Response object's Item field to determine whether or nor a working file delta exists
+     *
      * @param wfdelta MKS API Response object's Item representing the Working File Delta
      * @return true if the working file is a delta; false otherwise
      */
-    private boolean isDelta(Item wfdelta)
+    private boolean isDelta( Item wfdelta )
     {
         // Return false if there is no working file
-        if( wfdelta.getField("isDelta").getBoolean().booleanValue() )
+        if ( wfdelta.getField( "isDelta" ).getBoolean().booleanValue() )
         {
             return true;
         }
         else
         {
-        	return false;
+            return false;
         }
     }
-    
+
     /**
      * Executes a 'si add' command using the message for the description
+     *
      * @param memberFile Full path to the new member's location
-     * @param message Description for the new member's archive
+     * @param message    Description for the new member's archive
      * @return MKS API Response object
      * @throws APIException
      */
-    private Response add(File memberFile, String message) throws APIException
+    private Response add( File memberFile, String message )
+        throws APIException
     {
-		// Setup the add command    	
-        api.getLogger().info("Adding member: " + memberFile.getAbsolutePath());			
-        Command siAdd = new Command(Command.SI, "add");
-        siAdd.addOption(new Option("onExistingArchive", "sharearchive"));
-        siAdd.addOption(new Option("cpid", cpid));
-        if( null != message && message.length() > 0 ){ siAdd.addOption(new Option("description", message)); }
-        siAdd.addOption(new Option("cwd", memberFile.getParentFile().getAbsolutePath()));
-        siAdd.addSelection(memberFile.getName());
-        return api.runCommand(siAdd);
+        // Setup the add command
+        api.getLogger().info( "Adding member: " + memberFile.getAbsolutePath() );
+        Command siAdd = new Command( Command.SI, "add" );
+        siAdd.addOption( new Option( "onExistingArchive", "sharearchive" ) );
+        siAdd.addOption( new Option( "cpid", cpid ) );
+        if ( null != message && message.length() > 0 )
+        {
+            siAdd.addOption( new Option( "description", message ) );
+        }
+        siAdd.addOption( new Option( "cwd", memberFile.getParentFile().getAbsolutePath() ) );
+        siAdd.addSelection( memberFile.getName() );
+        return api.runCommand( siAdd );
     }
-    
+
     /**
      * Executes a 'si ci' command using the relativeName for the member name and message for the description
-     * @param memberFile Full path to the member's current sandbox location
+     *
+     * @param memberFile   Full path to the member's current sandbox location
      * @param relativeName Relative path from the nearest subproject or project
-     * @param message Description for checking in the new update
+     * @param message      Description for checking in the new update
      * @return MKS API Response object
      * @throws APIException
      */
-    private Response checkin(File memberFile, String relativeName, String message) throws APIException
+    private Response checkin( File memberFile, String relativeName, String message )
+        throws APIException
     {
-		// Setup the check-in command    	
-        api.getLogger().info("Checking in member:  " + memberFile.getAbsolutePath());			
-        Command sici = new Command(Command.SI, "ci");
-        sici.addOption(new Option("cpid", cpid));
-        if( null != message && message.length() > 0 ){ sici.addOption(new Option("description", message)); }
-        sici.addOption(new Option("cwd", memberFile.getParentFile().getAbsolutePath()));
-        sici.addSelection(relativeName);
-        return api.runCommand(sici);
+        // Setup the check-in command
+        api.getLogger().info( "Checking in member:  " + memberFile.getAbsolutePath() );
+        Command sici = new Command( Command.SI, "ci" );
+        sici.addOption( new Option( "cpid", cpid ) );
+        if ( null != message && message.length() > 0 )
+        {
+            sici.addOption( new Option( "description", message ) );
+        }
+        sici.addOption( new Option( "cwd", memberFile.getParentFile().getAbsolutePath() ) );
+        sici.addSelection( relativeName );
+        return api.runCommand( sici );
     }
-    
+
     /**
      * Executes a 'si drop' command using the relativeName for the member name
-     * @param memberFile Full path to the member's current sandbox location
+     *
+     * @param memberFile   Full path to the member's current sandbox location
      * @param relativeName Relative path from the nearest subproject or project
      * @return MKS API Response object
      * @throws APIException
      */
-    private Response dropMember(File memberFile, String relativeName) throws APIException
+    private Response dropMember( File memberFile, String relativeName )
+        throws APIException
     {
-		// Setup the drop command    	
-        api.getLogger().info("Dropping member " + memberFile.getAbsolutePath());			    		
-        Command siDrop = new Command(Command.SI, "drop");
-        siDrop.addOption(new Option("cwd", memberFile.getParentFile().getAbsolutePath()));
-        siDrop.addOption(new Option("noconfirm"));
-        siDrop.addOption(new Option("cpid", cpid));
-        siDrop.addOption(new Option("delete"));
-        siDrop.addSelection(relativeName);
-        return api.runCommand(siDrop);
-    }    
-    
+        // Setup the drop command
+        api.getLogger().info( "Dropping member " + memberFile.getAbsolutePath() );
+        Command siDrop = new Command( Command.SI, "drop" );
+        siDrop.addOption( new Option( "cwd", memberFile.getParentFile().getAbsolutePath() ) );
+        siDrop.addOption( new Option( "noconfirm" ) );
+        siDrop.addOption( new Option( "cpid", cpid ) );
+        siDrop.addOption( new Option( "delete" ) );
+        siDrop.addSelection( relativeName );
+        return api.runCommand( siDrop );
+    }
+
     /**
      * Executes a 'si diff' command to see if the working file has actually changed.  Even though the
      * working file delta might be true, that doesn't always mean the file has actually changed.
-     * @param memberFile Full path to the member's current sandbox location
+     *
+     * @param memberFile   Full path to the member's current sandbox location
      * @param relativeName Relative path from the nearest subproject or project
      * @return MKS API Response object
      */
-    private boolean hasMemberChanged(File memberFile, String relativeName)
+    private boolean hasMemberChanged( File memberFile, String relativeName )
     {
-    	// Setup the differences command
-		Command siDiff = new Command(Command.SI, "diff");
-		siDiff.addOption(new Option("cwd", memberFile.getParentFile().getAbsolutePath()));
-		siDiff.addSelection(relativeName);
-		try
-		{
-			// Run the diff command...
-			Response res = api.runCommand(siDiff);
-			try
-			{
-				// Return the changed flag...
-				return res.getWorkItems().next().getResult().getField("resultant").getItem().getField("different").getBoolean().booleanValue();
-			}
-			catch(NullPointerException npe)
-			{
-	    		api.getLogger().warn("Couldn't figure out differences for file: " + memberFile.getAbsolutePath());
-				api.getLogger().warn("Null value found along response object for WorkItem/Result/Field/Item/Field.getBoolean()");
-				api.getLogger().warn("Proceeding with the assumption that the file has changed!");				
-			}
-		}
-		catch(APIException aex)
-		{
-    		ExceptionHandler eh = new ExceptionHandler(aex);
-    		api.getLogger().warn("Couldn't figure out differences for file: " + memberFile.getAbsolutePath());
-			api.getLogger().warn(eh.getMessage());
-			api.getLogger().warn("Proceeding with the assumption that the file has changed!");
-			api.getLogger().debug(eh.getCommand() + " completed with exit Code " + eh.getExitCode());			
-		}
-		return true;	
+        // Setup the differences command
+        Command siDiff = new Command( Command.SI, "diff" );
+        siDiff.addOption( new Option( "cwd", memberFile.getParentFile().getAbsolutePath() ) );
+        siDiff.addSelection( relativeName );
+        try
+        {
+            // Run the diff command...
+            Response res = api.runCommand( siDiff );
+            try
+            {
+                // Return the changed flag...
+                return res.getWorkItems().next().getResult().getField( "resultant" ).getItem().getField(
+                    "different" ).getBoolean().booleanValue();
+            }
+            catch ( NullPointerException npe )
+            {
+                api.getLogger().warn( "Couldn't figure out differences for file: " + memberFile.getAbsolutePath() );
+                api.getLogger().warn(
+                    "Null value found along response object for WorkItem/Result/Field/Item/Field.getBoolean()" );
+                api.getLogger().warn( "Proceeding with the assumption that the file has changed!" );
+            }
+        }
+        catch ( APIException aex )
+        {
+            ExceptionHandler eh = new ExceptionHandler( aex );
+            api.getLogger().warn( "Couldn't figure out differences for file: " + memberFile.getAbsolutePath() );
+            api.getLogger().warn( eh.getMessage() );
+            api.getLogger().warn( "Proceeding with the assumption that the file has changed!" );
+            api.getLogger().debug( eh.getCommand() + " completed with exit Code " + eh.getExitCode() );
+        }
+        return true;
     }
-    	
+
     /**
      * Returns the full path name to the current Sandbox directory
+     *
      * @return
      */
     public String getSandboxDir()
     {
-    	return sandboxDir;
+        return sandboxDir;
     }
-    
+
     /**
      * Executes a 'si lock' command using the relativeName of the file
-     * @param memberFile Full path to the member's current sandbox location
+     *
+     * @param memberFile   Full path to the member's current sandbox location
+     * @param relativeName Relative path from the nearest subproject or project
+     * @return MKS API Response object
+     * @throws APIException
+     */
+    public Response lock( File memberFile, String relativeName )
+        throws APIException
+    {
+        // Setup the lock command
+        api.getLogger().debug( "Locking member: " + memberFile.getAbsolutePath() );
+        Command siLock = new Command( Command.SI, "lock" );
+        siLock.addOption( new Option( "revision", ":member" ) );
+        siLock.addOption( new Option( "cpid", cpid ) );
+        siLock.addOption( new Option( "cwd", memberFile.getParentFile().getAbsolutePath() ) );
+        siLock.addSelection( relativeName );
+        // Execute the lock command
+        return api.runCommand( siLock );
+    }
+
+    /**
+     * Executes a 'si unlock' command using the relativeName of the file
+     *
+     * @param memberFile   Full path to the member's current sandbox location
      * @param relativeName Relative path from the nearest subproject or project
      * @return MKS API Response object
      * @throws APIException
      */
-	public Response lock(File memberFile, String relativeName) throws APIException
-	{
-		// Setup the lock command
-        api.getLogger().debug("Locking member: " + memberFile.getAbsolutePath());			
-		Command siLock = new Command(Command.SI, "lock");
-		siLock.addOption(new Option("revision", ":member"));
-		siLock.addOption(new Option("cpid", cpid));
-		siLock.addOption(new Option("cwd", memberFile.getParentFile().getAbsolutePath()));
-		siLock.addSelection(relativeName);
-		// Execute the lock command
-		return api.runCommand(siLock);
-	}
-
-	/**
-	 * Executes a 'si unlock' command using the relativeName of the file
-	 * @param memberFile Full path to the member's current sandbox location
-	 * @param relativeName Relative path from the nearest subproject or project
-	 * @return MKS API Response object
-	 * @throws APIException
-	 */
-	public Response unlock(File memberFile, String relativeName) throws APIException
-	{
-		// Setup the unlock command
-        api.getLogger().debug("Unlocking member: " + memberFile.getAbsolutePath());			
-		Command siUnlock = new Command(Command.SI, "unlock");
-		siUnlock.addOption(new Option("revision", ":member"));
-		siUnlock.addOption(new Option("action", "remove"));
-		siUnlock.addOption(new Option("cwd", memberFile.getParentFile().getAbsolutePath()));
-		siUnlock.addSelection(relativeName);
-		// Execute the unlock command
-		return api.runCommand(siUnlock);
-	}
-	
+    public Response unlock( File memberFile, String relativeName )
+        throws APIException
+    {
+        // Setup the unlock command
+        api.getLogger().debug( "Unlocking member: " + memberFile.getAbsolutePath() );
+        Command siUnlock = new Command( Command.SI, "unlock" );
+        siUnlock.addOption( new Option( "revision", ":member" ) );
+        siUnlock.addOption( new Option( "action", "remove" ) );
+        siUnlock.addOption( new Option( "cwd", memberFile.getParentFile().getAbsolutePath() ) );
+        siUnlock.addSelection( relativeName );
+        // Execute the unlock command
+        return api.runCommand( siUnlock );
+    }
+
     /**
      * Removes the registration for the Sandbox in the user's profile
+     *
      * @return The API Response associated with executing this command
-     * @throws APIException 
+     * @throws APIException
      */
-    public Response drop() throws APIException
+    public Response drop()
+        throws APIException
     {
-    	File project = new File(siProject.getProjectName());
-    	File sandboxpj = new File(sandboxDir + fs + project.getName());
-    	
-    	// Check to see if the sandbox file already exists and its OK to use
-    	api.getLogger().debug("Sandbox Project File: " + sandboxpj.getAbsolutePath());    	
-		Command cmd = new Command(Command.SI, "dropsandbox");
-		cmd.addOption(new Option("delete", "members"));
-		cmd.addOption(new Option("sandbox", sandboxpj.getAbsolutePath()));    			
-		cmd.addOption(new Option("cwd", sandboxDir));
-		return api.runCommand(cmd);
+        File project = new File( siProject.getProjectName() );
+        File sandboxpj = new File( sandboxDir + fs + project.getName() );
+
+        // Check to see if the sandbox file already exists and its OK to use
+        api.getLogger().debug( "Sandbox Project File: " + sandboxpj.getAbsolutePath() );
+        Command cmd = new Command( Command.SI, "dropsandbox" );
+        cmd.addOption( new Option( "delete", "members" ) );
+        cmd.addOption( new Option( "sandbox", sandboxpj.getAbsolutePath() ) );
+        cmd.addOption( new Option( "cwd", sandboxDir ) );
+        return api.runCommand( cmd );
     }
-    
+
     /**
      * Creates a new Sandbox in the sandboxDir specified
+     *
      * @return true if the operation is successful; false otherwise
-     * @throws APIException 
+     * @throws APIException
      */
-    public boolean create() throws APIException
+    public boolean create()
+        throws APIException
     {
-    	File project = new File(siProject.getProjectName());
-    	File sandboxpj = new File(sandboxDir + fs + project.getName());
-    	
-    	// Check to see if the sandbox file already exists and its OK to use
-    	api.getLogger().debug("Sandbox Project File: " + sandboxpj.getAbsolutePath());    	
-    	if( sandboxpj.isFile() )
-    	{
-    		// Validate this sandbox
-    		if( isValidSandbox(sandboxpj.getAbsolutePath()) )
-    		{
-    			api.getLogger().debug("Reusing existing Sandbox in " + sandboxDir + " for project " + siProject.getConfigurationPath());
-    			return true;
-    		}
-    		else
-    		{
-    			api.getLogger().error("An invalid Sandbox exists in " + sandboxDir + ". Please provide a different location!");
-    			return false;
-    		}
-    	}
-    	else // Create a new sandbox in the location specified
-    	{
-    		api.getLogger().debug("Creating Sandbox in " + sandboxDir + " for project " + siProject.getConfigurationPath());
-    		try
-    		{
-    			Command cmd = new Command(Command.SI, "createsandbox");
-    			cmd.addOption(new Option("recurse"));
-    			cmd.addOption(new Option("nopopulate"));
-    			cmd.addOption(new Option("project", siProject.getConfigurationPath()));
-    			cmd.addOption(new Option("cwd", sandboxDir));
-    			api.runCommand(cmd);
-    		}
-    		catch(APIException aex)
-    		{
-    			// Check to see if this exception is due an existing sandbox registry entry
-    			ExceptionHandler eh = new ExceptionHandler(aex);
-    			if( eh.getMessage().indexOf("There is already a registered entry") > 0 )
-    			{
-    				// This will re-validate the sandbox, if Maven blew away the old directory
-    				return create();
-    			}
-    			else
-    			{
-    				throw aex;
-    			}
-    		}
-    		return true;
-    	}
+        File project = new File( siProject.getProjectName() );
+        File sandboxpj = new File( sandboxDir + fs + project.getName() );
+
+        // Check to see if the sandbox file already exists and its OK to use
+        api.getLogger().debug( "Sandbox Project File: " + sandboxpj.getAbsolutePath() );
+        if ( sandboxpj.isFile() )
+        {
+            // Validate this sandbox
+            if ( isValidSandbox( sandboxpj.getAbsolutePath() ) )
+            {
+                api.getLogger().debug(
+                    "Reusing existing Sandbox in " + sandboxDir + " for project " + siProject.getConfigurationPath() );
+                return true;
+            }
+            else
+            {
+                api.getLogger().error(
+                    "An invalid Sandbox exists in " + sandboxDir + ". Please provide a different location!" );
+                return false;
+            }
+        }
+        else // Create a new sandbox in the location specified
+        {
+            api.getLogger().debug(
+                "Creating Sandbox in " + sandboxDir + " for project " + siProject.getConfigurationPath() );
+            try
+            {
+                Command cmd = new Command( Command.SI, "createsandbox" );
+                cmd.addOption( new Option( "recurse" ) );
+                cmd.addOption( new Option( "nopopulate" ) );
+                cmd.addOption( new Option( "project", siProject.getConfigurationPath() ) );
+                cmd.addOption( new Option( "cwd", sandboxDir ) );
+                api.runCommand( cmd );
+            }
+            catch ( APIException aex )
+            {
+                // Check to see if this exception is due an existing sandbox registry entry
+                ExceptionHandler eh = new ExceptionHandler( aex );
+                if ( eh.getMessage().indexOf( "There is already a registered entry" ) > 0 )
+                {
+                    // This will re-validate the sandbox, if Maven blew away the old directory
+                    return create();
+                }
+                else
+                {
+                    throw aex;
+                }
+            }
+            return true;
+        }
     }
 
     /**
      * Resynchronizes an existing Sandbox
      * Assumes that the create() call has already been made to validate this sandbox
-     * @throws APIException 
+     *
+     * @throws APIException
      */
-    public Response resync() throws APIException
+    public Response resync()
+        throws APIException
     {
-		api.getLogger().debug("Resynchronizing Sandbox in " + sandboxDir + " for project " + siProject.getConfigurationPath());
-		Command cmd = new Command(Command.SI, "resync");
-		cmd.addOption(new Option("recurse"));
-		cmd.addOption(new Option("populate"));
-		cmd.addOption(new Option("cwd", sandboxDir));
-		return api.runCommand(cmd);
+        api.getLogger().debug(
+            "Resynchronizing Sandbox in " + sandboxDir + " for project " + siProject.getConfigurationPath() );
+        Command cmd = new Command( Command.SI, "resync" );
+        cmd.addOption( new Option( "recurse" ) );
+        cmd.addOption( new Option( "populate" ) );
+        cmd.addOption( new Option( "cwd", sandboxDir ) );
+        return api.runCommand( cmd );
     }
 
     /**
      * Executes a 'si makewritable' command to allow edits to all files in the Sandbox directory
+     *
      * @return MKS API Response object
      * @throws APIException
      */
-    public Response makeWriteable() throws APIException
+    public Response makeWriteable()
+        throws APIException
     {
-		api.getLogger().debug("Setting files to writeable in " + sandboxDir + " for project " + siProject.getConfigurationPath());
-		Command cmd = new Command(Command.SI, "makewritable");
-		cmd.addOption(new Option("recurse"));
-		cmd.addOption(new Option("cwd", sandboxDir));
-		return api.runCommand(cmd);    	
+        api.getLogger().debug(
+            "Setting files to writeable in " + sandboxDir + " for project " + siProject.getConfigurationPath() );
+        Command cmd = new Command( Command.SI, "makewritable" );
+        cmd.addOption( new Option( "recurse" ) );
+        cmd.addOption( new Option( "cwd", sandboxDir ) );
+        return api.runCommand( cmd );
     }
 
     /**
      * Executes a 'si revert' command to roll back changes to all files in the Sandbox directory
+     *
      * @return MKS API Response object
      * @throws APIException
      */
-    public Response revertMembers() throws APIException
+    public Response revertMembers()
+        throws APIException
     {
-		api.getLogger().debug("Reverting changes in sandbox " + sandboxDir + " for project " + siProject.getConfigurationPath());
-		Command cmd = new Command(Command.SI, "revert");
-		cmd.addOption(new Option("recurse"));
-		cmd.addOption(new Option("cwd", sandboxDir));
-		return api.runCommand(cmd);    	
+        api.getLogger().debug(
+            "Reverting changes in sandbox " + sandboxDir + " for project " + siProject.getConfigurationPath() );
+        Command cmd = new Command( Command.SI, "revert" );
+        cmd.addOption( new Option( "recurse" ) );
+        cmd.addOption( new Option( "cwd", sandboxDir ) );
+        return api.runCommand( cmd );
     }
-    
+
     /**
      * Executes a 'si viewnonmembers' command filtering the results using the exclude and include lists
+     *
      * @param exclude Pattern containing the exclude file list
      * @param include Pattern containing the include file list
      * @return List of ScmFile objects representing the new files in the Sandbox
      * @throws APIException
      */
-    public List<ScmFile> getNewMembers(String exclude, String include) throws APIException
+    public List<ScmFile> getNewMembers( String exclude, String include )
+        throws APIException
     {
-    	// Store a list of files that were added to the repository
-    	List<ScmFile> filesAdded = new ArrayList<ScmFile>();    	
-    	Command siViewNonMem = new Command(Command.SI, "viewnonmembers");
-        siViewNonMem.addOption(new Option("recurse"));
-        if( null != exclude && exclude.length() > 0 ){ siViewNonMem.addOption(new Option("exclude", exclude)); }
-        if( null != include && include.length() > 0 ){ siViewNonMem.addOption(new Option("include", include)); }       
-        siViewNonMem.addOption(new Option("noincludeFormers"));
-        siViewNonMem.addOption(new Option("cwd", sandboxDir));
-        Response response = api.runCommand(siViewNonMem);
-        for(WorkItemIterator wit = response.getWorkItems(); wit.hasNext();)
+        // Store a list of files that were added to the repository
+        List<ScmFile> filesAdded = new ArrayList<ScmFile>();
+        Command siViewNonMem = new Command( Command.SI, "viewnonmembers" );
+        siViewNonMem.addOption( new Option( "recurse" ) );
+        if ( null != exclude && exclude.length() > 0 )
+        {
+            siViewNonMem.addOption( new Option( "exclude", exclude ) );
+        }
+        if ( null != include && include.length() > 0 )
         {
-        	filesAdded.add(new ScmFile(wit.next().getField("absolutepath").getValueAsString(), ScmFileStatus.ADDED));
+            siViewNonMem.addOption( new Option( "include", include ) );
+        }
+        siViewNonMem.addOption( new Option( "noincludeFormers" ) );
+        siViewNonMem.addOption( new Option( "cwd", sandboxDir ) );
+        Response response = api.runCommand( siViewNonMem );
+        for ( WorkItemIterator wit = response.getWorkItems(); wit.hasNext(); )
+        {
+            filesAdded.add(
+                new ScmFile( wit.next().getField( "absolutepath" ).getValueAsString(), ScmFileStatus.ADDED ) );
         }
         return filesAdded;
-    	
+
     }
-    
+
     /**
      * Adds a list of files to the MKS Integrity SCM Project
+     *
      * @param exclude Pattern containing the exclude file list
      * @param include Pattern containing the include file list
      * @param message Description for the member's archive
      * @return
      */
-    public List<ScmFile> addNonMembers(String exclude, String include, String message)
+    public List<ScmFile> addNonMembers( String exclude, String include, String message )
     {
-    	// Re-initialize the overall addSuccess to be true for now
-    	addSuccess = true;
-    	// Store a list of files that were actually added to the repository
-    	List<ScmFile> filesAdded = new ArrayList<ScmFile>();
-    	api.getLogger().debug("Looking for new members in sandbox dir: " + sandboxDir);
+        // Re-initialize the overall addSuccess to be true for now
+        addSuccess = true;
+        // Store a list of files that were actually added to the repository
+        List<ScmFile> filesAdded = new ArrayList<ScmFile>();
+        api.getLogger().debug( "Looking for new members in sandbox dir: " + sandboxDir );
         try
         {
-        	List<ScmFile> newFileList = getNewMembers(exclude, include);
-	        for( Iterator<ScmFile> sit = newFileList.iterator(); sit.hasNext();)
-	        {
-	        	try
-	        	{
-	        		ScmFile localFile = sit.next();
-	        		// Attempt to add the file to the Integrity repository
-	        		add(new File(localFile.getPath()), message);
-	        		// If it was a success, then add it to the list of files that were actually added
-	        		filesAdded.add(localFile);
-	        	}
-	            catch(APIException aex)
-	            {
-	            	// Set the addSuccess to false, since we ran into a problem
-	            	addSuccess = false;
-	        		ExceptionHandler eh = new ExceptionHandler(aex);
-	    			api.getLogger().error("MKS API Exception: " + eh.getMessage());
-	    			api.getLogger().debug(eh.getCommand() + " completed with exit Code " + eh.getExitCode());
-	            }	        	
-	        }
-    	}
-        catch(APIException aex)
-        {
-        	// Set the addSuccess to false, since we ran into a problem
-        	addSuccess = false;
-    		ExceptionHandler eh = new ExceptionHandler(aex);
-			api.getLogger().error("MKS API Exception: " + eh.getMessage());
-			api.getLogger().debug(eh.getCommand() + " completed with exit Code " + eh.getExitCode());
+            List<ScmFile> newFileList = getNewMembers( exclude, include );
+            for ( Iterator<ScmFile> sit = newFileList.iterator(); sit.hasNext(); )
+            {
+                try
+                {
+                    ScmFile localFile = sit.next();
+                    // Attempt to add the file to the Integrity repository
+                    add( new File( localFile.getPath() ), message );
+                    // If it was a success, then add it to the list of files that were actually added
+                    filesAdded.add( localFile );
+                }
+                catch ( APIException aex )
+                {
+                    // Set the addSuccess to false, since we ran into a problem
+                    addSuccess = false;
+                    ExceptionHandler eh = new ExceptionHandler( aex );
+                    api.getLogger().error( "MKS API Exception: " + eh.getMessage() );
+                    api.getLogger().debug( eh.getCommand() + " completed with exit Code " + eh.getExitCode() );
+                }
+            }
+        }
+        catch ( APIException aex )
+        {
+            // Set the addSuccess to false, since we ran into a problem
+            addSuccess = false;
+            ExceptionHandler eh = new ExceptionHandler( aex );
+            api.getLogger().error( "MKS API Exception: " + eh.getMessage() );
+            api.getLogger().debug( eh.getCommand() + " completed with exit Code " + eh.getExitCode() );
         }
         return filesAdded;
     }
 
     /**
      * Returns the overall success of the add operation
+     *
      * @return
      */
     public boolean getOverallAddSuccess()
     {
-    	return addSuccess;
+        return addSuccess;
     }
 
     /**
      * Inspects the MKS API Response object's Item field to determine whether or nor a working file exists
+     *
      * @param wfdelta MKS API Response object's Item representing the Working File Delta
      * @return
      */
-    public boolean hasWorkingFile(Item wfdelta)
+    public boolean hasWorkingFile( Item wfdelta )
     {
         // Return false if there is no working file
-        if( wfdelta.getField("noWorkingFile").getBoolean().booleanValue() )
+        if ( wfdelta.getField( "noWorkingFile" ).getBoolean().booleanValue() )
         {
             return false;
         }
         else
         {
-        	return true;
+            return true;
         }
     }
-    
+
     /**
      * Executes a 'si viewsandbox' and parses the output for changed or dropped working files
+     *
      * @return A list of MKS API Response WorkItem objects representing the changes in the Sandbox
      * @throws APIException
      */
-    public List<WorkItem> getChangeList() throws APIException
+    public List<WorkItem> getChangeList()
+        throws APIException
     {
-    	// Store a list of files that were changed/removed to the repository
-    	List<WorkItem> changedFiles = new ArrayList<WorkItem>();
-    	// Setup the view sandbox command to figure out what has changed...
-        Command siViewSandbox = new Command(Command.SI, "viewsandbox");
+        // Store a list of files that were changed/removed to the repository
+        List<WorkItem> changedFiles = new ArrayList<WorkItem>();
+        // Setup the view sandbox command to figure out what has changed...
+        Command siViewSandbox = new Command( Command.SI, "viewsandbox" );
         // Create the --fields option
-        MultiValue mv = new MultiValue(",");
-        mv.add("name");
-        mv.add("context");
-        mv.add("wfdelta");
-        mv.add("memberarchive");
-        siViewSandbox.addOption(new Option("fields", mv));
-        siViewSandbox.addOption(new Option("recurse"));
-        siViewSandbox.addOption(new Option("noincludeDropped"));
-        siViewSandbox.addOption(new Option("filterSubs"));
-        siViewSandbox.addOption(new Option("cwd", sandboxDir));
-        
+        MultiValue mv = new MultiValue( "," );
+        mv.add( "name" );
+        mv.add( "context" );
+        mv.add( "wfdelta" );
+        mv.add( "memberarchive" );
+        siViewSandbox.addOption( new Option( "fields", mv ) );
+        siViewSandbox.addOption( new Option( "recurse" ) );
+        siViewSandbox.addOption( new Option( "noincludeDropped" ) );
+        siViewSandbox.addOption( new Option( "filterSubs" ) );
+        siViewSandbox.addOption( new Option( "cwd", sandboxDir ) );
+
         // Run the view sandbox command
-        Response r = api.runCommand(siViewSandbox);
+        Response r = api.runCommand( siViewSandbox );
         // Check-in all changed files, drop all members with missing working files
-        for( WorkItemIterator wit = r.getWorkItems(); wit.hasNext(); )
+        for ( WorkItemIterator wit = r.getWorkItems(); wit.hasNext(); )
         {
             WorkItem wi = wit.next();
-            api.getLogger().debug("Inspecting file: " + wi.getField("name").getValueAsString());
-            
-            if( wi.getModelType().equals(SIModelTypeName.MEMBER) )
-            {
-            	Item wfdeltaItem = (Item)wi.getField("wfdelta").getValue();
-            	// Proceed with this entry only if it is an actual working file delta
-            	if( isDelta(wfdeltaItem) )
-            	{
-	                File memberFile = new File(wi.getField("name").getValueAsString());
-	                if( hasWorkingFile(wfdeltaItem) )
-	                {
-	            		// Only report on files that have actually changed...                	
-	                	if( hasMemberChanged(memberFile, wi.getId()) )
-	                	{
-	                		changedFiles.add(wi);		                		
-	                	}
-	                }
-	                else
-	                {
-	            		// Also report on dropped files
-	            		changedFiles.add(wi);		                		
-	                }
-            	}
+            api.getLogger().debug( "Inspecting file: " + wi.getField( "name" ).getValueAsString() );
+
+            if ( wi.getModelType().equals( SIModelTypeName.MEMBER ) )
+            {
+                Item wfdeltaItem = (Item) wi.getField( "wfdelta" ).getValue();
+                // Proceed with this entry only if it is an actual working file delta
+                if ( isDelta( wfdeltaItem ) )
+                {
+                    File memberFile = new File( wi.getField( "name" ).getValueAsString() );
+                    if ( hasWorkingFile( wfdeltaItem ) )
+                    {
+                        // Only report on files that have actually changed...
+                        if ( hasMemberChanged( memberFile, wi.getId() ) )
+                        {
+                            changedFiles.add( wi );
+                        }
+                    }
+                    else
+                    {
+                        // Also report on dropped files
+                        changedFiles.add( wi );
+                    }
+                }
             }
         }
         return changedFiles;
     }
-    
+
     /**
      * Wrapper function to check-in all changes and drop members associated with missing working files
+     *
      * @param message Description for the changes
      * @return
      */
-    public List<ScmFile> checkInUpdates(String message)
+    public List<ScmFile> checkInUpdates( String message )
     {
-    	// Re-initialize the overall ciSuccess to be true for now
-    	ciSuccess = true;
-    	// Store a list of files that were changed/removed to the repository
-    	List<ScmFile> changedFiles = new ArrayList<ScmFile>();
-    	api.getLogger().debug("Looking for changed and dropped members in sandbox dir: " + sandboxDir);
-    	
+        // Re-initialize the overall ciSuccess to be true for now
+        ciSuccess = true;
+        // Store a list of files that were changed/removed to the repository
+        List<ScmFile> changedFiles = new ArrayList<ScmFile>();
+        api.getLogger().debug( "Looking for changed and dropped members in sandbox dir: " + sandboxDir );
+
         try
         {
-	        // Let the list of changed files
-        	List<WorkItem> changeList = getChangeList();
-	        // Check-in all changed files, drop all members with missing working files
-	        for( Iterator<WorkItem> wit = changeList.iterator(); wit.hasNext(); )
-	        {
-	        	try
-	        	{
-	        		WorkItem wi = wit.next();
-	        		File memberFile = new File(wi.getField("name").getValueAsString());
-            		// Check-in files that have actually changed...
-	        		if( hasWorkingFile((Item)wi.getField("wfdelta").getValue()) )
-	        		{
-                		// Lock each member as you go...
-                		lock(memberFile, wi.getId());
-                		// Commit the changes...
-                		checkin(memberFile, wi.getId(), message);
-                		// Update the changed file list
-                		changedFiles.add(new ScmFile(memberFile.getAbsolutePath(), ScmFileStatus.CHECKED_IN));		                		
-                	}
-	                else
-	                {
-	                    // Drop the member if there is no working file
-	                    dropMember(memberFile, wi.getId());
-                		// Update the changed file list
-	                    changedFiles.add(new ScmFile(memberFile.getAbsolutePath(), ScmFileStatus.DELETED));		                		
-	                }
-	        	}
-	            catch(APIException aex)
-	            {
-	            	// Set the ciSuccess to false, since we ran into a problem
-	            	ciSuccess = false;
-	        		ExceptionHandler eh = new ExceptionHandler(aex);
-	    			api.getLogger().error("MKS API Exception: " + eh.getMessage());
-	    			api.getLogger().debug(eh.getCommand() + " completed with exit Code " + eh.getExitCode());
-	            }	        	
-	        }
-        }
-        catch(APIException aex)
-        {
-        	// Set the ciSuccess to false, since we ran into a problem
-        	ciSuccess = false;
-    		ExceptionHandler eh = new ExceptionHandler(aex);
-			api.getLogger().error("MKS API Exception: " + eh.getMessage());
-			api.getLogger().debug(eh.getCommand() + " completed with exit Code " + eh.getExitCode());
-        }        
-        
+            // Let the list of changed files
+            List<WorkItem> changeList = getChangeList();
+            // Check-in all changed files, drop all members with missing working files
+            for ( Iterator<WorkItem> wit = changeList.iterator(); wit.hasNext(); )
+            {
+                try
+                {
+                    WorkItem wi = wit.next();
+                    File memberFile = new File( wi.getField( "name" ).getValueAsString() );
+                    // Check-in files that have actually changed...
+                    if ( hasWorkingFile( (Item) wi.getField( "wfdelta" ).getValue() ) )
+                    {
+                        // Lock each member as you go...
+                        lock( memberFile, wi.getId() );
+                        // Commit the changes...
+                        checkin( memberFile, wi.getId(), message );
+                        // Update the changed file list
+                        changedFiles.add( new ScmFile( memberFile.getAbsolutePath(), ScmFileStatus.CHECKED_IN ) );
+                    }
+                    else
+                    {
+                        // Drop the member if there is no working file
+                        dropMember( memberFile, wi.getId() );
+                        // Update the changed file list
+                        changedFiles.add( new ScmFile( memberFile.getAbsolutePath(), ScmFileStatus.DELETED ) );
+                    }
+                }
+                catch ( APIException aex )
+                {
+                    // Set the ciSuccess to false, since we ran into a problem
+                    ciSuccess = false;
+                    ExceptionHandler eh = new ExceptionHandler( aex );
+                    api.getLogger().error( "MKS API Exception: " + eh.getMessage() );
+                    api.getLogger().debug( eh.getCommand() + " completed with exit Code " + eh.getExitCode() );
+                }
+            }
+        }
+        catch ( APIException aex )
+        {
+            // Set the ciSuccess to false, since we ran into a problem
+            ciSuccess = false;
+            ExceptionHandler eh = new ExceptionHandler( aex );
+            api.getLogger().error( "MKS API Exception: " + eh.getMessage() );
+            api.getLogger().debug( eh.getCommand() + " completed with exit Code " + eh.getExitCode() );
+        }
+
         return changedFiles;
     }
 
     /**
      * Returns the overall success of the check-in operation
+     *
      * @return
      */
     public boolean getOverallCheckInSuccess()
     {
-    	return ciSuccess;
+        return ciSuccess;
     }
 
     /**
      * Creates one subproject per directory, as required.
+     *
      * @param dirPath A relative path structure of folders
      * @return Response containing the result for the created subproject
-     * @throws APIException 
+     * @throws APIException
      */
-    public Response createSubproject(String dirPath) throws APIException
+    public Response createSubproject( String dirPath )
+        throws APIException
     {
-		// Setup the create subproject command
-        api.getLogger().debug("Creating subprojects for: " + dirPath + "/project.pj");			
-		Command siCreateSubproject = new Command(Command.SI, "createsubproject");
-		siCreateSubproject.addOption(new Option("cpid", cpid));
-		siCreateSubproject.addOption(new Option("createSubprojects"));
-		siCreateSubproject.addOption(new Option("cwd", sandboxDir));
-		siCreateSubproject.addSelection(dirPath + "/project.pj");
-		// Execute the create subproject command
-		return api.runCommand(siCreateSubproject);
+        // Setup the create subproject command
+        api.getLogger().debug( "Creating subprojects for: " + dirPath + "/project.pj" );
+        Command siCreateSubproject = new Command( Command.SI, "createsubproject" );
+        siCreateSubproject.addOption( new Option( "cpid", cpid ) );
+        siCreateSubproject.addOption( new Option( "createSubprojects" ) );
+        siCreateSubproject.addOption( new Option( "cwd", sandboxDir ) );
+        siCreateSubproject.addSelection( dirPath + "/project.pj" );
+        // Execute the create subproject command
+        return api.runCommand( siCreateSubproject );
     }
-    
+
     /**
      * Executes the 'si rlog' command to generate a list of changed revision found between startDate and endDate
+     *
      * @param startDate The date range for the beginning of the operation
-     * @param endDate The date range for the end of the operation
+     * @param endDate   The date range for the end of the operation
      * @return ChangeLogSet containing a list of changes grouped by Change Pacakge ID
      * @throws APIException
      */
-    public ChangeLogSet getChangeLog(Date startDate, Date endDate) throws APIException
+    public ChangeLogSet getChangeLog( Date startDate, Date endDate )
+        throws APIException
     {
-    	// Initialize our return object
-    	ChangeLogSet changeLog = new ChangeLogSet(startDate, endDate);
-    	// By default we're going to group-by change package
-    	// Non change package changes will be lumped into one big Change Set
-    	Hashtable<String, ChangeSet> changeSetHash = new Hashtable<String, ChangeSet>();
-    	
-    	// Lets prepare our si rlog command for execution
-    	Command siRlog = new Command(Command.SI, "rlog");
-        siRlog.addOption(new Option("recurse"));
-        MultiValue rFilter = new MultiValue(":");
-        rFilter.add("daterange");
-        rFilter.add("'" + RLOG_DATEFORMAT.format(startDate) + "'-'" + RLOG_DATEFORMAT.format(endDate) + "'");
-        siRlog.addOption(new Option("rfilter", rFilter));
-        siRlog.addOption(new Option("cwd", sandboxDir));
+        // Initialize our return object
+        ChangeLogSet changeLog = new ChangeLogSet( startDate, endDate );
+        // By default we're going to group-by change package
+        // Non change package changes will be lumped into one big Change Set
+        Hashtable<String, ChangeSet> changeSetHash = new Hashtable<String, ChangeSet>();
+
+        // Lets prepare our si rlog command for execution
+        Command siRlog = new Command( Command.SI, "rlog" );
+        siRlog.addOption( new Option( "recurse" ) );
+        MultiValue rFilter = new MultiValue( ":" );
+        rFilter.add( "daterange" );
+        rFilter.add( "'" + RLOG_DATEFORMAT.format( startDate ) + "'-'" + RLOG_DATEFORMAT.format( endDate ) + "'" );
+        siRlog.addOption( new Option( "rfilter", rFilter ) );
+        siRlog.addOption( new Option( "cwd", sandboxDir ) );
         // Execute the si rlog command
-        Response response = api.runCommand(siRlog);
-        for(WorkItemIterator wit = response.getWorkItems(); wit.hasNext();)
+        Response response = api.runCommand( siRlog );
+        for ( WorkItemIterator wit = response.getWorkItems(); wit.hasNext(); )
         {
-        	WorkItem wi = wit.next();
-        	String memberName = wi.getContext();
-        	// We're going to have to do a little dance to get the correct server file name
-        	memberName = memberName.substring(0, memberName.lastIndexOf('/'));
-        	memberName = memberName + '/' + wi.getId();
-        	memberName = memberName.replace('\\', '/');
-        	// Now lets get the revisions for this file
-        	Field revisionsFld = wi.getField("revisions");
-        	if( null != revisionsFld && revisionsFld.getDataType().equals(Field.ITEM_LIST_TYPE) && null != revisionsFld.getList() )
-        	{
-        		@SuppressWarnings("unchecked")
-				List<Item> revList = revisionsFld.getList();
-        		for( Iterator<Item> lit = revList.iterator(); lit.hasNext(); )
-        		{
-        			Item revisionItem = lit.next();
-        			String revision = revisionItem.getId();
-        			String author = revisionItem.getField("author").getItem().getId();
-        			// Attempt to get the full name, if available
-        			try { author = revisionItem.getField("author").getItem().getField("fullname").getValueAsString(); }
-        			catch(NullPointerException npe){ /* ignore */ }
-        			String cpid = ":none";
-        			// Attempt to get the cpid for this revision
-        			try { cpid = revisionItem.getField("cpid").getItem().getId(); }
-        			catch(NullPointerException npe){ /* ignore */ }
-        			// Get the Change Package summary for this revision
-        			String comment = cpid + ": " + revisionItem.getField("cpsummary").getValueAsString();
-        			// Get the date associated with this revision
-        			Date date = revisionItem.getField("date").getDateTime();
-     
-        			// Lets create our ChangeFile based on the information we've gathered so far
-        			ChangeFile changeFile = new ChangeFile(memberName, revision); 
-
-        			// Check to see if we already have a ChangeSet grouping for this revision
-        			ChangeSet changeSet = changeSetHash.get(cpid);
-        			if( null != changeSet )
-        			{
-        				// Set the date of the ChangeSet to the oldest entry
-        				if( changeSet.getDate().after(date) ){ changeSet.setDate(date); }
-        				// Add the new ChangeFile
-        				changeSet.addFile(changeFile);
-        				// Update the changeSetHash
-        				changeSetHash.put(cpid, changeSet);
-        			}
-        			else // Create a new ChangeSet grouping and add the ChangeFile
-        			{
-        				List<ChangeFile> changeFileList = new ArrayList<ChangeFile>();
-        				changeFileList.add(changeFile);
-        				changeSet = new ChangeSet(date, comment, author, changeFileList);
-        				// Update the changeSetHash with an initial entry for the cpid
-        				changeSetHash.put(cpid, changeSet);
-        			}
-        		}
-        	}
-        	
+            WorkItem wi = wit.next();
+            String memberName = wi.getContext();
+            // We're going to have to do a little dance to get the correct server file name
+            memberName = memberName.substring( 0, memberName.lastIndexOf( '/' ) );
+            memberName = memberName + '/' + wi.getId();
+            memberName = memberName.replace( '\\', '/' );
+            // Now lets get the revisions for this file
+            Field revisionsFld = wi.getField( "revisions" );
+            if ( null != revisionsFld && revisionsFld.getDataType().equals( Field.ITEM_LIST_TYPE )
+                && null != revisionsFld.getList() )
+            {
+                @SuppressWarnings( "unchecked" ) List<Item> revList = revisionsFld.getList();
+                for ( Iterator<Item> lit = revList.iterator(); lit.hasNext(); )
+                {
+                    Item revisionItem = lit.next();
+                    String revision = revisionItem.getId();
+                    String author = revisionItem.getField( "author" ).getItem().getId();
+                    // Attempt to get the full name, if available
+                    try
+                    {
+                        author = revisionItem.getField( "author" ).getItem().getField( "fullname" ).getValueAsString();
+                    }
+                    catch ( NullPointerException npe )
+                    { /* ignore */ }
+                    String cpid = ":none";
+                    // Attempt to get the cpid for this revision
+                    try
+                    {
+                        cpid = revisionItem.getField( "cpid" ).getItem().getId();
+                    }
+                    catch ( NullPointerException npe )
+                    { /* ignore */ }
+                    // Get the Change Package summary for this revision
+                    String comment = cpid + ": " + revisionItem.getField( "cpsummary" ).getValueAsString();
+                    // Get the date associated with this revision
+                    Date date = revisionItem.getField( "date" ).getDateTime();
+
+                    // Lets create our ChangeFile based on the information we've gathered so far
+                    ChangeFile changeFile = new ChangeFile( memberName, revision );
+
+                    // Check to see if we already have a ChangeSet grouping for this revision
+                    ChangeSet changeSet = changeSetHash.get( cpid );
+                    if ( null != changeSet )
+                    {
+                        // Set the date of the ChangeSet to the oldest entry
+                        if ( changeSet.getDate().after( date ) )
+                        {
+                            changeSet.setDate( date );
+                        }
+                        // Add the new ChangeFile
+                        changeSet.addFile( changeFile );
+                        // Update the changeSetHash
+                        changeSetHash.put( cpid, changeSet );
+                    }
+                    else // Create a new ChangeSet grouping and add the ChangeFile
+                    {
+                        List<ChangeFile> changeFileList = new ArrayList<ChangeFile>();
+                        changeFileList.add( changeFile );
+                        changeSet = new ChangeSet( date, comment, author, changeFileList );
+                        // Update the changeSetHash with an initial entry for the cpid
+                        changeSetHash.put( cpid, changeSet );
+                    }
+                }
+            }
+
         }
-    	
+
         // Update the Change Log with the Change Sets
         List<ChangeSet> changeSetList = new ArrayList<ChangeSet>();
-        changeSetList.addAll(changeSetHash.values());
-        changeLog.setChangeSets(changeSetList);
-        
-    	return changeLog;
+        changeSetList.addAll( changeSetHash.values() );
+        changeLog.setChangeSets( changeSetList );
+
+        return changeLog;
     }
 }
\ No newline at end of file