alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Ant example source code file (StarTeamCheckout.java)

This example Ant source code file (StarTeamCheckout.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Ant tags/keywords

buildexception, buildexception, creating, failed, folder, integer, integer, io, item, items, items, string, string, unmatchedfilemap, util, view

The StarTeamCheckout.java source code

/*
 *  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 in StarTeam should be deleted.
     * Optional, defaults to <code>true.
     * @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.
     * @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
     *
     * @return the snapshot <code>View 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>stFilesfiles 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());
        }
    }


}

Other Ant examples (source code examples)

Here is a short list of links related to this Ant StarTeamCheckout.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.