nl.toolforge.karma.core.vc.cvsimpl.CVSModuleStatus.java Source code

Java tutorial

Introduction

Here is the source code for nl.toolforge.karma.core.vc.cvsimpl.CVSModuleStatus.java

Source

/*
Karma core - Core of the Karma application
Copyright (C) 2004  Toolforge <www.toolforge.nl>
    
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
    
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package nl.toolforge.karma.core.vc.cvsimpl;

import nl.toolforge.karma.core.KarmaRuntimeException;
import nl.toolforge.karma.core.Patch;
import nl.toolforge.karma.core.Version;
import nl.toolforge.karma.core.module.Module;
import nl.toolforge.karma.core.vc.DevelopmentLine;
import nl.toolforge.karma.core.vc.ModuleStatus;
import nl.toolforge.karma.core.vc.PatchLine;
import nl.toolforge.karma.core.vc.model.MainLine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.netbeans.lib.cvsclient.admin.Entry;
import org.netbeans.lib.cvsclient.admin.StandardAdminHandler;
import org.netbeans.lib.cvsclient.command.log.LogInformation;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * @author D.A. Smedes
 * @version $Id$
 */
public class CVSModuleStatus implements ModuleStatus {

    private static final Log logger = LogFactory.getLog(Utils.class);

    private boolean existsInRepository = false;

    private List matchingList = null;

    private Module module = null;
    private LogInformation logInfo = null;
    private boolean connectionFailure = false;
    private boolean authenticationFailure = false;
    private boolean internalError = false;

    /**
     * Creates a ModuleStatus instance with the LogInformation object that was generated by the <code>cvs log</code>
     * command.
     *
     * @param module The module.
     * @param logInfo A Netbeans LogInformation object.
     */
    public CVSModuleStatus(Module module, LogInformation logInfo) {
        this.module = module;
        setLogInformation(logInfo);
    }

    public CVSModuleStatus(Module module) {
        this.module = module;
    }

    public void setLogInformation(Object logInfo) {
        this.logInfo = (LogInformation) logInfo;
        matchingList = collectVersions(module);
    }

    /**
     * Returns a Version instance representing the next possible version (major or patch) for the module.
     *
     * @return
     */
    public Version getNextVersion() {

        if (matchingList.size() == 0) {

            // If the module is in a ReleaseManifest and has a PatchLine already, we can savely
            // return the initial patch level for the module.
            //
            // todo hmm (see sourceforge issue 1019628). Not totally convinced. What if the module doesn't have a patchline ?
            // todo there is something to this logic.

            if (module.hasPatchLine()) {
                return module.getVersion().createPatch(Patch.INITIAL_PATCH);
            }

            return null;
        }

        Version nextVersion = null;

        try {
            nextVersion = (Version) ((Version) matchingList.get(matchingList.size() - 1)).clone();
        } catch (CloneNotSupportedException e) {
            throw new KarmaRuntimeException(e.getMessage(), e);
        }

        nextVersion.increase();

        return nextVersion;
    }

    public Version getNextMajorVersion() {
        if (matchingList.size() == 0) {
            return null;
        }

        Version nextVersion = null;

        try {
            nextVersion = (Version) ((Version) matchingList.get(matchingList.size() - 1)).clone();
        } catch (CloneNotSupportedException e) {
            throw new KarmaRuntimeException(e.getMessage(), e);
        }

        nextVersion.increaseMajor();

        return nextVersion;
    }

    /**
     * The latest promoted version of the module in the version control system for the branch.
     *
     * @return
     */
    public Version getLastVersion() {

        if (matchingList.size() == 0) {

            if (module.hasPatchLine()) {
                return module.getVersion();
            } else {
                return null;
            }
        }
        return (Version) matchingList.get(matchingList.size() - 1);
    }

