|
|
@@ -1,867 +0,0 @@ |
|
|
|
/* |
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
|
|
* contributor license agreements. See the NOTICE file distributed with |
|
|
|
* this work for additional information regarding copyright ownership. |
|
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
|
|
* (the "License"); you may not use this file except in compliance with |
|
|
|
* the License. You may obtain a copy of the License at |
|
|
|
* |
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
|
|
* |
|
|
|
* Unless required by applicable law or agreed to in writing, software |
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
|
|
* See the License for the specific language governing permissions and |
|
|
|
* limitations under the License. |
|
|
|
* |
|
|
|
*/ |
|
|
|
package org.apache.tools.ant.taskdefs.optional.starteam; |
|
|
|
|
|
|
|
import com.starbase.starteam.Folder; |
|
|
|
import com.starbase.starteam.Label; |
|
|
|
import com.starbase.starteam.PropertyNames; |
|
|
|
import com.starbase.starteam.StarTeamFinder; |
|
|
|
import com.starbase.starteam.View; |
|
|
|
import com.starbase.starteam.ViewConfiguration; |
|
|
|
import com.starbase.util.OLEDate; |
|
|
|
import java.text.ParseException; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.util.Date; |
|
|
|
import java.util.Hashtable; |
|
|
|
import java.util.StringTokenizer; |
|
|
|
import org.apache.tools.ant.BuildException; |
|
|
|
import org.apache.tools.ant.util.DateUtils; |
|
|
|
import org.apache.tools.ant.DirectoryScanner; |
|
|
|
import org.apache.tools.ant.Project; |
|
|
|
|
|
|
|
/** |
|
|
|
* TreeBasedTask.java |
|
|
|
* This abstract class is the base for any tasks that are tree-based, that |
|
|
|
* is, for tasks which iterate over a tree of folders in StarTeam which |
|
|
|
* is reflected in a tree of folder the local machine. |
|
|
|
* |
|
|
|
* This class provides the tree-iteration functionality. Derived classes |
|
|
|
* will implement their specific task functionality by the visitor pattern, |
|
|
|
* specifically by implementing the method |
|
|
|
* <code>visit(Folder rootStarteamFolder, java.io.File rootLocalFolder)</code> |
|
|
|
* |
|
|
|
* Created: Sat Dec 15 16:55:19 2001 |
|
|
|
* |
|
|
|
* @see <a href="http://www.borland.com/us/products/starteam/index.html" |
|
|
|
* >borland StarTeam Web Site</a> |
|
|
|
*/ |
|
|
|
|
|
|
|
public abstract class TreeBasedTask extends StarTeamTask { |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
// default values for attributes. |
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
/** |
|
|
|
* This constant sets the filter to include all files. This default has |
|
|
|
* the same result as <code>setIncludes("*")</code>. |
|
|
|
* |
|
|
|
* @see #getIncludes() |
|
|
|
* @see #setIncludes(String includes) |
|
|
|
*/ |
|
|
|
public static final String DEFAULT_INCLUDESETTING = "*"; |
|
|
|
|
|
|
|
/** |
|
|
|
* This disables the exclude filter by default. In other words, no files |
|
|
|
* are excluded. This setting is equivalent to |
|
|
|
* <code>setExcludes(null)</code>. |
|
|
|
* |
|
|
|
* @see #getExcludes() |
|
|
|
* @see #setExcludes(String excludes) |
|
|
|
*/ |
|
|
|
public static final String DEFAULT_EXCLUDESETTING = null; |
|
|
|
|
|
|
|
//ATTRIBUTES settable from ant. |
|
|
|
|
|
|
|
/** |
|
|
|
* The root folder of the operation in StarTeam. |
|
|
|
*/ |
|
|
|
private String rootStarteamFolder = "/"; |
|
|
|
|
|
|
|
/** |
|
|
|
* The local folder corresponding to starteamFolder. If not specified |
|
|
|
* the Star Team default folder will be used. |
|
|
|
*/ |
|
|
|
private String rootLocalFolder = null; |
|
|
|
|
|
|
|
/** |
|
|
|
* All files that fit this pattern are checked out. |
|
|
|
*/ |
|
|
|
private String includes = DEFAULT_INCLUDESETTING; |
|
|
|
|
|
|
|
/** |
|
|
|
* All files fitting this pattern are ignored. |
|
|
|
*/ |
|
|
|
private String excludes = DEFAULT_EXCLUDESETTING; |
|
|
|
|
|
|
|
/** |
|
|
|
* StarTeam label on which to perform task. |
|
|
|
*/ |
|
|
|
private String label = null; |
|
|
|
|
|
|
|
/** |
|
|
|
* Set recursion to false to check out files in only the given folder |
|
|
|
* and not in its subfolders. |
|
|
|
*/ |
|
|
|
private boolean recursive = true; |
|
|
|
|
|
|
|
/** |
|
|
|
* Set preloadFileInformation to true to load all file information from the server |
|
|
|
* at once. Increases performance significantly for projects with many files and/or folders. |
|
|
|
*/ |
|
|
|
private boolean preloadFileInformation = true; |
|
|
|
|
|
|
|
/** |
|
|
|
* If forced set to true, files in the target directory will |
|
|
|
* be processed regardless of status in the repository. |
|
|
|
* Usually this should be true if rootlocalfolder is set |
|
|
|
* because status will be relative to the default folder, not |
|
|
|
* to the one being processed. |
|
|
|
*/ |
|
|
|
private boolean forced = false; |
|
|
|
|
|
|
|
private Label labelInUse = null; |
|
|
|
|
|
|
|
/** |
|
|
|
* holder for the asofdate attribute |
|
|
|
*/ |
|
|
|
private String asOfDate = null; |
|
|
|
|
|
|
|
/** |
|
|
|
* holder for the asofdateformat attribute |
|
|
|
*/ |
|
|
|
private String asOfDateFormat = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
// GET/SET methods. |
|
|
|
// Setters, of course are where ant user passes in values. |
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
/** |
|
|
|
* Set the root of the subtree in the StarTeam repository from which to |
|
|
|
* work; optional. Defaults to the root folder of the view ('/'). |
|
|
|
* @param rootStarteamFolder the root folder |
|
|
|
*/ |
|
|
|
public void setRootStarteamFolder(String rootStarteamFolder) { |
|
|
|
this.rootStarteamFolder = rootStarteamFolder; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* returns the root folder in the Starteam repository |
|
|
|
* used for this operation |
|
|
|
* @return the root folder in use |
|
|
|
*/ |
|
|
|
public String getRootStarteamFolder() { |
|
|
|
return this.rootStarteamFolder; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Set the local folder that will be the root of the tree |
|
|
|
* to which files are checked out; optional. |
|
|
|
* If this is not supplied, then the StarTeam "default folder" |
|
|
|
* associated with <tt>rootstarteamfolder</tt> is used. |
|
|
|
* |
|
|
|
* @param rootLocalFolder |
|
|
|
* the local folder that will mirror |
|
|
|
* this.rootStarteamFolder |
|
|
|
*/ |
|
|
|
public void setRootLocalFolder(String rootLocalFolder) { |
|
|
|
this.rootLocalFolder = rootLocalFolder; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the local folder specified by the user, |
|
|
|
* corresponding to the starteam folder for this operation |
|
|
|
* or null if not specified. |
|
|
|
* |
|
|
|
* @return the local folder that mirrors this.rootStarteamFolder |
|
|
|
*/ |
|
|
|
public String getRootLocalFolder() { |
|
|
|
return this.rootLocalFolder; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Declare files to include using standard <tt>includes</tt> patterns; optional. |
|
|
|
* @param includes A string of filter patterns to include. Separate the |
|
|
|
* patterns by spaces. |
|
|
|
* @see #getIncludes() |
|
|
|
* @see #setExcludes(String excludes) |
|
|
|
* @see #getExcludes() |
|
|
|
*/ |
|
|
|
public void setIncludes(String includes) { |
|
|
|
this.includes = includes; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gets the patterns from the include filter. Rather that duplicate the |
|
|
|
* details of AntStarTeamCheckOut's filtering here, refer to these |
|
|
|
* links: |
|
|
|
* |
|
|
|
* @return A string of filter patterns separated by spaces. |
|
|
|
* @see #setIncludes(String includes) |
|
|
|
* @see #setExcludes(String excludes) |
|
|
|
* @see #getExcludes() |
|
|
|
*/ |
|
|
|
public String getIncludes() { |
|
|
|
return includes; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* if excludes have been specified, emit the list to the log |
|
|
|
*/ |
|
|
|
protected void logIncludes() { |
|
|
|
if (DEFAULT_INCLUDESETTING != this.includes) { |
|
|
|
log(" Includes specified: " + this.includes); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Declare files to exclude using standard <tt>excludes</tt> patterns; optional. |
|
|
|
* When filtering files, AntStarTeamCheckOut |
|
|
|
* uses an unmodified version of <code>DirectoryScanner</code>'s |
|
|
|
* <code>match</code> method, so here are the patterns straight from the |
|
|
|
* Ant source code: |
|
|
|
* <br/> |
|
|
|
* Matches a string against a pattern. The pattern contains two special |
|
|
|
* characters: |
|
|
|
* <br/>'*' which means zero or more characters, |
|
|
|
* <br/>'?' which means one and only one character. |
|
|
|
* <br/> |
|
|
|
* For example, if you want to check out all files except .XML and |
|
|
|
* .HTML files, you would put the following line in your program: |
|
|
|
* <code>setExcludes("*.XML,*.HTML");</code> |
|
|
|
* Finally, note that filters have no effect on the <b>directories</b> |
|
|
|
* that are scanned; you could not skip over all files in directories |
|
|
|
* whose names begin with "project," for instance. |
|
|
|
* <br/> |
|
|
|
* Treatment of overlapping inlcudes and excludes: To give a simplistic |
|
|
|
* example suppose that you set your include filter to "*.htm *.html" |
|
|
|
* and your exclude filter to "index.*". What happens to index.html? |
|
|
|
* AntStarTeamCheckOut will not check out index.html, as it matches an |
|
|
|
* exclude filter ("index.*"), even though it matches the include |
|
|
|
* filter, as well. |
|
|
|
* <br/> |
|
|
|
* Please also read the following sections before using filters: |
|
|
|
* |
|
|
|
* @param excludes A string of filter patterns to exclude. Separate the |
|
|
|
* patterns by spaces. |
|
|
|
* @see #setIncludes(String includes) |
|
|
|
* @see #getIncludes() |
|
|
|
* @see #getExcludes() |
|
|
|
*/ |
|
|
|
public void setExcludes(String excludes) { |
|
|
|
this.excludes = excludes; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Gets the patterns from the exclude filter. Rather that duplicate the |
|
|
|
* details of AntStarTeanCheckOut's filtering here, refer to these |
|
|
|
* links: |
|
|
|
* |
|
|
|
* @return A string of filter patterns separated by spaces. |
|
|
|
* @see #setExcludes(String excludes) |
|
|
|
* @see #setIncludes(String includes) |
|
|
|
* @see #getIncludes() |
|
|
|
*/ |
|
|
|
public String getExcludes() { |
|
|
|
return excludes; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* if excludes have been specified, emit the list to the log |
|
|
|
*/ |
|
|
|
protected void logExcludes() { |
|
|
|
if (DEFAULT_EXCLUDESETTING != this.excludes) { |
|
|
|
log(" Excludes specified: " + this.excludes); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// CheckStyle:MethodNameCheck OFF - bc |
|
|
|
|
|
|
|
/** |
|
|
|
* protected function to allow subclasses to set the label (or not). |
|
|
|
* sets the StarTeam label |
|
|
|
* |
|
|
|
* @param label name of the StarTeam label to be set |
|
|
|
*/ |
|
|
|
protected void _setLabel(String label) { |
|
|
|
if (null != label) { |
|
|
|
label = label.trim(); |
|
|
|
if (label.length() > 0) { |
|
|
|
this.label = label; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* non-public method callable only by derived classes that implement |
|
|
|
* setAsOfDate (so that derived tasks that do not accept this |
|
|
|
* parameter will fail if user attempts to use it. |
|
|
|
* |
|
|
|
* @param asOfDate asOfDate entered by user. |
|
|
|
* @since Ant 1.6 |
|
|
|
*/ |
|
|
|
protected void _setAsOfDate(String asOfDate) { |
|
|
|
if (asOfDate != null && asOfDate.length() > 0) { |
|
|
|
this.asOfDate = asOfDate; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* non-public method callable only by derived classes that implement |
|
|
|
* setAsOfDateFormat (so that derived tasks that do not accept this |
|
|
|
* parameter will fail if user attempts to use it. |
|
|
|
* |
|
|
|
* @param asOfDateFormat asOfDate format entered by user. |
|
|
|
* @since Ant 1.6 |
|
|
|
*/ |
|
|
|
protected void _setAsOfDateFormat(String asOfDateFormat) { |
|
|
|
if (asOfDateFormat != null && asOfDateFormat.length() > 0) { |
|
|
|
this.asOfDateFormat = asOfDateFormat; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// CheckStyle:VisibilityModifier ON |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* return the asOfDate entered by the user for internal use by derived |
|
|
|
* classes. |
|
|
|
* |
|
|
|
* @return the asOfDate entered by the user |
|
|
|
* @since Ant 1.6 |
|
|
|
*/ |
|
|
|
protected String getAsOfDate() { |
|
|
|
return this.asOfDate; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* If an asofDate parameter has been supplied by the user return a |
|
|
|
* StarTeam view based on the configuration of the StarTeam view |
|
|
|
* specified the user as of the date specified in the parameter. |
|
|
|
* If no asofDate has been specified, return null. |
|
|
|
* |
|
|
|
* This method is meant to be called from within implementations of the |
|
|
|
* <code>createSnapshotView</code> abstract method. |
|
|
|
* |
|
|
|
* @param raw the raw view to be configured as of the supplied date |
|
|
|
* |
|
|
|
* @return the view as configured. |
|
|
|
* @exception BuildException |
|
|
|
* thrown if the date is not parsable by the default or |
|
|
|
* supplied format patterns. |
|
|
|
* @since Ant 1.6 |
|
|
|
*/ |
|
|
|
protected View getViewConfiguredByDate(View raw) throws BuildException { |
|
|
|
if (this.asOfDate == null) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
Date asOfDate = null; |
|
|
|
SimpleDateFormat fmt = null; |
|
|
|
if (this.asOfDateFormat != null) { |
|
|
|
fmt = new SimpleDateFormat(this.asOfDateFormat); |
|
|
|
try { |
|
|
|
asOfDate = fmt.parse(this.asOfDate); |
|
|
|
} catch (ParseException px) { |
|
|
|
throw new BuildException("AsOfDate " |
|
|
|
+ this.asOfDate |
|
|
|
+ " not parsable by supplied format " |
|
|
|
+ this.asOfDateFormat); |
|
|
|
} |
|
|
|
} else { |
|
|
|
try { |
|
|
|
asOfDate = DateUtils.parseIso8601DateTimeOrDate( |
|
|
|
this.asOfDate); |
|
|
|
} catch (ParseException px) { |
|
|
|
throw new BuildException("AsOfDate " |
|
|
|
+ this.asOfDate |
|
|
|
+ " not parsable by default" |
|
|
|
+ " ISO8601 formats"); |
|
|
|
} |
|
|
|
} |
|
|
|
return new View(raw, ViewConfiguration.createFromTime( |
|
|
|
new OLEDate(asOfDate))); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* return the label passed to the task by the user as a string |
|
|
|
* |
|
|
|
* @return the label passed to the task by the user as a string |
|
|
|
*/ |
|
|
|
protected String getLabel() { |
|
|
|
return this.label; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the value of recursive. |
|
|
|
* @return value of recursive. |
|
|
|
*/ |
|
|
|
public boolean isRecursive() { |
|
|
|
return this.recursive; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Flag to set to include files in subfolders in the operation; optional, |
|
|
|
* default true. |
|
|
|
* @param v Value to assign to recursive. |
|
|
|
*/ |
|
|
|
public void setRecursive(boolean v) { |
|
|
|
this.recursive = v; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the value of preloadFileInformation. |
|
|
|
* @return value of preloadFileInformation. |
|
|
|
*/ |
|
|
|
public boolean isPreloadFileInformation() { |
|
|
|
return this.preloadFileInformation; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Flag to set to preload file information from the server; optional, |
|
|
|
* default true. |
|
|
|
* Increases performance significantly for projects with many files |
|
|
|
* and/or folders. |
|
|
|
* @param v Value to assign to preloadFileInformation. |
|
|
|
*/ |
|
|
|
public void setPreloadFileInformation(boolean v) { |
|
|
|
this.preloadFileInformation = v; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the value of forced. |
|
|
|
* @return value of forced. |
|
|
|
*/ |
|
|
|
public boolean isForced() { |
|
|
|
return this.forced; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Flag to force actions regardless of the status |
|
|
|
* that StarTeam is maintaining for the file; optional, default false. |
|
|
|
* If <tt>rootlocalfolder</tt> is set then |
|
|
|
* this should be set "true" as otherwise the checkout will be based on statuses |
|
|
|
* which do not relate to the target folder. |
|
|
|
* @param v Value to assign to forced. |
|
|
|
*/ |
|
|
|
public void setForced(boolean v) { |
|
|
|
this.forced = v; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* returns true if a label has been specified and it is a view label. |
|
|
|
* |
|
|
|
* @return true if a label has been specified and it is a view label |
|
|
|
*/ |
|
|
|
protected boolean isUsingViewLabel() { |
|
|
|
return null != this.labelInUse && this.labelInUse.isViewLabel(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* returns true if a label has been specified and it is a revision label. |
|
|
|
* |
|
|
|
* @return true if a label has been specified and it is a revision label |
|
|
|
*/ |
|
|
|
protected boolean isUsingRevisionLabel() { |
|
|
|
return null != this.labelInUse && this.labelInUse.isRevisionLabel(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* returns the label being used |
|
|
|
* |
|
|
|
* @return the label being used |
|
|
|
*/ |
|
|
|
protected Label getLabelInUse() { |
|
|
|
return this.labelInUse; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* show the label in the log and its type. |
|
|
|
*/ |
|
|
|
protected void logLabel() { |
|
|
|
if (this.isUsingViewLabel()) { |
|
|
|
log(" Using view label " + getLabel()); |
|
|
|
} else if (this.isUsingRevisionLabel()) { |
|
|
|
log(" Using revision label " + getLabel()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* show the asofDate in the log |
|
|
|
* @since Ant 1.6 |
|
|
|
*/ |
|
|
|
protected void logAsOfDate() { |
|
|
|
if (null != this.asOfDate) { |
|
|
|
log(" Using view as of date " + getAsOfDate()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
// INCLUDE-EXCLUDE processing |
|
|
|
/////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
/** |
|
|
|
* Look if the file should be processed by the task. |
|
|
|
* Don't process it if it fits no include filters or if |
|
|
|
* it fits an exclude filter. |
|
|
|
* |
|
|
|
* @param pName the item name to look for being included. |
|
|
|
* |
|
|
|
* @return whether the file should be processed or not. |
|
|
|
*/ |
|
|
|
protected boolean shouldProcess(String pName) { |
|
|
|
boolean includeIt = matchPatterns(getIncludes(), pName); |
|
|
|
boolean excludeIt = matchPatterns(getExcludes(), pName); |
|
|
|
return (includeIt && !excludeIt); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Convenience method to see if a string match a one pattern |
|
|
|
* in given set of space-separated patterns. |
|
|
|
* @param patterns the space-separated list of patterns. |
|
|
|
* @param pName the name to look for matching. |
|
|
|
* @return whether the name match at least one pattern. |
|
|
|
*/ |
|
|
|
protected boolean matchPatterns(String patterns, String pName) { |
|
|
|
if (patterns == null) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
StringTokenizer exStr = new StringTokenizer(patterns, ","); |
|
|
|
while (exStr.hasMoreTokens()) { |
|
|
|
if (DirectoryScanner.match(exStr.nextToken(), pName)) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Finds and opens the root starteam folder of the operation specified |
|
|
|
* by this task. This will be one of the following cases: |
|
|
|
* |
|
|
|
* @return Starteam's root folder for the operation. |
|
|
|
* @exception BuildException |
|
|
|
* if the root folder cannot be found in the repository |
|
|
|
*/ |
|
|
|
private Folder configureRootStarteamFolder() |
|
|
|
throws BuildException { |
|
|
|
Folder starteamrootfolder = null; |
|
|
|
try { |
|
|
|
// no root local mapping has been specified. |
|
|
|
View snapshot = openView(); |
|
|
|
|
|
|
|
// find the starteam folder specified to be the root of the |
|
|
|
// operation. Throw if it can't be found. |
|
|
|
|
|
|
|
starteamrootfolder = |
|
|
|
StarTeamFinder.findFolder(snapshot.getRootFolder(), |
|
|
|
this.rootStarteamFolder); |
|
|
|
|
|
|
|
if (this.isPreloadFileInformation()) { |
|
|
|
PropertyNames pn = getServer().getPropertyNames(); |
|
|
|
String[] props = new String[] {pn.FILE_NAME, pn.FILE_PATH, |
|
|
|
pn.FILE_STATUS, pn.MODIFIED_TIME, |
|
|
|
pn.FILE_FILE_TIME_AT_CHECKIN, |
|
|
|
pn.MODIFIED_USER_ID, pn.FILE_SIZE, |
|
|
|
pn.FILE_ENCODING}; |
|
|
|
|
|
|
|
int depth = this.isRecursive() ? -1 : 0; |
|
|
|
starteamrootfolder.populateNow(getServer().getTypeNames().FILE, |
|
|
|
props, depth); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (BuildException e) { |
|
|
|
throw e; |
|
|
|
} catch (Exception e) { |
|
|
|
StringBuffer msg = new StringBuffer("Unable to find root folder ") |
|
|
|
.append(this.rootStarteamFolder) |
|
|
|
.append(" in repository at ") |
|
|
|
.append(getURL()); |
|
|
|
if (this.label != null) { |
|
|
|
msg.append(" using specified label ").append(this.label); |
|
|
|
} |
|
|
|
if (this.asOfDate != null) { |
|
|
|
msg.append(" as of specified date ") |
|
|
|
.append(this.asOfDate); |
|
|
|
} |
|
|
|
throw new BuildException(msg.toString(), e); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (null == starteamrootfolder) { |
|
|
|
throw new BuildException("Unable to find root folder " |
|
|
|
+ this.rootStarteamFolder + " in repository at " + getURL()); |
|
|
|
} |
|
|
|
|
|
|
|
return starteamrootfolder; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Returns the local folder mapped to the given StarTeam root folder |
|
|
|
* of the operation. There are two cases here, depending on whether |
|
|
|
* <code>rootLocalFolder</code> is defined. |
|
|
|
* If <code>rootLocalFolder</code> is defined, it will be used to |
|
|
|
* establish a root mapping. Otherwise, the repository's default root |
|
|
|
* folder will be used. |
|
|
|
* |
|
|
|
* @param starteamrootfolder |
|
|
|
* root Starteam folder initialized for the operation |
|
|
|
* |
|
|
|
* @return the local folder corresponding to the root Starteam folder. |
|
|
|
* @see findRootStarteamFolder |
|
|
|
*/ |
|
|
|
private java.io.File getLocalRootMapping(Folder starteamrootfolder) { |
|
|
|
// set the local folder. |
|
|
|
String localrootfolder; |
|
|
|
if (null != this.rootLocalFolder) { |
|
|
|
localrootfolder = rootLocalFolder; |
|
|
|
} else { |
|
|
|
// either use default path or root local mapping, |
|
|
|
// which is now embedded in the root folder |
|
|
|
localrootfolder = starteamrootfolder.getPathFragment(); |
|
|
|
} |
|
|
|
|
|
|
|
return new java.io.File(localrootfolder); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* extenders should emit to the log an entry describing the parameters |
|
|
|
* that will be used by this operation. |
|
|
|
* |
|
|
|
* @param starteamrootFolder |
|
|
|
* root folder in StarTeam for the operation |
|
|
|
* @param targetrootFolder |
|
|
|
* root local folder for the operation (whether specified by the user or not. |
|
|
|
*/ |
|
|
|
protected abstract void logOperationDescription( |
|
|
|
Folder starteamrootFolder, java.io.File targetrootFolder); |
|
|
|
|
|
|
|
/** |
|
|
|
* This method does the work of opening the supplied Starteam view and |
|
|
|
* calling the <code>visit()</code> method to perform the task. |
|
|
|
* Derived classes can customize the called methods |
|
|
|
* <code>testPreconditions()</code> and <code>visit()</code>. |
|
|
|
* |
|
|
|
* @exception BuildException if any error occurs in the processing |
|
|
|
* @see <code>testPreconditions()</code> |
|
|
|
* @see <code>visit()</code> |
|
|
|
*/ |
|
|
|
|
|
|
|
public final void execute() throws BuildException { |
|
|
|
try { |
|
|
|
|
|
|
|
Folder starteamrootfolder = configureRootStarteamFolder(); |
|
|
|
|
|
|
|
// set the local folder. |
|
|
|
java.io.File localrootfolder = |
|
|
|
getLocalRootMapping(starteamrootfolder); |
|
|
|
|
|
|
|
testPreconditions(); |
|
|
|
|
|
|
|
// Tell user what he is doing |
|
|
|
logOperationDescription(starteamrootfolder, localrootfolder); |
|
|
|
|
|
|
|
// Inspect everything in the root folder and then recursively |
|
|
|
visit(starteamrootfolder, localrootfolder); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
throw new BuildException(e); |
|
|
|
} finally { |
|
|
|
disconnectFromServer(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void findLabel(View v) throws BuildException { |
|
|
|
Label[] allLabels = v.getLabels(); |
|
|
|
for (int i = 0; i < allLabels.length; i++) { |
|
|
|
Label stLabel = allLabels[i]; |
|
|
|
log("checking label " + stLabel.getName(), Project.MSG_DEBUG); |
|
|
|
if (stLabel != null && !stLabel.isDeleted() && stLabel.getName().equals(this.label)) { |
|
|
|
if (!stLabel.isRevisionLabel() && !stLabel.isViewLabel()) { |
|
|
|
throw new BuildException("Unexpected label type."); |
|
|
|
} |
|
|
|
log("using label " + stLabel.getName(), Project.MSG_VERBOSE); |
|
|
|
this.labelInUse = stLabel; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
throw new BuildException("Error: label " |
|
|
|
+ this.label |
|
|
|
+ " does not exist in view " |
|
|
|
+ v.getFullName()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Helper method calls on the StarTeam API to retrieve an ID number |
|
|
|
* for the specified view, corresponding to this.label. |
|
|
|
* @param v the <code>View</code> in which to search for <code>this.label</code> |
|
|
|
* @return the ID number corresponding to <code>this.label</code> or -1 if |
|
|
|
* no label was provided. |
|
|
|
* @exception BuildException if <code>this.label</code> does not correspond |
|
|
|
* to any label in the supplied view |
|
|
|
*/ |
|
|
|
protected int getLabelID(View v) throws BuildException { |
|
|
|
if (null != this.label) { |
|
|
|
findLabel(v); |
|
|
|
return this.labelInUse.getID(); |
|
|
|
} |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get the id of the label in use. |
|
|
|
* @return id of the label in use, if labelinuse is present, |
|
|
|
* otherwise return null |
|
|
|
*/ |
|
|
|
protected int getIDofLabelInUse() { |
|
|
|
if (null != this.labelInUse) { |
|
|
|
return this.labelInUse.getID(); |
|
|
|
} |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Derived classes must override this class to define actual processing |
|
|
|
* to be performed on each folder in the tree defined for the task |
|
|
|
* |
|
|
|
* @param rootStarteamFolder |
|
|
|
* the StarTeam folderto be visited |
|
|
|
* @param rootLocalFolder |
|
|
|
* the local mapping of rootStarteamFolder |
|
|
|
* |
|
|
|
* @throws BuildException on error |
|
|
|
*/ |
|
|
|
protected abstract void visit(Folder rootStarteamFolder, |
|
|
|
java.io.File rootLocalFolder) |
|
|
|
throws BuildException; |
|
|
|
|
|
|
|
/** |
|
|
|
* Derived classes must override this method to define tests for |
|
|
|
* any preconditons required by the task. This method is called at |
|
|
|
* the beginning of the execute() method. |
|
|
|
* |
|
|
|
* @exception BuildException throw if any fatal error exists in the |
|
|
|
* parameters supplied. If there is a non-fatal condition, just writing |
|
|
|
* to the log may be appropriate. |
|
|
|
* @see <code>execute()</code> |
|
|
|
*/ |
|
|
|
protected abstract void testPreconditions() throws BuildException; |
|
|
|
|
|
|
|
/** |
|
|
|
* Return the full repository path name of a file. Surprisingly there's |
|
|
|
* no method in com.starbase.starteam.File to provide this. |
|
|
|
* |
|
|
|
* @param remotefile the Star Team file whose path is to be returned |
|
|
|
* |
|
|
|
* @return the full repository path name of a file. |
|
|
|
*/ |
|
|
|
public static String getFullRepositoryPath( |
|
|
|
com.starbase.starteam.File remotefile) { |
|
|
|
StringBuffer sb = new StringBuffer(); |
|
|
|
sb.append(remotefile.getParentFolderHierarchy()) |
|
|
|
.append(remotefile.getName()); |
|
|
|
return sb.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* This class implements a map of existing local files to possibly |
|
|
|
* existing repository files. The map is created by a TreeBasedTask |
|
|
|
* upon recursing into a directory. Each local item is mapped to an |
|
|
|
* unattached StarTeam object of the proper type, File->File and |
|
|
|
* Directory->Folder. |
|
|
|
* |
|
|
|
* As the TreeBased does its work, it deletes from the map all items |
|
|
|
* it has processed. |
|
|
|
* |
|
|
|
* When the TreeBased task processes all the items from the repository, |
|
|
|
* whatever items left in the UnmatchedFileMap are uncontrolled items |
|
|
|
* and can be processed as appropriate to the task. In the case of |
|
|
|
* Checkouts, they can be optionally deleted from the local tree. In the |
|
|
|
* case of Checkins they can optionally be added to the repository. |
|
|
|
*/ |
|
|
|
protected abstract class UnmatchedFileMap extends Hashtable { |
|
|
|
|
|
|
|
/** |
|
|
|
* initializes the UnmatchedFileMap with entries from the local folder |
|
|
|
* These will be mapped to the corresponding StarTeam entry even though |
|
|
|
* it will not, in fact, exist in the repository. But through it, it |
|
|
|
* can be added, listed, etc. |
|
|
|
* |
|
|
|
* @param localFolder |
|
|
|
* the local folder from which the mappings will be made. |
|
|
|
* @param remoteFolder |
|
|
|
* the corresponding StarTeam folder which will be processed. |
|
|
|
*/ |
|
|
|
UnmatchedFileMap init(java.io.File localFolder, Folder remoteFolder) { |
|
|
|
if (!localFolder.exists()) { |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
String[] localFiles = localFolder.list(); |
|
|
|
|
|
|
|
for (int i = 0; i < localFiles.length; i++) { |
|
|
|
String fn = localFiles[i]; |
|
|
|
java.io.File localFile = |
|
|
|
new java.io.File(localFolder, localFiles[i]).getAbsoluteFile(); |
|
|
|
|
|
|
|
log("adding " + localFile + " to UnmatchedFileMap", |
|
|
|
Project.MSG_DEBUG); |
|
|
|
|
|
|
|
if (localFile.isDirectory()) { |
|
|
|
this.put(localFile, new Folder(remoteFolder, fn, fn)); |
|
|
|
} else { |
|
|
|
com.starbase.starteam.File remoteFile = |
|
|
|
new com.starbase.starteam.File(remoteFolder); |
|
|
|
remoteFile.setName(fn); |
|
|
|
this.put(localFile, remoteFile); |
|
|
|
} |
|
|
|
} |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* remove an item found to be controlled from the map. |
|
|
|
* |
|
|
|
* @param localFile the local item found to be controlled. |
|
|
|
*/ |
|
|
|
void removeControlledItem(java.io.File localFile) { |
|
|
|
if (isActive()) { |
|
|
|
log("removing processed " + localFile.getAbsoluteFile() |
|
|
|
+ " from UnmatchedFileMap", Project.MSG_DEBUG); |
|
|
|
this.remove(localFile.getAbsoluteFile()); |
|
|
|
} |
|
|
|
} |
|
|
|
/** |
|
|
|
* override will perform the action appropriate for its task to perform |
|
|
|
* on items which are on the local tree but not in StarTeam. It is |
|
|
|
* assumed that this method will not be called until all the items in |
|
|
|
* the corresponding folder have been processed, and that the internal |
|
|
|
* map * will contain only uncontrolled items. |
|
|
|
*/ |
|
|
|
abstract void processUncontrolledItems() throws BuildException; |
|
|
|
|
|
|
|
/** |
|
|
|
* overrides must define this to declare how this method knows if it |
|
|
|
* is active. This presents extra clock cycles when the functionality |
|
|
|
* is not called for. |
|
|
|
* |
|
|
|
* @return True if this object is to perform its functionality. |
|
|
|
*/ |
|
|
|
protected abstract boolean isActive(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |