me.ikenga.SvnCollector.java Source code

Java tutorial

Introduction

Here is the source code for me.ikenga.SvnCollector.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package me.ikenga;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @author Stefan Kloe
 */
@Component
@Scope(value = "prototype")
public class SvnCollector {

    private static final Logger logger = LoggerFactory.getLogger(SvnCollector.class);

    private final static String PARAM_USER_NAME = "username";
    private final static String PARAM_PASSWORD = "password";
    private final static String PARAM_PROTOCOL = "protocol";
    private final static String PARAM_HOST = "host";
    private final static String PARAM_PORT = "port";
    private final static String PARAM_PATH = "path";
    private final static String LAST_REVISION = "lastRevision";

    private final static String SEPARATOR = "=\n";
    private final static String CONFIG = PARAM_USER_NAME + SEPARATOR + PARAM_PASSWORD + SEPARATOR + PARAM_PROTOCOL
            + SEPARATOR + PARAM_HOST + SEPARATOR + PARAM_PORT + SEPARATOR + PARAM_PATH + SEPARATOR;

    private Properties properties = new Properties();

    public SvnCollector() {
        loadProperties();
    }

    public void pull(final ScmHandler handler) throws ScmException {
        logger.debug("searching for new revisions");
        try {
            SVNURL svnurl = createSvnUrl();
            long headRevision = getHeadRevision(svnurl);

            long lastRevision = getLastRevision();
            if (lastRevision != headRevision) {
                ISVNLogEntryHandler svnLogHandler = new ISVNLogEntryHandler() {

                    @Override
                    public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
                        Date date = logEntry.getDate();
                        String author = logEntry.getAuthor();
                        long revision = logEntry.getRevision();

                        logger.debug(String.format("found revision %d from %s by %s", revision, date, author));

                        Map<String, Long> actions = new HashMap<>();
                        for (Map.Entry<String, SVNLogEntryPath> entry : logEntry.getChangedPaths().entrySet()) {
                            switch (entry.getValue().getType()) {
                            case SVNLogEntryPath.TYPE_ADDED:
                                addAction(actions, "SvnAddCount");
                                break;
                            case SVNLogEntryPath.TYPE_DELETED:
                                addAction(actions, "SvnDeleteCount");
                                break;
                            case SVNLogEntryPath.TYPE_MODIFIED:
                                addAction(actions, "SvnModifyCount");
                                break;
                            case SVNLogEntryPath.TYPE_REPLACED:
                                addAction(actions, "SvnReplaceCount");
                                break;
                            }
                        }

                        for (Map.Entry<String, Long> entry : actions.entrySet()) {
                            handler.handleLog(revision, date, logEntry.getMessage(), author, entry.getKey(),
                                    entry.getValue());
                        }
                    }

                    private void addAction(Map<String, Long> actions, String action) {
                        if (actions.containsKey(action)) {
                            actions.put(action, actions.get(action) + 1);
                        } else {
                            actions.put(action, 1L);
                        }
                    }
                };

                SVNClientManager.newInstance().getLogClient().doLog(svnurl, null, SVNRevision.HEAD,
                        SVNRevision.create(lastRevision), SVNRevision.HEAD, false, true, true, 0, null,
                        svnLogHandler);
            }

            properties.setProperty(LAST_REVISION, Long.toString(headRevision));
            saveProperties();
        } catch (SVNException ex) {
            logger.error("error accessing svn", ex);

            throw new ScmException(ex);
        }
    }

    private long getHeadRevision(SVNURL svnurl) throws ScmException {
        try {
            DAVRepositoryFactory.setup();
            SVNRepository repository = SVNRepositoryFactory.create(svnurl);

            byte[] decodedBytes = Base64.getDecoder().decode(properties.getProperty("password"));

            ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(
                    properties.getProperty("username"), new String(decodedBytes));
            repository.setAuthenticationManager(authManager);

            return repository.info(".", SVNRevision.HEAD.getNumber()).getRevision();
        } catch (SVNException ex) {

            throw new ScmException("could not create SvnRepositoryFactory", ex);
        }

    }

    private long getLastRevision() {
        return Long.valueOf(properties.getProperty(LAST_REVISION));
    }

    private void loadProperties() {
        File config = new File(System.getProperty("user.home"), ".ikenga/SvnCollector.properties");
        if (!config.exists()) {
            logger.info("no config file found, creating template");
            try {
                FileUtils.write(config, CONFIG, CharEncoding.UTF_8);
            } catch (IOException ex) {
                logger.error("could not write config file", ex);
            }
        }
        try (FileInputStream fileInputStream = new FileInputStream(config)) {
            properties.load(fileInputStream);
        } catch (IOException ex) {
            logger.error("could not load config file", ex);
        }

        if (StringUtils.isBlank(properties.getProperty(PARAM_PROTOCOL))
                || StringUtils.isBlank(properties.getProperty(PARAM_HOST))
                || StringUtils.isBlank(properties.getProperty(PARAM_PORT))
                || StringUtils.isBlank(properties.getProperty(PARAM_PATH))) {
            logger.error("config is empty");

            throw new IllegalStateException("not configured");
        }
    }

    private void saveProperties() {
        File config = new File(System.getProperty("user.home"), ".ikenga/SvnCollector.properties");

        try (FileOutputStream fileOutputStream = new FileOutputStream(config)) {
            properties.store(fileOutputStream, "");
        } catch (IOException ex) {
            logger.error("could not load config file", ex);
        }
    }

    private SVNURL createSvnUrl() throws NumberFormatException, ScmException {
        try {
            return SVNURL.create(properties.getProperty(PARAM_PROTOCOL), null, properties.getProperty(PARAM_HOST),
                    Integer.valueOf(properties.getProperty(PARAM_PORT)), properties.getProperty(PARAM_PATH), true);
        } catch (SVNException ex) {
            throw new ScmException("config is not filled correctly", ex);
        }
    }

}