    /**
     * Gets the local version of the module, which is determined by parsing the <code>CVS/Entries</code> file.
     *
     * @return The version of the local checkout or <code>null</code> when the HEAD of the developmentline is local.
     * @throws CVSException
     */
    public Version getLocalVersion() throws CVSException {
        logger.debug("Retrieving local version for module: " + module.getName());
        StandardAdminHandler handler = new StandardAdminHandler();
        Version localVersion = null;

        try {
            Entry[] entries = handler.getEntriesAsArray(module.getBaseDir());

            Entry moduleDescriptor = null;

            int i = 0;
            while (i < entries.length) {
                if (entries[i].getName().equals(Module.MODULE_DESCRIPTOR)) {
                    moduleDescriptor = entries[i];
                    break;
                }
                i++;
            }
            try {

                if (moduleDescriptor == null || moduleDescriptor.getTag() == null
                        || moduleDescriptor.getTag().matches(DevelopmentLine.DEVELOPMENT_LINE_PATTERN_STRING)) {
                    logger.debug("We're on the head. Return null.");
                    // We have the HEAD of a DevelopmentLine.
                    //
                    return null;
                }
                if (moduleDescriptor.getTag().startsWith(PatchLine.NAME_PREFIX)) {
                    localVersion = new Patch(
                            moduleDescriptor.getTag().substring(moduleDescriptor.getTag().indexOf("_") + 1));
                    logger.debug("PatchLine. Return " + localVersion);
                } else {
                    localVersion = new Version(
                            moduleDescriptor.getTag().substring(moduleDescriptor.getTag().indexOf("_") + 1));
                    logger.debug("MainLine. Return " + localVersion);
                }

            } catch (Exception e) {
                throw new CVSException(CVSException.LOCAL_MODULE_ERROR, new Object[] { module.getName() });
            }

        } catch (IOException e) {
            throw new CVSException(CVSException.LOCAL_MODULE_ERROR, new Object[] { module.getName() });
        }
        return localVersion;
    }

    public void setExistsInRepository(boolean exists) {
        existsInRepository = exists;
    }

    public boolean existsInRepository() {
        return existsInRepository;
    }

    private List collectVersions(Module module) {

        if (logInfo == null) {
            return new ArrayList();
        }

        // Step 1 : get all symbolicnames that apply to the correct pattern
        //
        //
        List matchingList = new ArrayList();

        Collection currentVersions = logInfo.getAllSymbolicNames();

        Pattern pattern = null;

        if (module.hasPatchLine()) {

            // We are working on the PatchLine of a module.
            //
            pattern = Pattern.compile(((PatchLine) module.getPatchLine()).getMatchingPattern());
        } else {
            // We are doing MAINLINE development.
            //
            pattern = Pattern.compile(MainLine.NAME_PREFIX.concat("_").concat(Version.VERSION_PATTERN_STRING));
        }

        // Collect all applicable symbolic names.
        //
        for (Iterator it = currentVersions.iterator(); it.hasNext();) {

            String s = ((LogInformation.SymName) it.next()).getName();

            Matcher matcher = pattern.matcher(s);
            if (matcher.matches()) {

                try {
                    if (module.hasPatchLine()) {
                        matchingList.add(new Patch(s.substring(s.lastIndexOf("_") + 1)));
                    } else {
                        matchingList.add(new Version(s.substring(s.lastIndexOf("_") + 1)));
                    }
                } catch (PatternSyntaxException p) {
                    // Ignore, just no match ...
                }
            }
        }

        // Step 2 : Sort them, so the last one is on top.
        //
        Collections.sort(matchingList);

        return matchingList;
    }

    public boolean connectionFailure() {
        return connectionFailure;
    }

    public boolean authenticationFailure() {
        return authenticationFailure;
    }

    public boolean internalError() {
        return internalError;
    }

    /**
     * Sets the indication that a connection failure to the remote CVS repository has occurred.
     */
    public void setConnnectionFailure() {
        connectionFailure = true;
    }

    public void setAuthenticationFailure() {
        authenticationFailure = true;
    }

    public void setInternalError() {
        internalError = true;
    }
}