git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@579316 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,361 +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.Item; | |||||
import com.starbase.starteam.Status; | |||||
import com.starbase.starteam.View; | |||||
import com.starbase.starteam.ViewConfiguration; | |||||
import java.io.IOException; | |||||
import java.util.Enumeration; | |||||
import org.apache.tools.ant.BuildException; | |||||
/** | |||||
* Checks files into a StarTeam project. | |||||
* Optionally adds files and in the local tree that | |||||
* are not managed by the repository to its control. | |||||
* Created: Sat Dec 15 20:26:07 2001 | |||||
* | |||||
* @version 1.0 | |||||
* | |||||
* @ant.task name="stcheckin" category="scm" product="Starteam" | |||||
*/ | |||||
public class StarTeamCheckin extends TreeBasedTask { | |||||
/** | |||||
* Constructor for StarTeamCheckin. | |||||
*/ | |||||
public StarTeamCheckin() { | |||||
// we want this to have a false default, unlike for Checkin. | |||||
setRecursive(false); | |||||
} | |||||
private boolean createFolders = true; | |||||
/** | |||||
* The comment which will be stored with the checkin. | |||||
*/ | |||||
private String comment = null; | |||||
/** | |||||
* holder for the add Uncontrolled attribute. If true, all | |||||
* local files not in StarTeam will be added to the repository. | |||||
*/ | |||||
private boolean addUncontrolled = false; | |||||
/** | |||||
* Sets the value of createFolders | |||||
* | |||||
* @param argCreateFolders Value to assign to this.createFolders | |||||
*/ | |||||
public void setCreateFolders(boolean argCreateFolders) { | |||||
this.createFolders = argCreateFolders; | |||||
} | |||||
/** | |||||
* Get the comment attribute for this operation | |||||
* @return value of comment. | |||||
*/ | |||||
public String getComment() { | |||||
return this.comment; | |||||
} | |||||
/** | |||||
* Optional checkin comment to be saved with the file. | |||||
* @param comment Value to assign to comment. | |||||
*/ | |||||
public void setComment(String comment) { | |||||
this.comment = comment; | |||||
} | |||||
/** | |||||
* Get the value of addUncontrolled. | |||||
* @return value of addUncontrolled. | |||||
*/ | |||||
public boolean isAddUncontrolled() { | |||||
return this.addUncontrolled; | |||||
} | |||||
/** | |||||
* if true, any files or folders NOT in StarTeam will be | |||||
* added to the repository. Defaults to "false". | |||||
* @param addUncontrolled Value to assign to addUncontrolled. | |||||
*/ | |||||
public void setAddUncontrolled(boolean addUncontrolled) { | |||||
this.addUncontrolled = addUncontrolled; | |||||
} | |||||
/** | |||||
* This attribute tells whether unlocked files on checkin (so that | |||||
* other users may access them) checkout or to leave the checkout status | |||||
* alone (default). | |||||
* @see #setUnlocked(boolean) | |||||
*/ | |||||
private int lockStatus = Item.LockType.UNCHANGED; | |||||
/** | |||||
* Set to do an unlocked checkout; optional, default is false; | |||||
* If true, file will be unlocked so that other users may | |||||
* change it. If false, lock status will not change. | |||||
* @param v true means do an unlocked checkout | |||||
* false means leave status alone. | |||||
*/ | |||||
public void setUnlocked(boolean v) { | |||||
if (v) { | |||||
this.lockStatus = Item.LockType.UNLOCKED; | |||||
} else { | |||||
this.lockStatus = Item.LockType.UNCHANGED; | |||||
} | |||||
} | |||||
/** | |||||
* Override of base-class abstract function creates an | |||||
* appropriately configured view. For checkins this is | |||||
* always the current or "tip" view. | |||||
* | |||||
* @param raw the unconfigured <code>View</code> | |||||
* @return the snapshot <code>View</code> appropriately configured. | |||||
*/ | |||||
protected View createSnapshotView(View raw) { | |||||
return new View(raw, ViewConfiguration.createTip()); | |||||
} | |||||
/** | |||||
* Implements base-class abstract function to define tests for | |||||
* any preconditons required by the task. | |||||
* | |||||
* @exception BuildException thrown if both rootLocalFolder | |||||
* and viewRootLocalFolder are defined | |||||
*/ | |||||
protected void testPreconditions() throws BuildException { | |||||
} | |||||
/** | |||||
* Implements base-class abstract function to 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 void logOperationDescription( | |||||
Folder starteamrootFolder, java.io.File targetrootFolder) { | |||||
log((this.isRecursive() ? "Recursive" : "Non-recursive") | |||||
+ " Checkin from" | |||||
+ (null == getRootLocalFolder() ? " (default): " : ": ") | |||||
+ targetrootFolder.getAbsolutePath()); | |||||
log("Checking in to: " + starteamrootFolder.getFolderHierarchy()); | |||||
logIncludes(); | |||||
logExcludes(); | |||||
if (this.lockStatus == Item.LockType.UNLOCKED) { | |||||
log(" Items will be checked in unlocked."); | |||||
} else { | |||||
log(" Items will be checked in with no change in lock status."); | |||||
} | |||||
if (this.isForced()) { | |||||
log(" Items will be checked in in accordance with repository " | |||||
+ "status and regardless of lock status."); | |||||
} else { | |||||
log(" Items will be checked in regardless of repository status " | |||||
+ "only if locked."); | |||||
} | |||||
} | |||||
/** | |||||
* Implements base-class abstract function to perform the checkout | |||||
* operation on the files in each folder of the tree. | |||||
* | |||||
* @param starteamFolder the StarTeam folder to which files | |||||
* will be checked in | |||||
* @param targetFolder local folder from which files will be checked in | |||||
* @exception BuildException if any error occurs | |||||
*/ | |||||
protected void visit(Folder starteamFolder, java.io.File targetFolder) | |||||
throws BuildException { | |||||
try { | |||||
if (null != getRootLocalFolder()) { | |||||
starteamFolder.setAlternatePathFragment( | |||||
targetFolder.getAbsolutePath()); | |||||
} | |||||
Folder[] foldersList = starteamFolder.getSubFolders(); | |||||
Item[] stFiles = starteamFolder.getItems(getTypeNames().FILE); | |||||
// note, it's important to scan the items BEFORE we make the | |||||
// UnmatchedFileMap because that creates a bunch of NEW | |||||
// folders and files (unattached to repository) and we | |||||
// don't want to include those in our traversal. | |||||
UnmatchedFileMap ufm = | |||||
new CheckinMap().init( | |||||
targetFolder.getAbsoluteFile(), starteamFolder); | |||||
for (int i = 0, size = foldersList.length; i < size; i++) { | |||||
Folder stFolder = foldersList[i]; | |||||
java.io.File subfolder = | |||||
new java.io.File(targetFolder, stFolder.getName()); | |||||
ufm.removeControlledItem(subfolder); | |||||
if (isRecursive()) { | |||||
visit(stFolder, subfolder); | |||||
} | |||||
} | |||||
for (int i = 0, size = stFiles.length; i < size; i++) { | |||||
com.starbase.starteam.File stFile = | |||||
(com.starbase.starteam.File) stFiles[i]; | |||||
processFile(stFile); | |||||
ufm.removeControlledItem( | |||||
new java.io.File(targetFolder, stFile.getName())); | |||||
} | |||||
if (this.addUncontrolled) { | |||||
ufm.processUncontrolledItems(); | |||||
} | |||||
} catch (IOException e) { | |||||
throw new BuildException(e); | |||||
} | |||||
} | |||||
/** | |||||
* provides a string showing from and to full paths for logging | |||||
* | |||||
* @param remotefile the Star Team file being processed. | |||||
* | |||||
* @return a string showing from and to full paths | |||||
*/ | |||||
private String describeCheckin(com.starbase.starteam.File remotefile) { | |||||
StringBuffer sb = new StringBuffer(); | |||||
sb.append(remotefile.getFullName()) | |||||
.append(" --> ") | |||||
.append(getFullRepositoryPath(remotefile)); | |||||
return sb.toString(); | |||||
} | |||||
/** | |||||
* Processes (checks-out) <code>stFiles</code>files from StarTeam folder. | |||||
* | |||||
* @param eachFile repository file to process | |||||
* @param targetFolder a java.io.File (Folder) to work | |||||
* @throws IOException when StarTeam API fails to work with files | |||||
*/ | |||||
private void processFile(com.starbase.starteam.File eachFile) | |||||
throws IOException { | |||||
String filename = eachFile.getName(); | |||||
// If the file doesn't pass the include/exclude tests, skip it. | |||||
if (!shouldProcess(filename)) { | |||||
log("Excluding " + getFullRepositoryPath(eachFile)); | |||||
return; | |||||
} | |||||
boolean checkin = true; | |||||
int fileStatus = (eachFile.getStatus()); | |||||
// We try to update the status once to give StarTeam | |||||
// another chance. | |||||
if (fileStatus == Status.MERGE || fileStatus == Status.UNKNOWN) { | |||||
eachFile.updateStatus(true, true); | |||||
fileStatus = (eachFile.getStatus()); | |||||
} | |||||
if (fileStatus == Status.MODIFIED) { | |||||
log("Checking in: " + describeCheckin(eachFile)); | |||||
} else if (fileStatus == Status.MISSING) { | |||||
log("Local file missing: " + describeCheckin(eachFile)); | |||||
checkin = false; | |||||
} else { | |||||
if (isForced()) { | |||||
log("Forced checkin of " + describeCheckin(eachFile) | |||||
+ " over status " + Status.name(fileStatus)); | |||||
} else { | |||||
log("Skipping: " + getFullRepositoryPath(eachFile) | |||||
+ " - status: " + Status.name(fileStatus)); | |||||
checkin = false; | |||||
} | |||||
} | |||||
if (checkin) { | |||||
eachFile.checkin(this.comment, this.lockStatus, | |||||
this.isForced(), true, true); | |||||
} | |||||
} | |||||
/** | |||||
* handles the deletion of uncontrolled items | |||||
*/ | |||||
private class CheckinMap extends UnmatchedFileMap { | |||||
protected boolean isActive() { | |||||
return StarTeamCheckin.this.addUncontrolled; | |||||
} | |||||
/** | |||||
* This override adds all its members to the repository. 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. | |||||
*/ | |||||
void processUncontrolledItems() throws BuildException { | |||||
if (this.isActive()) { | |||||
Enumeration e = this.keys(); | |||||
while (e.hasMoreElements()) { | |||||
java.io.File local = (java.io.File) e.nextElement(); | |||||
Item remoteItem = (Item) this.get(local); | |||||
remoteItem.update(); | |||||
// once we find a folder that isn't in the repository, | |||||
// we know we can add it. | |||||
if (local.isDirectory()) { | |||||
Folder folder = (Folder) remoteItem; | |||||
log("Added uncontrolled folder " | |||||
+ folder.getFolderHierarchy() | |||||
+ " from " + local.getAbsoluteFile()); | |||||
if (isRecursive()) { | |||||
UnmatchedFileMap submap = | |||||
new CheckinMap().init(local, folder); | |||||
submap.processUncontrolledItems(); | |||||
} | |||||
} else { | |||||
com.starbase.starteam.File remoteFile = | |||||
(com.starbase.starteam.File) remoteItem; | |||||
log("Added uncontrolled file " | |||||
+ TreeBasedTask.getFullRepositoryPath(remoteFile) | |||||
+ " from " + local.getAbsoluteFile()); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,643 +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.Item; | |||||
import com.starbase.starteam.Status; | |||||
import com.starbase.starteam.View; | |||||
import com.starbase.starteam.ViewConfiguration; | |||||
import java.io.IOException; | |||||
import java.io.File; | |||||
import java.util.Enumeration; | |||||
import java.util.Hashtable; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* Checks out files from a StarTeam project. | |||||
* It also creates all working directories on the | |||||
* local directory if appropriate. Ant Usage: | |||||
* <pre> | |||||
* <taskdef name="starteamcheckout" | |||||
* classname="org.apache.tools.ant.taskdefs.StarTeamCheckout"/> | |||||
* <starteamcheckout username="BuildMaster" password="ant" starteamFolder="Source" | |||||
* starteamurl="servername:portnum/project/view" | |||||
* createworkingdirectories="true"/> | |||||
* </pre> | |||||
* | |||||
* @version 1.1 | |||||
* @see <a href="http://www.borland.com/us/products/starteam/index.html" | |||||
* >borland StarTeam Web Site</a> | |||||
* | |||||
* @ant.task name="stcheckout" category="scm" | |||||
*/ | |||||
public class StarTeamCheckout extends TreeBasedTask { | |||||
/** | |||||
* holder for the createDirs attribute | |||||
*/ | |||||
private boolean createDirs = true; | |||||
/** | |||||
* holder for the deleteUncontrolled attribute. If true, | |||||
* all local files not in StarTeam will be deleted. | |||||
*/ | |||||
private boolean deleteUncontrolled = true; | |||||
/** | |||||
* holder for the deleteUncontrolled attribute. If true, | |||||
* (default) local non-binary files will be checked out using the local | |||||
* platform's EOL convention. If false, checkouts will preserve the | |||||
* server's EOL convention. | |||||
*/ | |||||
private boolean convertEOL = true; | |||||
/** | |||||
* flag (defaults to true) to create all directories | |||||
* that are in the Starteam repository even if they are empty. | |||||
* | |||||
* @param value the value to set the attribute to. | |||||
*/ | |||||
public void setCreateWorkingDirs(boolean value) { | |||||
this.createDirs = value; | |||||
} | |||||
/** | |||||
* Whether or not all local files <i>not<i> in StarTeam should be deleted. | |||||
* Optional, defaults to <code>true</code>. | |||||
* @param value the value to set the attribute to. | |||||
*/ | |||||
public void setDeleteUncontrolled(boolean value) { | |||||
this.deleteUncontrolled = value; | |||||
} | |||||
/** | |||||
* Set whether or not files should be checked out using the | |||||
* local machine's EOL convention. | |||||
* Optional, defaults to <code>true</code>. | |||||
* @param value the value to set the attribute to. | |||||
*/ | |||||
public void setConvertEOL(boolean value) { | |||||
this.convertEOL = value; | |||||
} | |||||
/** | |||||
* Sets the label StarTeam is to use for checkout; defaults to the most recent file. | |||||
* The label must exist in starteam or an exception will be thrown. | |||||
* @param label the label to be used | |||||
*/ | |||||
public void setLabel(String label) { | |||||
_setLabel(label); | |||||
} | |||||
/** | |||||
* This attribute tells whether to do a locked checkout, an unlocked | |||||
* checkout or to leave the checkout status alone (default). A locked | |||||
* checkout locks all other users out from making changes. An unlocked | |||||
* checkout reverts all local files to their previous repository status | |||||
* and removes the lock. | |||||
* @see #setLocked(boolean) | |||||
* @see #setUnlocked(boolean) | |||||
*/ | |||||
private int lockStatus = Item.LockType.UNCHANGED; | |||||
/** | |||||
* Set to do a locked checkout; optional default is false. | |||||
* @param v True to do a locked checkout, false to checkout without | |||||
* changing status/. | |||||
* @exception BuildException if both locked and unlocked are set true | |||||
*/ | |||||
public void setLocked(boolean v) throws BuildException { | |||||
setLockStatus(v, Item.LockType.EXCLUSIVE); | |||||
} | |||||
/** | |||||
* Set to do an unlocked checkout. Default is false; | |||||
* @param v True to do an unlocked checkout, false to checkout without | |||||
* changing status. | |||||
* @exception BuildException if both locked and unlocked are set true | |||||
*/ | |||||
public void setUnlocked(boolean v) throws BuildException { | |||||
setLockStatus(v, Item.LockType.UNLOCKED); | |||||
} | |||||
private void setLockStatus(boolean v, int newStatus) | |||||
throws BuildException { | |||||
if (v) { | |||||
if (this.lockStatus == Item.LockType.UNCHANGED) { | |||||
this.lockStatus = newStatus; | |||||
} else if (this.lockStatus != newStatus) { | |||||
throw new BuildException( | |||||
"Error: cannot set locked and unlocked both true."); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* should checked out files get the timestamp from the repository | |||||
* or the time they are checked out. True means use the repository | |||||
* timestamp. | |||||
*/ | |||||
private boolean useRepositoryTimeStamp = false; | |||||
/** | |||||
* sets the useRepositoryTimestmp member. | |||||
* | |||||
* @param useRepositoryTimeStamp | |||||
* true means checked out files will get the repository timestamp. | |||||
* false means the checked out files will be timestamped at the time | |||||
* of checkout. | |||||
*/ | |||||
public void setUseRepositoryTimeStamp(boolean useRepositoryTimeStamp) { | |||||
this.useRepositoryTimeStamp = useRepositoryTimeStamp; | |||||
} | |||||
/** | |||||
* returns the value of the useRepositoryTimestamp member | |||||
* | |||||
* @return the value of the useRepositoryTimestamp member | |||||
*/ | |||||
public boolean getUseRepositoryTimeStamp() { | |||||
return this.useRepositoryTimeStamp; | |||||
} | |||||
/** | |||||
* List files, dates, and statuses as of this date; optional. | |||||
* If not specified, the most recent version of each file will be listed. | |||||
* | |||||
* @param asOfDateParam the date as of which the listing to be made | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setAsOfDate(String asOfDateParam) { | |||||
_setAsOfDate(asOfDateParam); | |||||
} | |||||
/** | |||||
* Date Format with which asOfDate parameter to be parsed; optional. | |||||
* Must be a SimpleDateFormat compatible string. | |||||
* If not specified, and asOfDateParam is specified, parse will use ISO8601 | |||||
* datetime and date formats. | |||||
* | |||||
* @param asOfDateFormat the SimpleDateFormat-compatible format string | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setAsOfDateFormat(String asOfDateFormat) { | |||||
_setAsOfDateFormat(asOfDateFormat); | |||||
} | |||||
/** | |||||
* Override of base-class abstract function creates an | |||||
* appropriately configured view for checkouts - either | |||||
* the current view or a view from this.label or the raw | |||||
* view itself in the case of a revision label. | |||||
* | |||||
* @param raw the unconfigured <code>View</code> | |||||
* | |||||
* @return the snapshot <code>View</code> appropriately configured. | |||||
* @exception BuildException on error | |||||
*/ | |||||
protected View createSnapshotView(View raw) throws BuildException { | |||||
int labelID = getLabelID(raw); | |||||
// if a label has been supplied and it is a view label, use it | |||||
// to configure the view | |||||
if (this.isUsingViewLabel()) { | |||||
return new View(raw, ViewConfiguration.createFromLabel(labelID)); | |||||
// if a label has been supplied and it is a revision label, use the raw | |||||
// the view as the snapshot | |||||
} else if (this.isUsingRevisionLabel()) { | |||||
return raw; | |||||
} | |||||
// if a date has been supplied use a view configured to the date. | |||||
View view = getViewConfiguredByDate(raw); | |||||
if (view != null) { | |||||
return view; | |||||
// otherwise, use this view configured as the tip. | |||||
} else { | |||||
return new View(raw, ViewConfiguration.createTip()); | |||||
} | |||||
} | |||||
/** | |||||
* Implements base-class abstract function to define tests for | |||||
* any preconditons required by the task. | |||||
* | |||||
* @exception BuildException thrown if both rootLocalFolder | |||||
* and viewRootLocalFolder are defined | |||||
*/ | |||||
protected void testPreconditions() throws BuildException { | |||||
if (this.isUsingRevisionLabel() && this.createDirs) { | |||||
log("Ignoring createworkingdirs while using a revision label." | |||||
+ " Folders will be created only as needed.", | |||||
Project.MSG_WARN); | |||||
this.createDirs = false; | |||||
} | |||||
if (lockStatus != Item.LockType.UNCHANGED) { | |||||
boolean lockStatusBad = false; | |||||
if (null != getLabel()) { | |||||
log("Neither locked nor unlocked may be true" | |||||
+ " when checking out a labeled version.", | |||||
Project.MSG_ERR); | |||||
lockStatusBad = true; | |||||
} else if (null != getAsOfDate()) { | |||||
log("Neither locked nor unlocked may be true" | |||||
+ " when checking out by date.", | |||||
Project.MSG_ERR); | |||||
lockStatusBad = true; | |||||
} | |||||
if (lockStatusBad) { | |||||
throw new BuildException( | |||||
"Lock status may not be changed" | |||||
+ " when checking out a non-current version."); | |||||
} | |||||
} | |||||
if (null != getLabel() && null != getAsOfDate()) { | |||||
throw new BuildException( | |||||
"Both label and asOfDate specified. " | |||||
+ "Unable to process request."); | |||||
} | |||||
} | |||||
/** | |||||
* 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 void logOperationDescription( | |||||
Folder starteamrootFolder, java.io.File targetrootFolder) { | |||||
log((this.isRecursive() ? "Recursive" : "Non-recursive") | |||||
+ " Checkout from: " + starteamrootFolder.getFolderHierarchy()); | |||||
log(" Checking out to" | |||||
+ (null == getRootLocalFolder() ? "(default): " : ": ") | |||||
+ targetrootFolder.getAbsolutePath()); | |||||
logLabel(); | |||||
logAsOfDate(); | |||||
logIncludes(); | |||||
logExcludes(); | |||||
if (this.lockStatus == Item.LockType.EXCLUSIVE) { | |||||
log(" Items will be checked out with Exclusive locks."); | |||||
} else if (this.lockStatus == Item.LockType.UNLOCKED) { | |||||
log(" Items will be checked out unlocked " | |||||
+ "(even if presently locked)."); | |||||
} else { | |||||
log(" Items will be checked out with no change in lock status."); | |||||
} | |||||
log(" Items will be checked out with " | |||||
+ (this.useRepositoryTimeStamp ? "repository timestamps." | |||||
: "the current timestamp.")); | |||||
log(" Items will be checked out " | |||||
+ (this.isForced() ? "regardless of" : "in accordance with") | |||||
+ " repository status."); | |||||
if (this.deleteUncontrolled) { | |||||
log(" Local items not found in the repository will be deleted."); | |||||
} | |||||
log(" Items will be checked out " | |||||
+ (this.convertEOL ? "using the local machine's EOL convention" | |||||
: "without changing the EOL convention used on the server")); | |||||
log(" Directories will be created" | |||||
+ (this.createDirs ? " wherever they exist in the repository, even if empty." | |||||
: " only where needed to check out files.")); | |||||
} | |||||
/** | |||||
* Implements base-class abstract function to perform the checkout | |||||
* operation on the files in each folder of the tree. | |||||
* | |||||
* @param starteamFolder the StarTeam folder from which files to be | |||||
* checked out | |||||
* @param targetFolder the local mapping of rootStarteamFolder | |||||
* @exception BuildException if any error occurs | |||||
*/ | |||||
protected void visit(Folder starteamFolder, java.io.File targetFolder) | |||||
throws BuildException { | |||||
try { | |||||
if (null != getRootLocalFolder()) { | |||||
starteamFolder.setAlternatePathFragment( | |||||
targetFolder.getAbsolutePath()); | |||||
} | |||||
if (!targetFolder.exists()) { | |||||
if (!this.isUsingRevisionLabel()) { | |||||
if (this.createDirs) { | |||||
if (targetFolder.mkdirs()) { | |||||
log("Creating folder: " + targetFolder); | |||||
} else { | |||||
throw new BuildException( | |||||
"Failed to create local folder " + targetFolder); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
Folder[] foldersList = starteamFolder.getSubFolders(); | |||||
Item[] filesList = starteamFolder.getItems(getTypeNames().FILE); | |||||
if (this.isUsingRevisionLabel()) { | |||||
// prune away any files not belonging to the revision label | |||||
// this is one ugly API from Starteam SDK | |||||
Hashtable labelItems = new Hashtable(filesList.length); | |||||
int s = filesList.length; | |||||
int[] ids = new int[s]; | |||||
for (int i = 0; i < s; i++) { | |||||
ids[i] = filesList[i].getItemID(); | |||||
labelItems.put(new Integer(ids[i]), new Integer(i)); | |||||
} | |||||
int[] foundIds = getLabelInUse().getLabeledItemIDs(ids); | |||||
s = foundIds.length; | |||||
Item[] labeledFiles = new Item[s]; | |||||
for (int i = 0; i < s; i++) { | |||||
Integer id = new Integer(foundIds[i]); | |||||
labeledFiles[i] = | |||||
filesList[((Integer) labelItems.get(id)).intValue()]; | |||||
} | |||||
filesList = labeledFiles; | |||||
} | |||||
// note, it's important to scan the items BEFORE we make the | |||||
// Unmatched file map because that creates a bunch of NEW | |||||
// folders and files (unattached to repository) and we | |||||
// don't want to include those in our traversal. | |||||
UnmatchedFileMap ufm = | |||||
new CheckoutMap(). | |||||
init(targetFolder.getAbsoluteFile(), starteamFolder); | |||||
for (int i = 0; i < foldersList.length; i++) { | |||||
Folder stFolder = foldersList[i]; | |||||
java.io.File subfolder = | |||||
new java.io.File(targetFolder, stFolder.getName()); | |||||
ufm.removeControlledItem(subfolder); | |||||
if (isRecursive()) { | |||||
visit(stFolder, subfolder); | |||||
} | |||||
} | |||||
for (int i = 0; i < filesList.length; i++) { | |||||
com.starbase.starteam.File stFile = | |||||
(com.starbase.starteam.File) filesList[i]; | |||||
processFile(stFile, targetFolder); | |||||
ufm.removeControlledItem( | |||||
new java.io.File(targetFolder, stFile.getName())); | |||||
} | |||||
if (this.deleteUncontrolled) { | |||||
ufm.processUncontrolledItems(); | |||||
} | |||||
} catch (IOException e) { | |||||
throw new BuildException(e); | |||||
} | |||||
} | |||||
/** | |||||
* provides a string showing from and to full paths for logging | |||||
* | |||||
* @param remotefile the Star Team file being processed. | |||||
* | |||||
* @return a string showing from and to full paths | |||||
*/ | |||||
private String describeCheckout(com.starbase.starteam.File remotefile, | |||||
java.io.File localFile) { | |||||
StringBuffer sb = new StringBuffer(); | |||||
sb.append(getFullRepositoryPath(remotefile)) | |||||
.append(" --> "); | |||||
if (null == localFile) { | |||||
sb.append(remotefile.getFullName()); | |||||
} else { | |||||
sb.append(localFile); | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
private String describeCheckout(com.starbase.starteam.File remotefile) { | |||||
return describeCheckout(remotefile, null); | |||||
} | |||||
/** | |||||
* Processes (checks out) <code>stFiles</code>files from StarTeam folder. | |||||
* | |||||
* @param eachFile repository file to process | |||||
* @param targetFolder a java.io.File (Folder) to work | |||||
* @throws IOException when StarTeam API fails to work with files | |||||
*/ | |||||
private void processFile(com.starbase.starteam.File eachFile, | |||||
File targetFolder) | |||||
throws IOException { | |||||
String filename = eachFile.getName(); | |||||
java.io.File localFile = new java.io.File(targetFolder, filename); | |||||
// If the file doesn't pass the include/exclude tests, skip it. | |||||
if (!shouldProcess(filename)) { | |||||
log("Excluding " + getFullRepositoryPath(eachFile), | |||||
Project.MSG_INFO); | |||||
return; | |||||
} | |||||
if (this.isUsingRevisionLabel()) { | |||||
if (!targetFolder.exists()) { | |||||
if (targetFolder.mkdirs()) { | |||||
log("Creating folder: " + targetFolder); | |||||
} else { | |||||
throw new BuildException( | |||||
"Failed to create local folder " + targetFolder); | |||||
} | |||||
} | |||||
boolean success = eachFile.checkoutByLabelID( | |||||
localFile, | |||||
getIDofLabelInUse(), | |||||
this.lockStatus, | |||||
!this.useRepositoryTimeStamp, | |||||
true, | |||||
false); | |||||
if (success) { | |||||
log("Checked out " + describeCheckout(eachFile, localFile)); | |||||
} | |||||
} else { | |||||
boolean checkout = true; | |||||
// Just a note: StarTeam has a status for NEW which implies | |||||
// that there is an item on your local machine that is not | |||||
// in the repository. These are the items that show up as | |||||
// NOT IN VIEW in the Starteam GUI. | |||||
// One would think that we would want to perhaps checkin the | |||||
// NEW items (not in all cases! - Steve Cohen 15 Dec 2001) | |||||
// Unfortunately, the sdk doesn't really work, and we can't | |||||
// actually see anything with a status of NEW. That is why | |||||
// we can just check out everything here without worrying | |||||
// about losing anything. | |||||
int fileStatus = (eachFile.getStatus()); | |||||
// We try to update the status once to give StarTeam | |||||
// another chance. | |||||
if (fileStatus == Status.MERGE | |||||
|| fileStatus == Status.UNKNOWN) { | |||||
eachFile.updateStatus(true, true); | |||||
fileStatus = (eachFile.getStatus()); | |||||
} | |||||
log(eachFile.toString() + " has status of " | |||||
+ Status.name(fileStatus), Project.MSG_DEBUG); | |||||
switch (fileStatus) { | |||||
case Status.OUTOFDATE: | |||||
case Status.MISSING: | |||||
log("Checking out: " + describeCheckout(eachFile)); | |||||
break; | |||||
default: | |||||
if (isForced() && fileStatus != Status.CURRENT) { | |||||
log("Forced checkout of " | |||||
+ describeCheckout(eachFile) | |||||
+ " over status " + Status.name(fileStatus)); | |||||
} else { | |||||
log("Skipping: " + getFullRepositoryPath(eachFile) | |||||
+ " - status: " + Status.name(fileStatus)); | |||||
checkout = false; | |||||
} | |||||
} | |||||
if (checkout) { | |||||
if (!targetFolder.exists()) { | |||||
if (targetFolder.mkdirs()) { | |||||
log("Creating folder: " + targetFolder); | |||||
} else { | |||||
throw new BuildException( | |||||
"Failed to create local folder " + targetFolder); | |||||
} | |||||
} | |||||
eachFile.checkout(this.lockStatus, | |||||
!this.useRepositoryTimeStamp, this.convertEOL, false); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* handles the deletion of uncontrolled items | |||||
*/ | |||||
private class CheckoutMap extends UnmatchedFileMap { | |||||
protected boolean isActive() { | |||||
return StarTeamCheckout.this.deleteUncontrolled; | |||||
} | |||||
/** | |||||
* override of the base class init. It can be much simpler, since | |||||
* the action to be taken is simply to delete the local files. No | |||||
* further interaction with the repository is necessary. | |||||
* | |||||
* @param localFolder | |||||
* the local folder from which the mappings will be made. | |||||
* @param remoteFolder | |||||
* not used in this implementation | |||||
*/ | |||||
UnmatchedFileMap init(java.io.File localFolder, Folder remoteFolder) { | |||||
if (!localFolder.exists()) { | |||||
return this; | |||||
} | |||||
String[] localFiles = localFolder.list(); | |||||
// PR 31965 says that it can return null | |||||
if (localFiles == null) { | |||||
return this; | |||||
} | |||||
for (int i = 0; i < localFiles.length; 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, ""); | |||||
} else { | |||||
this.put(localFile, ""); | |||||
} | |||||
} | |||||
return this; | |||||
} | |||||
/** | |||||
* deletes uncontrolled items from the local tree. 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. | |||||
*/ | |||||
void processUncontrolledItems() throws BuildException { | |||||
if (this.isActive()) { | |||||
Enumeration e = this.keys(); | |||||
while (e.hasMoreElements()) { | |||||
java.io.File local = (java.io.File) e.nextElement(); | |||||
delete(local); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* deletes all files and if the file is a folder recursively deletes | |||||
* everything in it. | |||||
* | |||||
* @param local The local file or folder to be deleted. | |||||
*/ | |||||
void delete(java.io.File local) { | |||||
// once we find a folder that isn't in the repository, | |||||
// anything below it can be deleted. | |||||
if (local.isDirectory() && isRecursive()) { | |||||
String[] contents = local.list(); | |||||
for (int i = 0; i < contents.length; i++) { | |||||
java.io.File file = new java.io.File(local, contents[i]); | |||||
delete(file); | |||||
} | |||||
} | |||||
local.delete(); | |||||
log("Deleted uncontrolled item " + local.getAbsolutePath()); | |||||
} | |||||
} | |||||
} |
@@ -1,196 +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.Label; | |||||
import com.starbase.starteam.View; | |||||
import com.starbase.util.OLEDate; | |||||
import java.text.ParseException; | |||||
import java.text.SimpleDateFormat; | |||||
import java.util.Date; | |||||
import org.apache.tools.ant.BuildException; | |||||
/** | |||||
* Creates a view label in StarTeam at the specified view. | |||||
* | |||||
* Ant Usage: | |||||
* <pre> | |||||
* <taskdef name="stlabel" | |||||
* classname="org.apache.tools.ant.taskdefs.optional.starteam.StarTeamLabel"/< | |||||
* <stlabel | |||||
* label="1.0" lastbuild="20011514100000" description="Successful Build" | |||||
* username="BuildMaster" password="ant" | |||||
* starteamurl="server:port/project/view"/> | |||||
* </pre> | |||||
* | |||||
* @see <a href="http://www.borland.com/us/products/starteam/index.html" | |||||
* >borland StarTeam Web Site</a> | |||||
* | |||||
* @ant.task name="stlabel" category="scm" | |||||
*/ | |||||
public class StarTeamLabel extends StarTeamTask { | |||||
/** | |||||
* The name of the label to be set in Starteam. | |||||
*/ | |||||
private String labelName; | |||||
/** | |||||
* The label description to be set in Starteam. | |||||
*/ | |||||
private String description; | |||||
/** | |||||
* If true, this will be a build label. If false, it will be a non-build | |||||
* label. The default is false. Has no effect if revision label is | |||||
* true. | |||||
*/ | |||||
private boolean buildlabel = false; | |||||
/** | |||||
* If true, this will be a revision label. If false, it will be a build | |||||
* label. The default is false. | |||||
*/ | |||||
private boolean revisionlabel = false; | |||||
/** | |||||
* The time of the last successful. The new label will be a snapshot of the | |||||
* repository at this time. String should be formatted as "yyyyMMddHHmmss" | |||||
*/ | |||||
private OLEDate lastBuild = null; | |||||
private static final SimpleDateFormat DATE_FORMAT = | |||||
new SimpleDateFormat("yyyyMMddHHmmss"); | |||||
/** | |||||
* The name to be given to the label; required. | |||||
* @param label the name to be used | |||||
*/ | |||||
public void setLabel(String label) { | |||||
this.labelName = label; | |||||
} | |||||
/** | |||||
* Description of the label to be stored in the StarTeam project. | |||||
* @param description the description to be used | |||||
*/ | |||||
public void setDescription(String description) { | |||||
this.description = description; | |||||
} | |||||
/** | |||||
* set the type of label based on the supplied value - if true, this | |||||
* label will be a revision label, if false, a build label. | |||||
* | |||||
* @param buildlabel If true this will be a revision label; if false, | |||||
* a build label | |||||
*/ | |||||
public void setBuildLabel(boolean buildlabel) { | |||||
this.buildlabel = buildlabel; | |||||
} | |||||
/** | |||||
* set the type of label based on the supplied value - if true, this | |||||
* label will be a revision label, if false, a build label. | |||||
* | |||||
* @param revisionlabel If true this will be a revision label; if false, | |||||
* a build label | |||||
*/ | |||||
public void setRevisionLabel(boolean revisionlabel) { | |||||
this.revisionlabel = revisionlabel; | |||||
} | |||||
/** | |||||
* The timestamp of the build that will be stored with the label; required. | |||||
* Must be formatted <code>yyyyMMddHHmmss</code> | |||||
* @param lastbuild the timestamp of the last build | |||||
* @throws BuildException on error | |||||
*/ | |||||
public void setLastBuild(String lastbuild) throws BuildException { | |||||
try { | |||||
Date lastBuildTime = DATE_FORMAT.parse(lastbuild); | |||||
this.lastBuild = new OLEDate(lastBuildTime); | |||||
} catch (ParseException e) { | |||||
throw new BuildException("Unable to parse the date '" | |||||
+ lastbuild + "'", e); | |||||
} | |||||
} | |||||
/** | |||||
* This method does the work of creating the new view and checking it into | |||||
* Starteam. | |||||
* @throws BuildException on error | |||||
*/ | |||||
public void execute() throws BuildException { | |||||
if (this.revisionlabel && this.buildlabel) { | |||||
throw new BuildException("'revisionlabel' and 'buildlabel' " | |||||
+ "both specified. A revision label cannot be a build label."); | |||||
} | |||||
try { | |||||
View snapshot = openView(); | |||||
// Create the new label and update the repository | |||||
if (this.revisionlabel) { | |||||
new Label(snapshot, this.labelName, this.description).update(); | |||||
log("Created Revision Label " + this.labelName); | |||||
} else if (null != lastBuild) { | |||||
new Label(snapshot, this.labelName, this.description, this.lastBuild, | |||||
this.buildlabel).update(); | |||||
log("Created View Label (" | |||||
+ (this.buildlabel ? "" : "non-") + "build) " + this.labelName | |||||
+ " as of " + this.lastBuild.toString()); | |||||
} else { | |||||
new Label(snapshot, this.labelName, this.description, | |||||
this.buildlabel).update(); | |||||
log("Created View Label (" | |||||
+ (this.buildlabel ? "" : "non-") + "build) " + this.labelName); | |||||
} | |||||
} catch (Exception e) { | |||||
throw new BuildException(e); | |||||
} finally { | |||||
disconnectFromServer(); | |||||
} | |||||
} | |||||
/** | |||||
* Override of base-class abstract function creates an | |||||
* appropriately configured view. For labels this a view | |||||
* configured as of this.lastBuild. | |||||
* | |||||
* @param raw the unconfigured <code>View</code> | |||||
* @return the snapshot <code>View</code> appropriately configured. | |||||
*/ | |||||
protected View createSnapshotView(View raw) { | |||||
/* | |||||
if (this.revisionlabel) { | |||||
return raw; | |||||
} | |||||
return new View(raw, ViewConfiguration.createFromTime(this.lastBuild)); | |||||
*/ | |||||
return raw; | |||||
} | |||||
} | |||||
@@ -1,338 +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.File; | |||||
import com.starbase.starteam.Folder; | |||||
import com.starbase.starteam.Item; | |||||
import com.starbase.starteam.Status; | |||||
import com.starbase.starteam.View; | |||||
import com.starbase.starteam.ViewConfiguration; | |||||
import java.io.IOException; | |||||
import java.text.SimpleDateFormat; | |||||
import java.util.Enumeration; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | |||||
/** | |||||
* Produces a listing of the contents of the StarTeam repository | |||||
* at the specified view and StarTeamFolder. | |||||
* | |||||
* Created: Tue Dec 25 06:51:14 2001 | |||||
* | |||||
* @version 1.0 | |||||
* | |||||
* @ant.task name="stlist" category="scm" | |||||
*/ | |||||
public class StarTeamList extends TreeBasedTask { | |||||
private boolean listUncontrolled = true; | |||||
/** | |||||
* List files, dates, and statuses as of this label; optional. | |||||
* The label must exist in starteam or an exception will be thrown. | |||||
* If not specified, the most recent version of each file will be listed. | |||||
* | |||||
* @param label the label to be listed | |||||
*/ | |||||
public void setLabel(String label) { | |||||
_setLabel(label); | |||||
} | |||||
/** | |||||
* List files, dates, and statuses as of this date; optional. | |||||
* If not specified, the most recent version of each file will be listed. | |||||
* | |||||
* @param asOfDateParam the date as of which the listing to be made | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setAsOfDate(String asOfDateParam) { | |||||
_setAsOfDate(asOfDateParam); | |||||
} | |||||
/** | |||||
* Date Format with which asOfDate parameter to be parsed; optional. | |||||
* Must be a SimpleDateFormat compatible string. | |||||
* If not specified, and asOfDateParam is specified, parse will use ISO8601 | |||||
* datetime and date formats. | |||||
* | |||||
* @param asOfDateFormat the SimpleDateFormat-compatible format string | |||||
* @since Ant 1.6 | |||||
*/ | |||||
public void setAsOfDateFormat(String asOfDateFormat) { | |||||
_setAsOfDateFormat(asOfDateFormat); | |||||
} | |||||
/** | |||||
* Override of base-class abstract function creates an | |||||
* appropriately configured view for checkoutlists - either | |||||
* the current view or a view from this.label. | |||||
* | |||||
* @param raw the unconfigured <code>View</code> | |||||
* @return the snapshot <code>View</code> appropriately configured. | |||||
*/ | |||||
protected View createSnapshotView(View raw) { | |||||
int labelID = getLabelID(raw); | |||||
// if a label has been supplied, use it to configure the view | |||||
// otherwise use current view | |||||
if (labelID >= 0) { | |||||
return new View(raw, ViewConfiguration.createFromLabel(labelID)); | |||||
} | |||||
// if a date has been supplied use a view configured to the date. | |||||
View view = getViewConfiguredByDate(raw); | |||||
if (view != null) { | |||||
return view; | |||||
// otherwise, use this view configured as the tip. | |||||
} else { | |||||
return new View(raw, ViewConfiguration.createTip()); | |||||
} | |||||
} | |||||
/** | |||||
* Required base-class abstract function implementation checks for | |||||
* incompatible parameters. | |||||
* | |||||
* @exception BuildException thrown on incompatible params specified | |||||
*/ | |||||
protected void testPreconditions() throws BuildException { | |||||
if (null != getLabel() && null != getAsOfDate()) { | |||||
throw new BuildException( | |||||
"Both label and asOfDate specified. " | |||||
+ "Unable to process request."); | |||||
} | |||||
} | |||||
/** | |||||
* 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 void logOperationDescription(Folder starteamrootFolder, | |||||
java.io.File targetrootFolder) { | |||||
log((this.isRecursive() ? "Recursive" : "Non-recursive") | |||||
+ " Listing of: " + starteamrootFolder.getFolderHierarchy()); | |||||
log("Listing against local folder" | |||||
+ (null == getRootLocalFolder() ? " (default): " : ": ") | |||||
+ targetrootFolder.getAbsolutePath(), | |||||
Project.MSG_INFO); | |||||
logLabel(); | |||||
logAsOfDate(); | |||||
logIncludes(); | |||||
logExcludes(); | |||||
} | |||||
/** | |||||
* Implements base-class abstract function to perform the checkout | |||||
* operation on the files in each folder of the tree. | |||||
* | |||||
* @param starteamFolder the StarTeam folder from which files to be | |||||
* checked out | |||||
* @param targetFolder the local mapping of rootStarteamFolder | |||||
* @throws BuildException on error | |||||
*/ | |||||
protected void visit(Folder starteamFolder, java.io.File targetFolder) | |||||
throws BuildException { | |||||
try { | |||||
if (null != getRootLocalFolder()) { | |||||
starteamFolder.setAlternatePathFragment( | |||||
targetFolder.getAbsolutePath()); | |||||
} | |||||
Folder[] subFolders = starteamFolder.getSubFolders(); | |||||
Item[] files = starteamFolder.getItems(getTypeNames().FILE); | |||||
UnmatchedFileMap ufm = | |||||
new UnmatchedListingMap().init( | |||||
targetFolder.getAbsoluteFile(), starteamFolder); | |||||
log(""); | |||||
log("Listing StarTeam folder " | |||||
+ starteamFolder.getFolderHierarchy()); | |||||
log(" against local folder " + targetFolder.getAbsolutePath()); | |||||
// For all Files in this folder, we need to check | |||||
// if there have been modifications. | |||||
for (int i = 0; i < files.length; i++) { | |||||
File eachFile = (File) files[i]; | |||||
String filename = eachFile.getName(); | |||||
java.io.File localFile = | |||||
new java.io.File(targetFolder, filename); | |||||
ufm.removeControlledItem(localFile); | |||||
// If the file doesn't pass the include/exclude tests, skip it. | |||||
if (!shouldProcess(filename)) { | |||||
continue; | |||||
} | |||||
list(eachFile, localFile); | |||||
} | |||||
// Now we recursively call this method on all sub folders in this | |||||
// folder unless recursive attribute is off. | |||||
for (int i = 0; i < subFolders.length; i++) { | |||||
java.io.File targetSubfolder = | |||||
new java.io.File(targetFolder, subFolders[i].getName()); | |||||
ufm.removeControlledItem(targetSubfolder); | |||||
if (isRecursive()) { | |||||
visit(subFolders[i], targetSubfolder); | |||||
} | |||||
} | |||||
if (this.listUncontrolled) { | |||||
ufm.processUncontrolledItems(); | |||||
} | |||||
} catch (IOException e) { | |||||
throw new BuildException(e); | |||||
} | |||||
} | |||||
private static final SimpleDateFormat SDF = | |||||
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss zzz"); | |||||
/** | |||||
* Log a repositary file and it's corresponding local file. | |||||
* @param reposFile the repositary file to log | |||||
* @param localFile the corresponding local file | |||||
* @throws IOException on error getting information from files | |||||
*/ | |||||
protected void list(File reposFile, java.io.File localFile) | |||||
throws IOException { | |||||
StringBuffer b = new StringBuffer(); | |||||
int status = reposFile.getStatus(); | |||||
java.util.Date displayDate = null; | |||||
if (status == Status.NEW) { | |||||
displayDate = new java.util.Date(localFile.lastModified()); | |||||
} else { | |||||
displayDate = reposFile.getModifiedTime().createDate(); | |||||
} | |||||
b.append(pad(Status.name(status), 12)).append(' '); | |||||
b.append(pad(getUserName(reposFile.getLocker()), 20)) | |||||
.append(' ') | |||||
.append(SDF.format(displayDate)) | |||||
.append(rpad(String.valueOf(reposFile.getSize()), 9)) | |||||
.append(' ') | |||||
.append(reposFile.getName()); | |||||
log(b.toString()); | |||||
} | |||||
private static final String BLANK_STRING = blanks(30); | |||||
private static String blanks(int len) { | |||||
StringBuffer b = new StringBuffer(); | |||||
for (int i = 0; i < len; i++) { | |||||
b.append(' '); | |||||
} | |||||
return b.toString(); | |||||
} | |||||
/** | |||||
* Return a padded string. | |||||
* @param s the string to pad | |||||
* @param padlen the size of the padded string | |||||
* @return the padded string | |||||
*/ | |||||
protected static String pad(String s, int padlen) { | |||||
return (s + BLANK_STRING).substring(0, padlen); | |||||
} | |||||
/** | |||||
* Return a right padded string. | |||||
* @param s the string to pad | |||||
* @param padlen the size of the padded string | |||||
* @return the padded string | |||||
*/ | |||||
protected static String rpad(String s, int padlen) { | |||||
s = BLANK_STRING + s; | |||||
return s.substring(s.length() - padlen); | |||||
} | |||||
/** | |||||
* handles the list of uncontrolled items | |||||
*/ | |||||
private class UnmatchedListingMap extends UnmatchedFileMap { | |||||
protected boolean isActive() { | |||||
return StarTeamList.this.listUncontrolled; | |||||
} | |||||
/** | |||||
* lists uncontrolled items from the local tree. 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. | |||||
*/ | |||||
void processUncontrolledItems() throws BuildException { | |||||
if (this.isActive()) { | |||||
Enumeration e = this.keys(); | |||||
// handle the files so they appear first | |||||
while (e.hasMoreElements()) { | |||||
java.io.File local = (java.io.File) e.nextElement(); | |||||
Item remoteItem = (Item) this.get(local); | |||||
// once we find a folder that isn't in the repository, | |||||
// we know we can add it. | |||||
if (local.isFile()) { | |||||
com.starbase.starteam.File remoteFile = | |||||
(com.starbase.starteam.File) remoteItem; | |||||
try { | |||||
list(remoteFile, local); | |||||
} catch (IOException ie) { | |||||
throw new BuildException("IOError in stlist", ie); | |||||
} | |||||
} | |||||
} | |||||
// now do it again for the directories so they appear last. | |||||
e = this.keys(); | |||||
while (e.hasMoreElements()) { | |||||
java.io.File local = (java.io.File) e.nextElement(); | |||||
Item remoteItem = (Item) this.get(local); | |||||
// once we find a folder that isn't in the repository, | |||||
// we know we can add it. | |||||
if (local.isDirectory()) { | |||||
Folder folder = (Folder) remoteItem; | |||||
if (isRecursive()) { | |||||
log("Listing uncontrolled folder " | |||||
+ folder.getFolderHierarchy() | |||||
+ " from " + local.getAbsoluteFile()); | |||||
UnmatchedFileMap submap = | |||||
new UnmatchedListingMap().init(local, folder); | |||||
submap.processUncontrolledItems(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
@@ -1,362 +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.BuildNumber; | |||||
import com.starbase.starteam.Server; | |||||
import com.starbase.starteam.StarTeamFinder; | |||||
import com.starbase.starteam.TypeNames; | |||||
import com.starbase.starteam.User; | |||||
import com.starbase.starteam.View; | |||||
import java.util.StringTokenizer; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.Task; | |||||
/** | |||||
* Common super class for all StarTeam tasks. | |||||
* At this level of the hierarchy we are concerned only with obtaining a | |||||
* connection to the StarTeam server. The subclass <code>TreeBasedTask</code>, | |||||
* also abstract defines the tree-walking behavior common to many subtasks. | |||||
* | |||||
* @see TreeBasedTask | |||||
* @version 1.1 | |||||
*/ | |||||
public abstract class StarTeamTask extends Task { | |||||
// ATTRIBUTES | |||||
/** | |||||
* The username of the connection | |||||
*/ | |||||
private String userName; | |||||
/** | |||||
* The username of the connection | |||||
*/ | |||||
private String password; | |||||
/** | |||||
* name of Starteam server to connect to | |||||
*/ | |||||
private String servername; | |||||
/** | |||||
* port of Starteam server to connect to | |||||
*/ | |||||
private String serverport; | |||||
/** | |||||
* name of Starteam project to connect to | |||||
*/ | |||||
private String projectname; | |||||
/** | |||||
* name of Starteam view to connect to | |||||
*/ | |||||
private String viewname; | |||||
/** | |||||
*The starteam server through which all activities will be done. | |||||
*/ | |||||
private Server server = null; | |||||
private void logStarteamVersion() { | |||||
log("StarTeam version: " | |||||
+ BuildNumber.getDisplayString(), Project.MSG_VERBOSE); | |||||
} | |||||
///////////////////////////////////////////////////////// | |||||
// GET/SET methods. | |||||
// Setters, of course are where ant user passes in values. | |||||
///////////////////////////////////////////////////////// | |||||
/** | |||||
* Set the name of StarTeamServer; | |||||
* required if <tt>URL</tt> is not set. | |||||
* @param servername a <code>String</code> value | |||||
* @see #setURL(String) | |||||
*/ | |||||
public final void setServername(String servername) { | |||||
this.servername = servername; | |||||
} | |||||
/** | |||||
* returns the name of the StarTeamServer | |||||
* | |||||
* @return the name of the StarTeam server | |||||
* @see #getURL() | |||||
*/ | |||||
public final String getServername() { | |||||
return this.servername; | |||||
} | |||||
/** | |||||
* set the port number of the StarTeam connection; | |||||
* required if <tt>URL</tt> is not set. | |||||
* @param serverport port number to be set | |||||
* @see #setURL(String) | |||||
*/ | |||||
public final void setServerport(String serverport) { | |||||
this.serverport = serverport; | |||||
} | |||||
/** | |||||
* returns the port number of the StarTeam connection | |||||
* | |||||
* @return the port number of the StarTeam connection | |||||
* @see #getURL() | |||||
*/ | |||||
public final String getServerport() { | |||||
return this.serverport; | |||||
} | |||||
/** | |||||
* set the name of the StarTeam project to be acted on; | |||||
* required if <tt>URL</tt> is not set. | |||||
* | |||||
* @param projectname the name of the StarTeam project to be acted on | |||||
* @see #setURL(String) | |||||
*/ | |||||
public final void setProjectname(String projectname) { | |||||
this.projectname = projectname; | |||||
} | |||||
/** | |||||
* returns the name of the StarTeam project to be acted on | |||||
* | |||||
* @return the name of the StarTeam project to be acted on | |||||
* @see #getURL() | |||||
*/ | |||||
public final String getProjectname() { | |||||
return this.projectname; | |||||
} | |||||
/** | |||||
* set the name of the StarTeam view to be acted on; | |||||
* required if <tt>URL</tt> is not set. | |||||
* | |||||
* @param viewname the name of the StarTeam view to be acted on | |||||
* @see #setURL(String) | |||||
*/ | |||||
public final void setViewname(String viewname) { | |||||
this.viewname = viewname; | |||||
} | |||||
/** | |||||
* returns the name of the StarTeam view to be acted on | |||||
* | |||||
* @return the name of the StarTeam view to be acted on | |||||
* @see #getURL() | |||||
*/ | |||||
public final String getViewname() { | |||||
return this.viewname; | |||||
} | |||||
/** | |||||
* Set the server name, server port, | |||||
* project name and project folder in one shot; | |||||
* optional, but the server connection must be specified somehow. | |||||
* | |||||
* @param url a <code>String</code> of the form | |||||
* "servername:portnum/project/view" | |||||
* @see #setServername(String) | |||||
* @see #setServerport(String) | |||||
* @see #setProjectname(String) | |||||
* @see #setViewname(String) | |||||
*/ | |||||
public final void setURL(String url) { | |||||
StringTokenizer t = new StringTokenizer(url, "/"); | |||||
if (t.hasMoreTokens()) { | |||||
String unpw = t.nextToken(); | |||||
int pos = unpw.indexOf(":"); | |||||
if (pos > 0) { | |||||
this.servername = unpw.substring(0, pos); | |||||
this.serverport = unpw.substring(pos + 1); | |||||
if (t.hasMoreTokens()) { | |||||
this.projectname = t.nextToken(); | |||||
if (t.hasMoreTokens()) { | |||||
this.viewname = t.nextToken(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* convenience method returns whole URL at once | |||||
* returns | |||||
* as a single string | |||||
*/ | |||||
/** | |||||
* a convenience method which returns the whole StarTeam | |||||
* connection information as a single URL string of | |||||
* | |||||
* @return a <code>String</code> of the form | |||||
* "servername:portnum/project/view" | |||||
* @see #getServername() | |||||
* @see #getServerport() | |||||
* @see #getProjectname() | |||||
* @see #getViewname() | |||||
*/ | |||||
public final String getURL() { | |||||
return this.servername + ":" | |||||
+ this.serverport + "/" | |||||
+ this.projectname + "/" | |||||
+ ((null == this.viewname) ? "" : this.viewname); | |||||
} | |||||
/** | |||||
* returns an URL string useful for interacting with many StarTeamFinder | |||||
* methods. | |||||
* | |||||
* @return the URL string for this task. | |||||
*/ | |||||
protected final String getViewURL() { | |||||
return getUserName() + ":" + getPassword() + "@" + getURL(); | |||||
} | |||||
/** | |||||
* set the name of the StarTeam user, needed for the connection | |||||
* | |||||
* @param userName name of the user to be logged in | |||||
*/ | |||||
public final void setUserName(String userName) { | |||||
this.userName = userName; | |||||
} | |||||
/** | |||||
* returns the name of the StarTeam user | |||||
* | |||||
* @return the name of the StarTeam user | |||||
*/ | |||||
public final String getUserName() { | |||||
return this.userName; | |||||
} | |||||
/** | |||||
* set the password to be used for login; required. | |||||
* | |||||
* @param password the password to be used for login | |||||
*/ | |||||
public final void setPassword(String password) { | |||||
this.password = password; | |||||
} | |||||
/** | |||||
* returns the password used for login | |||||
* | |||||
* @return the password used for login | |||||
*/ | |||||
public final String getPassword() { | |||||
return this.password; | |||||
} | |||||
/** | |||||
* returns a reference to the server which may be used for informational | |||||
* purposes by subclasses. | |||||
* | |||||
* @return a reference to the server | |||||
*/ | |||||
protected final Server getServer() { | |||||
return this.server; | |||||
} | |||||
/** | |||||
* disconnects from the StarTeam server. Should be called from the | |||||
* finally clause of every StarTeamTask-based execute method. | |||||
*/ | |||||
protected final void disconnectFromServer() { | |||||
if (null != this.server) { | |||||
this.server.disconnect(); | |||||
log("successful disconnect from StarTeam Server " + servername, | |||||
Project.MSG_VERBOSE); | |||||
} | |||||
} | |||||
/** | |||||
* returns a list of TypeNames known to the server. | |||||
* | |||||
* @return a reference to the server's TypeNames | |||||
*/ | |||||
protected final TypeNames getTypeNames() { | |||||
return this.server.getTypeNames(); | |||||
} | |||||
/** | |||||
* Derived classes must override <code>createSnapshotView</code> | |||||
* defining the kind of configured view appropriate to its task. | |||||
* | |||||
* @param rawview the unconfigured <code>View</code> | |||||
* @return the snapshot <code>View</code> appropriately configured. | |||||
* @throws BuildException on error | |||||
*/ | |||||
protected abstract View createSnapshotView(View rawview) | |||||
throws BuildException; | |||||
/** | |||||
* All subclasses will call on this method to open the view needed for | |||||
* processing. This method also saves a reference to the | |||||
* <code>Server</code> that may be accessed for information at various | |||||
* points in the process. | |||||
* | |||||
* @return the <code>View</code> that will be used for processing. | |||||
* @see #createSnapshotView(View) | |||||
* @see #getServer() | |||||
* @throws BuildException on error | |||||
*/ | |||||
protected View openView() throws BuildException { | |||||
logStarteamVersion(); | |||||
View view = null; | |||||
try { | |||||
view = StarTeamFinder.openView(getViewURL()); | |||||
} catch (Exception e) { | |||||
throw new BuildException( | |||||
"Failed to connect to " + getURL(), e); | |||||
} | |||||
if (null == view) { | |||||
throw new BuildException("Cannot find view" + getURL() | |||||
+ " in repository()"); | |||||
} | |||||
View snapshot = createSnapshotView(view); | |||||
log("Connected to StarTeam view " + getURL(), | |||||
Project.MSG_VERBOSE); | |||||
this.server = snapshot.getServer(); | |||||
return snapshot; | |||||
} | |||||
/** | |||||
* Returns the name of the user with the supplied ID or a blank string | |||||
* if user not found. | |||||
* | |||||
* @param userID a user's ID | |||||
* @return the name of the user with ID userID | |||||
*/ | |||||
protected final String getUserName(int userID) { | |||||
User u = this.server.getUser(userID); | |||||
if (null == u) { | |||||
return ""; | |||||
} | |||||
return u.getName(); | |||||
} | |||||
} |
@@ -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(); | |||||
} | |||||
} |