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(); | |||||
| } | |||||
| } | |||||