From dc7444ae578ffecc195c4f19a2afbd086532c849 Mon Sep 17 00:00:00 2001 From: Conor MacNeill Date: Mon, 21 Aug 2000 15:05:55 +0000 Subject: [PATCH] StarTeam checkout task Submitted by: Chris Povirk git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267936 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 2 + .../tools/ant/taskdefs/defaults.properties | 1 + .../optional/scm/AntStarTeamCheckOut.java | 1404 +++++++++++++++++ 3 files changed, 1407 insertions(+) create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java diff --git a/build.xml b/build.xml index 3ea136cc5..b042d1e08 100644 --- a/build.xml +++ b/build.xml @@ -51,6 +51,7 @@ + @@ -85,6 +86,7 @@ + diff --git a/src/main/org/apache/tools/ant/taskdefs/defaults.properties b/src/main/org/apache/tools/ant/taskdefs/defaults.properties index 5b1dd8129..d5817998d 100644 --- a/src/main/org/apache/tools/ant/taskdefs/defaults.properties +++ b/src/main/org/apache/tools/ant/taskdefs/defaults.properties @@ -57,6 +57,7 @@ cab=org.apache.tools.ant.taskdefs.optional.Cab ftp=org.apache.tools.ant.taskdefs.optional.FTP javacc=org.apache.tools.ant.taskdefs.optional.javacc.JavaCC jjtree=org.apache.tools.ant.taskdefs.optional.javacc.JJTree +starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut # deprecated ant tasks (kept for back compatibility) javadoc2=org.apache.tools.ant.taskdefs.Javadoc diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java b/src/main/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java new file mode 100644 index 000000000..9fe068d72 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java @@ -0,0 +1,1404 @@ +/* ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.tools.ant.taskdefs.optional.scm; + +import org.apache.tools.ant.*; +import java.io.*; +import java.util.*; +import com.starbase.starteam.*; +import com.starbase.util.Platform; + +/** + * Checks out files from a specific StarTeam server, project, view, and + * folder. + *

+ * This program logs in to a StarTeam server and opens up the specified + * project and view. Then, it searches through that view for the given + * folder (or, if you prefer, it uses the root folder). Beginning with + * that folder and optionally continuing recursivesly, AntStarTeamCheckOut + * compares each file with your include and exclude filters and checks it + * out only if appropriate. + *

+ * Checked out files go to a directory you specify under the subfolder + * named for the default StarTeam path to the view. That is, if you + * entered /home/cpovirk/work as the target folder, your project was named + * "OurProject," the given view was named "TestView," and that view is + * stored by default at "C:\projects\Test," your files would be checked + * out to /home/cpovirk/work/Test." I avoided using the project name in + * the path because you may want to keep several versions of the same + * project on your computer, and I didn't want to use the view name, as + * there may be many "Test" or "Version 1.0" views, for example. This + * system's success, of course, depends on what you set the default path + * to in StarTeam. + *

+ * You can set AntStarTeamCheckOut to verbose or quiet mode. Also, it has + * a safeguard against overwriting the files on your computer: If the + * target directory you specify already exists, the program will throw a + * BuildException. To override the exception, set force to + * true. + *

