Return-Path: X-Original-To: apmail-maven-commits-archive@www.apache.org Delivered-To: apmail-maven-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6D6E27E18 for ; Sat, 27 Aug 2011 12:39:56 +0000 (UTC) Received: (qmail 69091 invoked by uid 500); 27 Aug 2011 12:39:53 -0000 Delivered-To: apmail-maven-commits-archive@maven.apache.org Received: (qmail 68900 invoked by uid 500); 27 Aug 2011 12:39:50 -0000 Mailing-List: contact commits-help@maven.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@maven.apache.org Delivered-To: mailing list commits@maven.apache.org Received: (qmail 68893 invoked by uid 99); 27 Aug 2011 12:39:50 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 27 Aug 2011 12:39:50 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 27 Aug 2011 12:39:43 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 9696A2388AB9; Sat, 27 Aug 2011 12:39:23 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Sat, 27 Aug 2011 12:39:22 -0000 To: commits@maven.apache.org From: olamy@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110827123923.9696A2388AB9@eris.apache.org> 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 *
Provides metadata information about a Project - * @version $Id: Project.java 1.6 2011/08/22 13:06:48EDT Cletus D'Souza (dsouza) Exp $ + * * @author Cletus D'Souza + * @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 FILES_ORDER = new Comparator() - { - public int compare(Member cmm1, Member cmm2) - { - return cmm1.getMemberName().compareToIgnoreCase(cmm2.getMemberName()); - } - }; - - /** - * Checks if the given value is a valid MKS Integrity Label. - *
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 listFiles(String workspaceDir) throws APIException - { - // Re-initialize the member list for this project - List memberList = new ArrayList(); - // Initialize the project config hash - Hashtable pjConfigHash = new Hashtable(); - // 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. + *
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 listFiles( String workspaceDir ) + throws APIException + { + // Re-initialize the member list for this project + List memberList = new ArrayList(); + // Initialize the project config hash + Hashtable pjConfigHash = new Hashtable(); + // 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 Cletus D'Souza - */ + * @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 getNewMembers(String exclude, String include) throws APIException + public List getNewMembers( String exclude, String include ) + throws APIException { - // Store a list of files that were added to the repository - List filesAdded = new ArrayList(); - 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 filesAdded = new ArrayList(); + 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 addNonMembers(String exclude, String include, String message) + public List 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 filesAdded = new ArrayList(); - 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 filesAdded = new ArrayList(); + api.getLogger().debug( "Looking for new members in sandbox dir: " + sandboxDir ); try { - List newFileList = getNewMembers(exclude, include); - for( Iterator 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 newFileList = getNewMembers( exclude, include ); + for ( Iterator 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 getChangeList() throws APIException + public List getChangeList() + throws APIException { - // Store a list of files that were changed/removed to the repository - List changedFiles = new ArrayList(); - // 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 changedFiles = new ArrayList(); + // 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 checkInUpdates(String message) + public List 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 changedFiles = new ArrayList(); - 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 changedFiles = new ArrayList(); + api.getLogger().debug( "Looking for changed and dropped members in sandbox dir: " + sandboxDir ); + try { - // Let the list of changed files - List changeList = getChangeList(); - // Check-in all changed files, drop all members with missing working files - for( Iterator 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 changeList = getChangeList(); + // Check-in all changed files, drop all members with missing working files + for ( Iterator 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 changeSetHash = new Hashtable(); - - // 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 changeSetHash = new Hashtable(); + + // 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 revList = revisionsFld.getList(); - for( Iterator 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 changeFileList = new ArrayList(); - 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 revList = revisionsFld.getList(); + for ( Iterator 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 changeFileList = new ArrayList(); + 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 changeSetList = new ArrayList(); - changeSetList.addAll(changeSetHash.values()); - changeLog.setChangeSets(changeSetList); - - return changeLog; + changeSetList.addAll( changeSetHash.values() ); + changeLog.setChangeSets( changeSetList ); + + return changeLog; } } \ No newline at end of file