massbank.svn.SVNClientWrapper.java Source code

Java tutorial

Introduction

Here is the source code for massbank.svn.SVNClientWrapper.java

Source

/*******************************************************************************
 *
 * Copyright (C) 2012 MassBank project
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 *******************************************************************************
 *
 * SVNClientWrapper.java
 *
 * ver 1.0.1 2012.11.05
 *
 ******************************************************************************/
package massbank.svn;

import java.io.File;
import java.util.List;
import java.util.HashMap;
import java.util.logging.Logger;
import org.apache.commons.io.FileUtils;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import org.tmatesoft.svn.core.wc.SVNStatus;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.ISVNOptions;
import org.tmatesoft.svn.core.wc.SVNWCClient;
import org.tmatesoft.svn.core.wc.SVNUpdateClient;
import org.tmatesoft.svn.core.wc.SVNCommitClient;
import org.tmatesoft.svn.core.wc.SVNStatusClient;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;

public class SVNClientWrapper {
    private static final int ERROR_NEXT_THROW = -1;
    private static final int ERROR_NEXT_BREAK = 0;
    private static final int ERROR_NEXT_RETRY = 1;

    private static HashMap<String, SVNClientManager> managerList = new HashMap<String, SVNClientManager>();
    private SVNClientManager manager = null;
    private SVNURL repoURL = null;
    private String workCopyPath = "";
    private File workCopy = null;
    private String className = this.getClass().getCanonicalName();
    private final Logger logger = Logger.getLogger("global");

    /*
     * constructor
     */
    public SVNClientWrapper(String repoURL, String workCopyPath) throws SVNException {
        this.workCopyPath = workCopyPath;
        this.workCopy = new File(workCopyPath);
        this.repoURL = SVNURL.parseURIEncoded(repoURL);
        String[] vals = SVNServiceManager.SVN_INFO.split(":");
        if (!managerList.containsKey(workCopyPath)) {
            ISVNOptions options = SVNWCUtil.createDefaultOptions(false);
            ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(vals[0], vals[1]);
            this.manager = SVNClientManager.newInstance(options, authManager);
            managerList.put(this.workCopyPath, this.manager);
        } else {
            this.manager = this.managerList.get(this.workCopyPath);
        }
    }

    /*
     * Schedules an unversioned item for addition to a repository thus putting it under version control.
     */
    public void add(String filePath) throws SVNException {
        SVNWCClient client = this.manager.getWCClient();
        int cnt = 0;
        while (true) {
            try {
                client.doAdd(new File(filePath), true, false, true, false);
                return;
            } catch (SVNException e) {
                int ret = handleError("add", e, ++cnt);
                switch (ret) {
                case ERROR_NEXT_THROW:
                    throw e;
                case ERROR_NEXT_BREAK:
                    return;
                case ERROR_NEXT_RETRY:
                    continue;
                }
            }
        }
    }

    /*
     * Schedules a Working Copy item for deletion.
     */
    public boolean delete(String filePath) throws SVNException {
        SVNWCClient client = this.manager.getWCClient();
        int cnt = 0;
        while (true) {
            try {
                client.doDelete(new File(filePath), true, false);
                return true;
            } catch (SVNException e) {
                SVNErrorCode errCode = e.getErrorMessage().getErrorCode();
                // E195006
                if (errCode == SVNErrorCode.CLIENT_MODIFIED) {
                    String errMessage = errCode.toString();
                    logger.warning("[SVNService] delete --> " + errMessage);
                    return false;
                }
                int ret = handleError("delete", e, ++cnt);
                switch (ret) {
                case ERROR_NEXT_THROW:
                    throw e;
                case ERROR_NEXT_BREAK:
                    return true;
                case ERROR_NEXT_RETRY:
                    continue;
                }
            }
        }
    }