+ * This program makes use of functions from the StarTeam API. As a result + * AntStarTeamCheckOut is available only to licensed users of StarTeam and + * requires the StarTeam SDK to function. You must have + * starteam-sdk.jar in your classpath to run this program. + * For more information about the StarTeam API and how to license it, see + * the link below. + * + * @author Chris Povirk + * @author JC Mann + * @author Jeff Gettle + * @version 1.0 + * @see StarBase Web Site + */ +public class AntStarTeamCheckOut extends org.apache.tools.ant.Task +{ + + /** + * By default, force is set to "false" through this field. + * If you set force to "true," AntStarTeamCheckOut will + * overwrite files in the target directory. If the target directory does + * not exist, the force setting does nothing. Note that + * DEFAULT_FORCESETTING and force are strings, + * not boolean values. See the links below for more information. + * + * @see #getForce() + * @see #getForceAsBoolean() + * @see #setForce(String force) + */ + static public final String DEFAULT_FORCESETTING = "false"; + + /** + * This field is used in setting verbose to "false", the + * default. If verbose is true, AntStarTeamCheckOut will + * display file and directory names as it checks files out. The default + * setting displays only a total. Note that + * DEFAULT_VERBOSESETTING and verbose are + * strings, not boolean values. See the links below for more + * information. + * + * @see #getVerbose() + * @see #getVerboseAsBoolean() + * @see #setVerbose(String verbose) + */ + static public final String DEFAULT_VERBOSESETTING = "false"; + + /** + * DEFAULT_RECURSIONSETTING contains the normal setting -- + * true -- for recursion. Thus, if you do not + * setRecursion("false") somewhere in your program, + * AntStarTeamCheckOut will check files out from all subfolders as well + * as from the given folder. + * + * @see #getRecursion() + * @see #setRecursion(String recursion) + */ + static public final String DEFAULT_RECURSIONSETTING = "true"; + + /** + * This constant sets the filter to include all files. This default has + * the same result as setIncludes("*"). + * + * @see #getIncludes() + * @see #setIncludes(String includes) + */ + static public final String DEFAULT_INCLUDESETTING = "*"; + + /** + * This disables the exclude filter by default. In other words, no files + * are excluded. This setting is equivalent to + * setExcludes(null). + * + * @see #getExcludes() + * @see #setExcludes(String excludes) + */ + static public final String DEFAULT_EXCLUDESETTING = null; + + /** + * The default folder to search; the root folder. Since + * AntStarTeamCheckOut searches subfolders, by default it processes an + * entire view. + * + * @see #getFolderName() + * @see #setFolderName(String folderName) + */ + static public final String DEFAULT_FOLDERSETTING = null; + + + /** + * This is used when formatting the output. The directory name is + * displayed only when it changes. + */ + private Folder prevFolder = null; + + /** + * This field keeps count of the number of files checked out. + */ + private int checkedOut; + + // Change these through their GET and SET methods. + + /** + * The name of the server you wish to connect to. + */ + private String serverName = null; + + /** + * The port on the server used for StarTeam. + */ + private String serverPort = null; + + /** + * The name of your project. + */ + private String projectName = null; + + /** + * The name of the folder you want to check out files from. All + * subfolders will be searched, as well. + */ + private String folderName = DEFAULT_FOLDERSETTING; + + /** + * The view that the files you want are in. + */ + private String viewName = null; + + /** + * Your username on the StarTeam server. + */ + private String username = null; + + /** + * Your StarTeam password. + */ + private String password = null; + + /** + * The path to the root folder you want to check out to. This is a local + * directory. + */ + private String targetFolder = null; + + /** + * If force set to true, AntStarTeamCheckOut will overwrite files in the + * target directory. + */ + private String force = DEFAULT_FORCESETTING; + + /** + * When verbose is true, the program will display all files and + * directories as they are checked out. + */ + private String verbose = DEFAULT_VERBOSESETTING; + + /** + * Set recursion to false to check out files in only the given folder + * and not in its subfolders. + */ + private String recursion = DEFAULT_RECURSIONSETTING; + + // These fields deal with includes and excludes + + /** + * 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; + + /** + * The file delimitor on the user's system. + */ + private String delim = Platform.getFilePathDelim(); + + /** + * Do the execution. + * + * @exception BuildException + */ + public void execute() throws BuildException + { + + // Check all of the properties that are required. + if ( getServerName() == null ) + { + project.log("ServerName must not be null."); + return; + } + if ( getServerPort() == null ) + { + project.log("ServerPort must not be null."); + return; + } + if ( getProjectName() == null ) + { + project.log("ProjectName must not be null."); + return; + } + if ( getViewName() == null ) + { + project.log("ViewName must not be null."); + return; + } + if ( getUsername() == null ) + { + project.log("Username must not be null."); + return; + } + if ( getPassword() == null ) + { + project.log("Password must not be null."); + return; + } + if ( getTargetFolder() == null ) + { + project.log("TargetFolder must not be null."); + return; + } + + // Because of the way I create the full target path, there must be NO slash at the end of targetFolder and folderName + // However, if the slash or backslash is the only character, leave it alone + if (!(getTargetFolder()==null)) + { + if ((getTargetFolder().endsWith("/") || getTargetFolder().endsWith("\\")) && getTargetFolder().length() > 1) + { + setTargetFolder(getTargetFolder().substring(0, getTargetFolder().length() - 1)); + } + } + + if (!(getFolderName()==null)) + { + if ((getFolderName().endsWith("/") || getFolderName().endsWith("\\")) && getFolderName().length() > 1) + { + setFolderName(getFolderName().substring(0, getFolderName().length() - 1)); + } + } + + // Check to see if the target directory exists. + java.io.File dirExist = new java.io.File(getTargetFolder()); + if (dirExist.isDirectory() && !getForceAsBoolean()) + { + project.log("Target directory exists. Set \"force\" to \"true\" to continue anyway."); + return; + } + + try + { + // Connect to the StarTeam server, and log on. + Server s = getServer(); + + // Search the items on this server. + runServer(s); + + // Disconnect from the server. + s.disconnect(); + + // after you are all of the properties are ok, do your thing + // with StarTeam. If there are any kind of exceptions then + // send the message to the project log. + + // Tell how many files were checked out. + project.log(checkedOut + " files checked out."); + } + catch (Throwable e) + { + project.log(" " + e.getMessage()); + } + } + + /** + * Creates and logs in to a StarTeam server. + * + * @return A StarTeam server. + */ + protected Server getServer() + { + // Simplest constructor, uses default encryption algorithm and compression level. + Server s = new Server(getServerName(), getServerPortAsInt()); + + // Optional; logOn() connects if necessary. + s.connect(); + + // Logon using specified user name and password. + s.logOn(getUsername(), getPassword()); + + return s; + } + + /** + * Searches for the specified project on the server. + * + * @param s A StarTeam server. + */ + protected void runServer(Server s) + { + + com.starbase.starteam.Project[] projects = s.getProjects(); + for (int i = 0; i < projects.length; i++) + { + com.starbase.starteam.Project p = projects[i]; + + if (p.getName().equals(getProjectName())) + { + if (getVerboseAsBoolean()) + { + project.log("Found " + getProjectName() + delim); + } + runProject(s, p); + break; + } + } + } + + /** + * Searches for the given view in the project. + * + * @param s A StarTeam server. + * @param p A valid project on the given server. + */ + protected void runProject(Server s, com.starbase.starteam.Project p) + { + View[] views = p.getViews(); + for (int i = 0; i < views.length; i++) + { + View v = views[i]; + if (v.getName().equals(getViewName())) + { + if (getVerboseAsBoolean()) + { + project.log("Found " + getProjectName() + delim + getViewName() + delim); + } + runType(s, p, v, s.typeForName((String)s.getTypeNames().FILE)); + break; + } + } + } + + /** + * Searches for folders in the given view. + * + * @param s A StarTeam server. + * @param p A valid project on the server. + * @param v A view name from the specified project. + * @param t An item type which is currently always "file". + */ + protected void runType(Server s, com.starbase.starteam.Project p, View v, Type t) + { + + // This is ugly; checking for the root folder. + Folder f = v.getRootFolder(); + if (!(getFolderName()==null)) + { + if (getFolderName().equals("\\") || getFolderName().equals("/")) + { + setFolderName(null); + } + else + { + f = StarTeamFinder.findFolder(v.getRootFolder(), getFolderName()); + } + } + + if (getVerboseAsBoolean() && !(getFolderName()==null)) + { + project.log("Found " + getProjectName() + delim + getViewName() + delim + getFolderName() + delim + "\n"); + } + + // For performance reasons, it is important to pre-fetch all the + // properties we'll need for all the items we'll be searching. + + // We always display the ItemID (OBJECT_ID) and primary descriptor. + int nProperties = 2; + + // We'll need this item type's primary descriptor. + Property p1 = getPrimaryDescriptor(t); + + // Does this item type have a secondary descriptor? + // If so, we'll need it. + Property p2 = getSecondaryDescriptor(t); + if (p2 != null) + { + nProperties++; + } + + // Now, build an array of the property names. + String[] strNames = new String[nProperties]; + int iProperty = 0; + strNames[iProperty++] = s.getPropertyNames().OBJECT_ID; + strNames[iProperty++] = p1.getName(); + if (p2 != null) + { + strNames[iProperty++] = p2.getName(); + } + + // Pre-fetch the item properties and cache them. + f.populateNow(t.getName(), strNames, -1); + + // Now, search for items in the selected folder. + runFolder(s, p, v, t, f); + + // Free up the memory used by the cached items. + f.discardItems(t.getName(), -1); + } + + /** + * Searches for files in the given folder. This method is recursive and + * thus searches all subfolders. + * + * @param s A StarTeam server. + * @param p A valid project on the server. + * @param v A view name from the specified project. + * @param t An item type which is currently always "file". + * @param f The folder to search. + */ + protected void runFolder(Server s, com.starbase.starteam.Project p, View v, Type t, Folder f) + { + + // Process all items in this folder. + Item[] items = f.getItems(t.getName()); + for (int i = 0; i < items.length; i++) + { + runItem(s, p, v, t, f, items[i]); + } + + // Process all subfolders recursively if recursion is on. + if (getRecursionAsBoolean()) + { + Folder[] subfolders = f.getSubFolders(); + for (int i = 0; i < subfolders.length; i++) + { + runFolder(s, p, v, t, subfolders[i]); + } + } + } + + /** + * Check out one file if it matches the include filter but not the + * exclude filter. + * + * @param s A StarTeam server. + * @param p A valid project on the server. + * @param v A view name from the specified project. + * @param t An item type which is currently always "file". + * @param f The folder the file is localed in. + * @param item The file to check out. + */ + protected void runItem(Server s, com.starbase.starteam.Project p, View v, Type t, Folder f, Item item) + { + + // Get descriptors for this item type. + Property p1 = getPrimaryDescriptor(t); + Property p2 = getSecondaryDescriptor(t); + + // Time to filter... + String pName = (String)item.get(p1.getName()); + boolean includeIt = false; + boolean excludeIt = false; + + // See if it fits any includes. + if (getIncludes()!=null) + { + StringTokenizer inStr = new StringTokenizer(getIncludes(), " "); + while (inStr.hasMoreTokens()) + { + if (match(inStr.nextToken(), pName)) + { + includeIt = true; + } + } + } + + // See if it fits any excludes. + if (getExcludes()!=null) + { + StringTokenizer exStr = new StringTokenizer(getExcludes(), " "); + while (exStr.hasMoreTokens()) + { + if (match(exStr.nextToken(), pName)) + { + excludeIt = true; + } + } + } + + // Don't check it out if + // (a) It fits no include filters + // (b) It fits an exclude filter + if (!includeIt | excludeIt) + { + return; + } + + // VERBOSE MODE ONLY + if (getVerboseAsBoolean()) + { + // Show folder only if changed. + boolean bShowHeader = true; + if (f != prevFolder) + { + // We want to display the folder the same way you would + // enter it on the command line ... so we remove the + // View name (which is also the name of the root folder, + // and therefore shows up at the start of the path). + String strFolder = f.getFolderHierarchy(); + int i = strFolder.indexOf(delim); + if (i >= 0) + { + strFolder = strFolder.substring(i+1); + } + System.out.println(" Folder: \"" + strFolder + "\""); + prevFolder = f; + } + else + bShowHeader = false; + + // If we displayed the project, view, item type, or folder, + // then show the list of relevant item properties. + if (bShowHeader) + { + System.out.print(" Item"); + System.out.print(",\t" + p1.getDisplayName()); + if (p2 != null) + { + System.out.print(",\t" + p2.getDisplayName()); + } + System.out.println(""); + } + + // Finally, show the Item properties ... + + // Always show the ItemID. + System.out.print(" " + item.getItemID()); + + // Show the primary descriptor. + // There should always be one. + System.out.print(",\t" + formatForDisplay(p1, item.get(p1.getName()))); + + // Show the secondary descriptor, if there is one. + // Some item types have one, some don't. + if (p2 != null) + { + System.out.print(",\t" + formatForDisplay(p2, item.get(p2.getName()))); + } + + // Show if the file is locked. + int locker = item.getLocker(); + if (locker>-1) + { + System.out.println(",\tLocked by " + locker); + } + else + { + System.out.println(",\tNot locked"); + } + } + // END VERBOSE ONLY + + // Check it out; also ugly. + + // Change the item to be checked out to a StarTeam File. + com.starbase.starteam.File remote = (com.starbase.starteam.File)item; + + // Create a variable dirName that contains the name of the StarTeam folder that is the root folder in this view. + // Get the default path to the current view. + String dirName = v.getDefaultPath(); + // Settle on "/" as the default path separator for this purpose only. + dirName = dirName.replace('\\', '/'); + // Take the StarTeam folder name furthest down in the hierarchy. + dirName = dirName.substring(dirName.lastIndexOf("/", dirName.length() - 2) + 1, dirName.length() - 1); + + // Replace the projectName in the file's absolute path to the viewName. + // This eventually makes the target of a checkout operation equal to: + // targetFolder + dirName + [subfolders] + itemName + StringTokenizer pathTokenizer = new StringTokenizer(item.getParentFolder().getFolderHierarchy(), delim); + String localName = delim; + String currentToken = null; + while (pathTokenizer.hasMoreTokens()) + { + currentToken = pathTokenizer.nextToken(); + if (currentToken.equals(getProjectName())) + { + currentToken = dirName; + } + localName += currentToken + delim; + } + // Create a reference to the local target file using the format listed above. + java.io.File local = new java.io.File(getTargetFolder() + localName + item.get(p1.getName())); + try + { + remote.checkoutTo(local, Item.LockType.UNCHANGED, false, true, true); + } + catch (Throwable e) + { + project.log(" " + e.getMessage()); + } + checkedOut++; + } + + /** + * Get the primary descriptor of the given item type. + * Returns null if there isn't one. + * In practice, all item types have a primary descriptor. + * + * @param t An item type. At this point it will always be "file". + * @return The specified item's primary descriptor. + */ + protected Property getPrimaryDescriptor(Type t) + { + Property[] properties = t.getProperties(); + for (int i = 0; i < properties.length; i++) + { + Property p = properties[i]; + if (p.isPrimaryDescriptor()) + { + return p; + } + } + return null; + } + + /** + * Get the secondary descriptor of the given item type. + * Returns null if there isn't one. + * + * @param t An item type. At this point it will always be "file". + * @return The specified item's secondary descriptor. There may not be + * one for every file. + */ + protected Property getSecondaryDescriptor(Type t) + { + Property[] properties = t.getProperties(); + for (int i = 0; i < properties.length; i++) + { + Property p = properties[i]; + if (p.isDescriptor() && !p.isPrimaryDescriptor()) + { + return p; + } + } + return null; + } + + /** + * Formats a property value for display to the user. + * + * @param p An item property to format. + * @param value + * @return A string containing the property, which is truncated to 35 + * characters for display. + */ + protected String formatForDisplay(Property p, Object value) + { + if (p.getTypeCode() == Property.Types.TEXT) + { + String str = value.toString(); + if (str.length() > 35) + { + str = str.substring(0, 32) + "..."; + } + return "\"" + str + "\""; + } + else + { + if (p.getTypeCode() == Property.Types.ENUMERATED) + { + return "\"" + p.getEnumDisplayName(((Integer)value).intValue()) + "\""; + } + else + { + return value.toString(); + } + } + } + + // TORN STRAIGHT FROM ANT.DIRECTORYSCANNER + + /** + * TORN STRAIGHT FROM ANT.DIRECTORYSCANNER + * + * Matches a string against a pattern. The pattern contains two special + * characters:
+ * '*' which means zero or more characters,
+ * '?' which means one and only one character. + * + * @param pattern the (non-null) pattern to match against + * @param str the (non-null) string that must be matched against the + * pattern + * @return true when the string matches against the + * pattern, false otherwise. + */ + private static boolean match(String pattern, String str) + { + char[] patArr = pattern.toCharArray(); + char[] strArr = str.toCharArray(); + int patIdxStart = 0; + int patIdxEnd = patArr.length-1; + int strIdxStart = 0; + int strIdxEnd = strArr.length-1; + char ch; + + boolean containsStar = false; + for (int i = 0; i < patArr.length; i++) + { + if (patArr[i] == '*') + { + containsStar = true; + break; + } + } + + if (!containsStar) + { + // No '*'s, so we make a shortcut + if (patIdxEnd != strIdxEnd) + { + return false; // Pattern and string do not have the same size + } + for (int i = 0; i <= patIdxEnd; i++) + { + ch = patArr[i]; + if (ch != '?' && ch != strArr[i]) + { + return false; // Character mismatch + } + } + return true; // String matches against pattern + } + + if (patIdxEnd == 0) + { + return true; // Pattern contains only '*', which matches anything + } + + // Process characters before first star + while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) + { + if (ch != '?' && ch != strArr[strIdxStart]) + { + return false; + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) + { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) + { + if (patArr[i] != '*') + { + return false; + } + } + return true; + } + + // Process characters after last star + while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) + { + if (ch != '?' && ch != strArr[strIdxEnd]) + { + return false; + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) + { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) + { + if (patArr[i] != '*') + { + return false; + } + } + return true; + } + + // process pattern between stars. padIdxStart and patIdxEnd point + // always to a '*'. + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) + { + int patIdxTmp = -1; + for (int i = patIdxStart+1; i <= patIdxEnd; i++) + { + if (patArr[i] == '*') + { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart+1) + { + // Two stars next to each other, skip the first one. + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp-patIdxStart-1); + int strLength = (strIdxEnd-strIdxStart+1); + int foundIdx = -1; + strLoop: + for (int i = 0; i <= strLength - patLength; i++) + { + for (int j = 0; j < patLength; j++) + { + ch = patArr[patIdxStart+j+1]; + if (ch != '?' && ch != strArr[strIdxStart+i+j]) + { + continue strLoop; + } + } + + foundIdx = strIdxStart+i; + break; + } + + if (foundIdx == -1) + { + return false; + } + + patIdxStart = patIdxTmp; + strIdxStart = foundIdx+patLength; + } + + // All characters in the string are used. Check if only '*'s are left + // in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) + { + if (patArr[i] != '*') + { + return false; + } + } + return true; + } + + // Begin SET and GET methods + + /** + * Sets the serverName attribute to the given value. + * + * @param serverName The name of the server you wish to connect to. + * @see #getServerName() + */ + public void setServerName(String serverName) + { + this.serverName = serverName; + } + + /** + * Gets the serverName attribute. + * + * @return The StarTeam server to log in to. + * @see #setServerName(String serverName) + */ + public String getServerName() + { + return serverName; + } + + /** + * Sets the serverPort attribute to the given value. The + * given value must be a valid integer, but it must be a string object. + * + * @param serverPort A string containing the port on the StarTeam server + * to use. + * @see #getServerPort() + */ + public void setServerPort(String serverPort) + { + this.serverPort = serverPort; + } + + /** + * Gets the serverPort attribute. + * + * @return A string containing the port on the StarTeam server to use. + * @see #getServerPortAsInt() + * @see #setServerPort(String serverPort) + */ + public String getServerPort() + { + return serverPort; + } + + /** + * Gets the serverPort attribute as an integer. + * + * @return An integer value for the port on the StarTeam server to use. + * @see #getServerPort() + * @see #setServerPort(String serverPort) + */ + public int getServerPortAsInt() + { + return Integer.parseInt(serverPort); + } + + /** + * Sets the projectName attribute to the given value. + * + * @param projectName + * The StarTeam project to search. + * @see #getProjectName() + */ + public void setProjectName(String projectName) + { + this.projectName = projectName; + } + + /** + * Gets the projectName attribute. + * + * @return The StarTeam project to search. + * @see #setProjectName(String projectName) + */ + public String getProjectName() + { + return projectName; + } + + /** + * Sets the viewName attribute to the given value. + * + * @param viewName The view to find the specified folder in. + * @see #getViewName() + */ + public void setViewName(String viewName) + { + this.viewName = viewName; + } + + /** + * Gets the viewName attribute. + * + * @return The view to find the specified folder in. + * @see #setViewName(String viewName) + */ + public String getViewName() + { + return viewName; + } + + /** + * Sets the folderName attribute to the given value. To + * search the root folder, use a slash or backslash, or simply don't set + * a folder at all. + * + * @param folderName The subfolder from which to check out files. + * @see #getFolderName() + */ + public void setFolderName(String folderName) + { + this.folderName = folderName; + } + + /** + * Gets the folderName attribute. + * + * @return The subfolder from which to check out files. All subfolders + * will be searched, as well. + * @see #setFolderName(String folderName) + */ + public String getFolderName() + { + return folderName; + } + + /** + * Sets the username attribute to the given value. + * + * @param username Your username for the specified StarTeam server. + * @see #getUsername() + */ + public void setUsername(String username) + { + this.username = username; + } + + /** + * Gets the username attribute. + * + * @return The username given by the user. + * @see #setUsername(String username) + */ + public String getUsername() + { + return username; + } + + /** + * Sets the password attribute to the given value. + * + * @param password Your password for the specified StarTeam server. + * @see #getPassword() + */ + public void setPassword(String password) + { + this.password = password; + } + + /** + * Gets the password attribute. + * + * @return The password given by the user. + * @see #setPassword(String password) + */ + public String getPassword() + { + return password; + } + + /** + * Sets the targetFolder attribute to the given value. + * + * @param target The target path on the local machine to check out to. + * @see #getTargetFolder() + */ + public void setTargetFolder(String targetFolder) + { + this.targetFolder = targetFolder; + } + + /** + * Gets the targetFolder attribute. + * + * @return The target path on the local machine to check out to. + * + * @see #setTargetFolder(String targetFolder) + */ + public String getTargetFolder() + { + return targetFolder; + } + + /** + * Sets the force attribute to the given value. + * + * @param force A string containing "true" or "false" that tells the + * application whether to continue if the target directory + * exists. If force is true, + * AntStarTeamCheckOut will overwrite files in the target + * directory. By default it set to false as a safeguard. + * Note that if the target directory does not exist, this + * setting has no effect. + * @see #DEFAULT_FORCESETTING + * @see #getForce() + * @see #getForceAsBoolean() + */ + public void setForce(String force) + { + this.force = force; + } + + /** + * Gets the force attribute. + * + * @return A string containing "true" or "false" telling the application + * whether to continue if the target directory exists. If + * force is true, AntStarTeamCheckOut will + * overwrite files in the target directory. If it is false and + * the target directory exists, AntStarTeamCheckOut will exit + * with a warning. If the target directory does not exist, this + * setting has no effect. The default setting is false. + * @see #DEFAULT_FORCESETTING + * @see #getForceAsBoolean() + * @see #setForce(String force) + */ + public String getForce() + { + return force; + } + + /** + * Gets the force attribute as a boolean value. + * + * @return A boolean value telling whether to continue if the target + * directory exists. + * @see #DEFAULT_FORCESETTING + * @see #getForce() + * @see #setForce(String force) + */ + public boolean getForceAsBoolean() + { + return project.toBoolean(force); + } + + /** + * Turns recursion on or off. + * + * @param verbose A string containing "true" or "false." If it is true, + * the default, subfolders are searched recursively for + * files to check out. Otherwise, only files specified + * by folderName are scanned. + * @see #DEFAULT_RECURSIONSETTING + * @see #getRecursion() + * @see #getRecursionAsBoolean() + */ + public void setRecursion(String recursion) + { + this.recursion = recursion; + } + + /** + * Gets the recursion attribute, which tells + * AntStarTeamCheckOut whether to search subfolders when checking out + * files. + * + * @return A string telling whether recursion is "true" or + * "false." + * + * @see #DEFAULT_RECURSIONSETTING + * @see #getRecursionAsBoolean() + * @see #setRecursion(String recursion) + */ + public String getRecursion() + { + return recursion; + } + + /** + * Gets the recursion attribute as a boolean value. + * + * @return A boolean value telling whether subfolders of + * folderName will be scanned for files to check out. + * + * @see #DEFAULT_RECURSIONSETTING + * @see #getRecursion() + * @see #setRecursion(String recursion) + */ + public boolean getRecursionAsBoolean() + { + return project.toBoolean(recursion); + } + + /** + * Sets the verbose attribute to the given value. + * + * @param verbose A string containing "true" or "false" to tell + * AntStarTeamCheckOut whether to display files as they + * are checked out. By default it is false, so the + * program only displays the total number of files unless + * you override this default. + * @see #DEFAULT_FORCESETTING + * @see #getForce() + * @see #getForceAsBoolean() + */ + public void setVerbose(String verbose) + { + this.verbose = verbose; + } + + /** + * Gets the verbose attribute. + * + * @return A string containing "true" or "false" telling the application + * to display all files as it checks them out. By default it is + * false, so the program only displays the total number of + * files. + * @see #DEFAULT_VERBOSESETTING + * @see #getVerboseAsBoolean() + * @see #setVerbose(String verbose) + */ + public String getVerbose() + { + return verbose; + } + + /** + * Gets the verbose attribute as a boolean value. + * + * @return A boolean value telling whether to display all files as they + * are checked out. + * @see #DEFAULT_VERBOSESETTING + * @see #getVerbose() + * @see #setVerbose(String verbose) + */ + public boolean getVerboseAsBoolean() + { + return project.toBoolean(verbose); + } + + // Begin filter getters and setters + + /** + * Sets the include filter. When filtering files, AntStarTeamCheckOut + * uses an unmodified version of DirectoryScanner's + * match method, so here are the patterns straight from the + * Ant source code: + *

+ * Matches a string against a pattern. The pattern contains two special + * characters: + *
'*' which means zero or more characters, + *
'?' which means one and only one character. + *

+ * I would have used the Ant method directly from its class, but + * match is a private member, so I cannot access it from + * this program. + *

+ * Separate multiple inlcude filters by spaces, not commas as Ant + * uses. For example, if you want to check out all .java and .class\ + * files, you would put the following line in your program: + * setIncludes("*.java *.class"); + * Finally, note that filters have no effect on the directories + * that are scanned; you could not check out files from directories with + * names beginning only with "build," for instance. Of course, you + * could limit AntStarTeamCheckOut to a particular folder and its + * subfolders with the setFolderName(String folderName) + * command. + *

+ * 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. + *

+ * Please also read the following sections before using filters: + * + * @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 AntStarTeanCheckOut'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; + } + + /** + * Sets the exclude filter. When filtering files, AntStarTeamCheckOut + * uses an unmodified version of DirectoryScanner's + * match method, so here are the patterns straight from the + * Ant source code: + *

+ * Matches a string against a pattern. The pattern contains two special + * characters: + *
'*' which means zero or more characters, + *
'?' which means one and only one character. + *

+ * I would have used the Ant method directly from its class, but + * match is a private member, so I cannot access it from + * this program. + *

+ * Separate multiple exlcude filters by spaces, not commas as Ant + * uses. For example, if you want to check out all files except .XML and + * .HTML files, you would put the following line in your program: + * setExcludes("*.XML *.HTML"); + * Finally, note that filters have no effect on the directories + * that are scanned; you could not skip over all files in directories + * whose names begin with "project," for instance. + *

+ * 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. + *

+ * 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; + } + +}