I posted a quick description of my AntStarTeamCheckOut task yesterday,
so today I am sending the code (attached) and a very brief usage manual.
Here is my Javadoc description.
> 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.
>
Parameters:
serverName -- the name of the StarTeam server to log in to
serverPort -- the above server's port used for StarTeam
projectName -- the name of the project to open
viewName -- the view in that project to scan
folderName -- the base folder in the view to check out from
username -- your username on the server
password -- your password
targetFolder -- the local directory to check out files to; a
directory named for the project folder will appear under here
force -- boolean value checked when targetFolder exists; if true,
AntStarTeamCheckOut will overwrite files; if false; it will throw a
BuildException
verbose -- if true, filenames are displayed as the files are checked
out; if false, only a total number is displayed at the end
recursion -- tells whether to recursively search subfolders for
files to check out
includes -- filter for files to include; separate multiple filters
by spaces
excludes -- filter for files to exclude; separate multiple filters
by spaces
Example of Usage:
<taskdef name="starTeamCheckOut" classname="AntStarTeamCheckOut" />
<starTeamCheckOut serverName="k6server" serverPort="49201"
projectName="database" viewName="development"
folderName="java" username="jsmith" password="h1536E"
targetFolder="/usr/local/projects" force="true"
verbose="false" recursion="true" includes="*.java *.jsp"
excludes=""
/>
Logs in to the server "k6server" on port 49201 as the user "jsmith"
using the password "h1536E". Checks out all *.java and *.jsp files
underneath the "java" folder in the "development" view of the project
named "database". Display only the total number of files checked out,
and continue even if the target folder already exists.
Three things that could be done with this project:
- Verify that it works on Windows systems (tested only on Linux and
SunOS).
- Build in Ant's more powerful includes and excludes. My program cannot
use directory wildcards like "**/java/*"; it can only handle simple
patterns like "*.class *.jar".
- Rewrite the "force" code. Right now if you checked out two separate
projects to "/usr/local/projects," AntStarTeamCheckOut would think you
were overwriting the first project with the second, for it only looks to
see if the targetFolder exists, not if targetFolder/[project folder]
does.
Remember that you must be a licensed user of StarTeam to use this task.
--Chris Povirk
/* ====================================================================
*
* 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 [EMAIL PROTECTED]
*
* 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
* <http://www.apache.org/>.
*
*/
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.
* <BR><BR>
* 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.
* <BR><BR>
* 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.
* <BR><BR>
* 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 <CODE>force</CODE> to
* true.
* <BR><BR>
* <B>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
* <CODE>starteam-sdk.jar</CODE> in your classpath to run this program.
* For more information about the StarTeam API and how to license it, see
* the link below.</B>
*
* @author <A HREF="mailto:[EMAIL PROTECTED]">Chris Povirk</A>
* @author <A HREF="mailto:[EMAIL PROTECTED]">JC Mann</A>
* @author <A HREF="mailto:[EMAIL PROTECTED]">Jeff Gettle</A>
* @version 1.0
* @see <A HREF="http://www.starbase.com/">StarBase Web Site</A>
*/
public class AntStarTeamCheckOut extends org.apache.tools.ant.Task
{
/**
* By default, <CODE>force</CODE> is set to "false" through this field.
* If you set <CODE>force</CODE> to "true," AntStarTeamCheckOut will
* overwrite files in the target directory. If the target directory does
* not exist, the <CODE>force</CODE> setting does nothing. Note that
* <CODE>DEFAULT_FORCESETTING</CODE> and <CODE>force</CODE> 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 <CODE>verbose</CODE> to "false", the
* default. If <CODE>verbose</CODE> is true, AntStarTeamCheckOut will
* display file and directory names as it checks files out. The default
* setting displays only a total. Note that
* <CODE>DEFAULT_VERBOSESETTING</CODE> and <CODE>verbose</CODE> 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";
/**
* <CODE>DEFAULT_RECURSIONSETTING</CODE> contains the normal setting --
* true -- for recursion. Thus, if you do not
* <CODE>setRecursion("false")</CODE> 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 <CODE>setIncludes("*")</CODE>.
*
* @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
* <CODE>setExcludes(null)</CODE>.
*
* @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
/**
* <B>TORN STRAIGHT FROM ANT.DIRECTORYSCANNER</B>
*
* 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.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the
* pattern
* @return <code>true</code> when the string matches against the
* pattern, <code>false</code> 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 <CODE>serverName</CODE> 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 <CODE>serverName</CODE> attribute.
*
* @return The StarTeam server to log in to.
* @see #setServerName(String serverName)
*/
public String getServerName()
{
return serverName;
}
/**
* Sets the <CODE>serverPort</CODE> 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 <CODE>serverPort</CODE> 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 <CODE>serverPort</CODE> 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 <CODE>projectName</CODE> attribute to the given value.
*
* @param projectName
* The StarTeam project to search.
* @see #getProjectName()
*/
public void setProjectName(String projectName)
{
this.projectName = projectName;
}
/**
* Gets the <CODE>projectName</CODE> attribute.
*
* @return The StarTeam project to search.
* @see #setProjectName(String projectName)
*/
public String getProjectName()
{
return projectName;
}
/**
* Sets the <CODE>viewName</CODE> 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 <CODE>viewName</CODE> attribute.
*
* @return The view to find the specified folder in.
* @see #setViewName(String viewName)
*/
public String getViewName()
{
return viewName;
}
/**
* Sets the <CODE>folderName</CODE> 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 <CODE>folderName</CODE> 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 <CODE>username</CODE> 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 <CODE>username</CODE> attribute.
*
* @return The username given by the user.
* @see #setUsername(String username)
*/
public String getUsername()
{
return username;
}
/**
* Sets the <CODE>password</CODE> 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 <CODE>password</CODE> attribute.
*
* @return The password given by the user.
* @see #setPassword(String password)
*/
public String getPassword()
{
return password;
}
/**
* Sets the <CODE>targetFolder</CODE> 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 <CODE>targetFolder</CODE> attribute.
*
* @return The target path on the local machine to check out to.
*
* @see #setTargetFolder(String targetFolder)
*/
public String getTargetFolder()
{
return targetFolder;
}
/**
* Sets the <CODE>force</CODE> 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 <CODE>force</CODE> 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 <CODE>force</CODE> attribute.
*
* @return A string containing "true" or "false" telling the application
* whether to continue if the target directory exists. If
* <CODE>force</CODE> 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 <CODE>force</CODE> 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 <CODE>folderName</CODE> are scanned.
* @see #DEFAULT_RECURSIONSETTING
* @see #getRecursion()
* @see #getRecursionAsBoolean()
*/
public void setRecursion(String recursion)
{
this.recursion = recursion;
}
/**
* Gets the <CODE>recursion</CODE> attribute, which tells
* AntStarTeamCheckOut whether to search subfolders when checking out
* files.
*
* @return A string telling whether <CODE>recursion</CODE> is "true" or
* "false."
*
* @see #DEFAULT_RECURSIONSETTING
* @see #getRecursionAsBoolean()
* @see #setRecursion(String recursion)
*/
public String getRecursion()
{
return recursion;
}
/**
* Gets the <CODE>recursion</CODE> attribute as a boolean value.
*
* @return A boolean value telling whether subfolders of
* <CODE>folderName</CODE> 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 <CODE>verbose</CODE> 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 <CODE>verbose</CODE> 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 <CODE>verbose</CODE> 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 <CODE>DirectoryScanner</CODE>'s
* <CODE>match</CODE> method, so here are the patterns straight from the
* Ant source code:
* <BR><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><BR>
* I would have used the Ant method directly from its class, but
* <CODE>match</CODE> is a private member, so I cannot access it from
* this program.
* <BR><BR>
* Separate multiple inlcude filters by <I>spaces</I>, 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:
* <CODE>setIncludes("*.java *.class");</CODE>
* Finally, note that filters have no effect on the <B>directories</B>
* 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 <CODE>setFolderName(String folderName)</CODE>
* command.
* <BR><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><BR>
* 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 <CODE>DirectoryScanner</CODE>'s
* <CODE>match</CODE> method, so here are the patterns straight from the
* Ant source code:
* <BR><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><BR>
* I would have used the Ant method directly from its class, but
* <CODE>match</CODE> is a private member, so I cannot access it from
* this program.
* <BR><BR>
* Separate multiple exlcude filters by <I>spaces</I>, 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:
* <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><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><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;
}
}