    /*
     * Recursively cleans up the working copy, removing locks and resuming unfinished operations.
     */
    public void cleanup() {
        SVNWCClient client = this.manager.getWCClient();
        try {
            client.doCleanup(this.workCopy);
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    /*
     * Reverts all local changes made to a Working Copy item(s) thus bringing it to a 'pristine' state.
     */
    public void revert() {
        try {
            SVNWCClient client = this.manager.getWCClient();
            client.doRevert(this.workCopy, true);
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    /*
     * Collects and returns information on a single Working Copy item. 
     */
    public SVNInfo getInfo() throws SVNException {
        SVNWCClient client = this.manager.getWCClient();
        return client.doInfo(this.workCopy, SVNRevision.BASE);
    }

    /*
     * Committs local changes made to the Working Copy items.
     */
    public void commit(String commitMsg) throws SVNException {
        SVNCommitClient client = this.manager.getCommitClient();
        File[] commitDirs = new File[] { this.workCopy };
        int cnt = 0;
        while (true) {
            try {
                client.doCommit(commitDirs, true, commitMsg, false, true);
                return;
            } catch (SVNException e) {
                int ret = handleError("commit", e, ++cnt);
                switch (ret) {
                case ERROR_NEXT_THROW:
                    throw e;
                case ERROR_NEXT_BREAK:
                    return;
                case ERROR_NEXT_RETRY:
                    continue;
                }
            }
        }
    }

    /*
     * Committs a creation of a new directory
     */
    public void mkdir() {
        SVNCommitClient client = this.manager.getCommitClient();
        try {
            client.doMkDir(new SVNURL[] { this.repoURL }, "");
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    /*
     *  Checks out a Working Copy from a repository.
     */
    public long checkout() throws SVNException {
        return checkout(SVNRevision.HEAD.getNumber());
    }

    /*
     *  Checks out a Working Copy from a repository.
     */
    public long checkout(long revision) throws SVNException {
        SVNUpdateClient client = this.manager.getUpdateClient();
        client.setIgnoreExternals(false);
        SVNRevision getRevision = SVNRevision.create(revision);
        int cnt = 0;
        while (true) {
            try {
                long retRevision = client.doCheckout(this.repoURL, this.workCopy, getRevision, getRevision, true);
                return retRevision;
            } catch (SVNException e) {
                int ret = handleError("checkout", e, ++cnt);
                switch (ret) {
                case ERROR_NEXT_THROW:
                    throw e;
                case ERROR_NEXT_BREAK:
                    return 0;
                case ERROR_NEXT_RETRY:
                    continue;
                }
            }
        }
    }

    /*
     * Collects status information on a single Working Copy item.
     */
    public StatusHandler getStatus() throws SVNException {
        SVNStatusClient client = this.manager.getStatusClient();
        StatusHandler status = null;
        boolean reportAll = false;
        boolean checkouted = false;
        int cnt = 0;
        while (true) {
            try {
                StatusHandler sh = new StatusHandler(checkouted);
                long revision = client.doStatus(this.workCopy, true, true, reportAll, false, true, sh);
                return sh;
            } catch (SVNException e1) {
                SVNErrorCode errCode = e1.getErrorMessage().getErrorCode();
                // E155007
                if (errCode == SVNErrorCode.WC_NOT_DIRECTORY) {
                    try {
                        checkout();
                        reportAll = checkouted = true;
                    } catch (SVNException e2) {
                        throw e2;
                    }
                } else {
                    int ret = handleError("delete", e1, ++cnt);
                    switch (ret) {
                    case ERROR_NEXT_THROW:
                        throw e1;
                    case ERROR_NEXT_BREAK:
                        return null;
                    case ERROR_NEXT_RETRY:
                        continue;
                    }
                }
            }
        }
    }

    /*
     * Error handling
     */
    private int handleError(String methodName, SVNException e, int cnt) {
        if (SVNServiceManager.isTerminated) {
            return ERROR_NEXT_BREAK;
        }

        int ret = ERROR_NEXT_RETRY;
        SVNErrorCode errCode = e.getErrorMessage().getErrorCode();
        String errMessage = errCode.toString();
        logger.warning("[SVNService] " + methodName + " --> " + errMessage);
        int maxRetry = 5;
        if (methodName.equals("add") || methodName.equals("delete")) {
            maxRetry = 1;
        }

        // E155004, E155010
        if (errCode == SVNErrorCode.WC_LOCKED || errCode == SVNErrorCode.WC_PATH_NOT_FOUND) {
            logger.warning("[SVNService] WC:" + workCopyPath);
            try {
                Thread.sleep(2000);
            } catch (java.lang.InterruptedException ex) {
            }

            if (cnt <= maxRetry) {
                if (cnt == maxRetry) {
                    cleanup();
                }
                logger.info("[SVNService] retry " + String.valueOf(cnt));
                ret = ERROR_NEXT_RETRY;
            } else {
                ret = ERROR_NEXT_BREAK;
            }
        } else if (cnt == 1) {
            // E155000
            if (errCode == SVNErrorCode.WC_OBSTRUCTED_UPDATE) {
                cleanDirectory();
            }
            // E155015
            else if (errCode == SVNErrorCode.WC_FOUND_CONFLICT) {
                revert();
            }
            // E155032
            else if (errCode == SVNErrorCode.WC_DB_ERROR) {
                cleanDirectory();
            }
            // E170000
            else if (errCode == SVNErrorCode.RA_ILLEGAL_URL) {
                logger.info("[SVNService] URL:" + this.repoURL);
                mkdir();
            }
            // E170001, E175002, E200005
            else if (errCode == SVNErrorCode.RA_NOT_AUTHORIZED || errCode == SVNErrorCode.RA_DAV_REQUEST_FAILED
                    || errCode == SVNErrorCode.UNVERSIONED_RESOURCE) {
                ret = ERROR_NEXT_BREAK;
            }
            // E175005
            else if (errCode == SVNErrorCode.RA_DAV_ALREADY_EXISTS) {
                revert();
            }
            // E200030
            else if (errCode == SVNErrorCode.SQLITE_ERROR) {
                cleanup();
            }
        } else {
            ret = ERROR_NEXT_THROW;
        }
        return ret;
    }

    /*
     * clean directory
     */
    private void cleanDirectory() {
        logger.info("[SVNService] cleanDirectory");
        try {
            FileUtils.cleanDirectory(this.workCopy);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}