org.repodriller.RepositoryMining.java Source code

Java tutorial

Introduction

Here is the source code for org.repodriller.RepositoryMining.java

Source

/**
 * Copyright 2014 Maurcio Aniche
    
 * Licensed 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.repodriller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.log4j.Logger;
import org.repodriller.domain.ChangeSet;
import org.repodriller.domain.Commit;
import org.repodriller.filter.commit.CommitFilter;
import org.repodriller.filter.commit.NoFilter;
import org.repodriller.filter.range.CommitRange;
import org.repodriller.persistence.NoPersistence;
import org.repodriller.persistence.PersistenceMechanism;
import org.repodriller.scm.CommitVisitor;
import org.repodriller.scm.SCMRepository;

import com.google.common.collect.Lists;

public class RepositoryMining {

    private static final String DATE_FORMAT = "dd/MM/yyyy HH:mm:ss";
    private static final Logger log = Logger.getLogger(RepositoryMining.class);

    private List<SCMRepository> repos;
    private CommitVisitorIterator visitors;
    private CommitRange range;
    private int threads;
    private boolean reverseOrder;
    private List<CommitFilter> filters;

    public RepositoryMining() {
        repos = new ArrayList<SCMRepository>();
        visitors = new CommitVisitorIterator(log);
        filters = Arrays.asList((CommitFilter) new NoFilter());
        this.threads = 1;
    }

    public RepositoryMining through(CommitRange range) {
        this.range = range;
        return this;
    }

    public RepositoryMining in(SCMRepository... repo) {
        this.repos.addAll(Arrays.asList(repo));
        return this;
    }

    public RepositoryMining process(CommitVisitor visitor, PersistenceMechanism writer) {
        visitors.put(visitor, writer);
        return this;
    }

    public RepositoryMining filters(CommitFilter... filters) {
        this.filters = Arrays.asList(filters);
        return this;
    }

    public RepositoryMining reverseOrder() {
        reverseOrder = true;
        return this;
    }

    public RepositoryMining process(CommitVisitor visitor) {
        return process(visitor, new NoPersistence());
    }

    public void mine() {

        for (SCMRepository repo : repos) {
            visitors.initializeVisitors(repo);
            processRepos(repo);
            visitors.finalizeVisitors(repo);
        }
        visitors.closeAllPersistence();
        printScript();

    }

    private void processRepos(SCMRepository repo) {
        log.info("Git repository in " + repo.getPath());

        List<ChangeSet> allCs = range.get(repo.getScm());
        if (!reverseOrder)
            Collections.reverse(allCs);

        log.info("Total of commits: " + allCs.size());

        log.info("Starting threads: " + threads);
        ExecutorService exec = Executors.newFixedThreadPool(threads);
        List<List<ChangeSet>> partitions = Lists.partition(allCs, threads);
        for (List<ChangeSet> partition : partitions) {

            exec.submit(() -> {
                for (ChangeSet cs : partition) {
                    try {
                        processChangeSet(repo, cs);
                    } catch (OutOfMemoryError e) {
                        System.err.println("Commit " + cs.getId() + " in " + repo.getLastDir() + " caused OOME");
                        e.printStackTrace();
                        System.err.println("goodbye :/");

                        log.fatal("Commit " + cs.getId() + " in " + repo.getLastDir() + " caused OOME", e);
                        log.fatal("Goodbye! ;/");
                        System.exit(-1);
                    } catch (Throwable t) {
                        log.error(t);
                    }
                }
            });
        }

        try {
            exec.shutdown();
            exec.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            log.error("error waiting for threads to terminate in " + repo.getLastDir(), e);
        }
    }

    private void printScript() {
        log.info("# --------------------------------------------------");
        log.info("Study has been executed in the following projects:");
        for (SCMRepository repo : repos) {
            log.info("- " + repo.getOrigin() + ", from " + repo.getFirstCommit() + " to " + repo.getHeadCommit());
        }

        log.info("The following processors were executed:");

        visitors.printScript();
    }

    private void processChangeSet(SCMRepository repo, ChangeSet cs) {
        Commit commit = repo.getScm().getCommit(cs.getId());
        log.info("Commit #" + commit.getHash() + " @ " + repo.getLastDir() + " in "
                + DateFormatUtils.format(commit.getDate().getTime(), DATE_FORMAT) + " from "
                + commit.getAuthor().getName() + " with " + commit.getModifications().size() + " modifications");

        if (!filtersAccept(commit)) {
            log.info("-> Filtered");
            return;
        }

        visitors.processCommit(repo, commit);

    }

    private boolean filtersAccept(Commit commit) {
        for (CommitFilter filter : filters) {
            if (!filter.accept(commit))
                return false;
        }
        return true;
    }

    public RepositoryMining withThreads(int n) {
        this.threads = n;
        return this;
    }
}