org.eclipse.egit.internal.mylyn.ui.commit.TaskReferenceFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.egit.internal.mylyn.ui.commit.TaskReferenceFactory.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Benjamin Muskalla and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Benjamin Muskalla <bmuskalla@tasktop.com> - initial API and implementation
 *     Ilya Ivanov <ilya.ivanov@intland.com> - task repository url resolving
 *******************************************************************************/
package org.eclipse.egit.internal.mylyn.ui.commit;

import java.io.IOException;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;

import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.egit.core.Activator;
import org.eclipse.egit.internal.mylyn.ui.EGitMylynUI;
import org.eclipse.egit.ui.internal.synchronize.model.GitModelCommit;
import org.eclipse.egit.ui.internal.synchronize.model.GitModelRepository;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
import org.eclipse.mylyn.internal.team.ui.LinkedTaskInfo;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.team.ui.AbstractTaskReference;

/**
 * Adapter factory to bridge between Mylyn and EGit domain models.
 */
@SuppressWarnings("restriction")
public class TaskReferenceFactory implements IAdapterFactory {
    private static final Class<?>[] ADAPTER_TYPES = new Class[] { AbstractTaskReference.class };

    private static final String BUGTRACK_SECTION = "bugtracker"; //$NON-NLS-1$
    private static final String BUGTRACK_URL = "url"; //$NON-NLS-1$

    @SuppressWarnings({ "rawtypes" })
    public Class[] getAdapterList() {
        final Class[] c = new Class[ADAPTER_TYPES.length];
        System.arraycopy(ADAPTER_TYPES, 0, c, 0, c.length);
        return c;
    }

    @SuppressWarnings("rawtypes")
    public Object getAdapter(Object adaptableObject, Class adapterType) {
        if (!AbstractTaskReference.class.equals(adapterType))
            return null;

        return adaptFromObject(adaptableObject);
    }

    private AbstractTaskReference adaptFromObject(Object element) {
        RevCommit commit = getCommitForElement(element);
        if (commit != null)
            return adaptFromRevCommit(commit);

        return null;
    }

    /**
     * Finds {@link TaskRepository} for provided {@link RevCommit} object and returns new {@link LinkedTaskInfo} object
     * or <code>null</code> if nothing found.
     * @param commit a {@link RevCommit} object to look for
     * @return {@link LinkedTaskInfo} object, or <code>null</code> if repository not found
     */
    private AbstractTaskReference adaptFromRevCommit(RevCommit commit) {
        Repository[] repositories = Activator.getDefault().getRepositoryCache().getAllRepositories();
        for (Repository r : repositories) {
            RevWalk revWalk = new RevWalk(r);

            String repoUrl = null;
            String message = null;
            long timestamp = 0;

            // try to get repository url and commit message
            try {
                RevCommit revCommit = revWalk.parseCommit(commit);
                if (revCommit != null) {
                    repoUrl = getRepoUrl(r);
                    message = revCommit.getFullMessage();
                    timestamp = (long) revCommit.getCommitTime() * 1000;
                }
            } catch (IOException e) {
                continue;
            } catch (RuntimeException e) {
                continue;
            }

            if (message == null || message.trim().length() == 0)
                continue;

            String taskRepositoryUrl = null;
            if (repoUrl != null) {
                TaskRepository repository = getTaskRepositoryByGitRepoURL(repoUrl);
                if (repository != null)
                    taskRepositoryUrl = repository.getRepositoryUrl();
            }

            return new LinkedTaskInfo(taskRepositoryUrl, null, null, message, timestamp);
        }

        return null;
    }

    private static RevCommit getCommitForElement(Object element) {
        RevCommit commit = null;
        if (element instanceof RevCommit)
            commit = (RevCommit) element;
        else if (element instanceof GitModelCommit) {
            GitModelCommit modelCommit = (GitModelCommit) element;
            if (!(modelCommit.getParent() instanceof GitModelRepository))
                return null; // should never happen

            GitModelRepository parent = (GitModelRepository) modelCommit.getParent();
            Repository repo = parent.getRepository();
            AbbreviatedObjectId id = modelCommit.getCachedCommitObj().getId();

            commit = new RevWalk(repo).lookupCommit(id.toObjectId());
        }
        return commit;
    }

    /**
     * Finds {@link TaskRepository} by provided Git repository Url
     * @param repoUrl Git repository url
     * @return {@link TaskRepository} associated with this Git repo or <code>null</code> if nothing found
     */
    private TaskRepository getTaskRepositoryByGitRepoURL(final String repoUrl) {
        if (repoUrl == null)
            return null;

        try {
            return getTaskRepositoryByHost(new URIish(repoUrl).getHost());
        } catch (Exception ex) {
            EGitMylynUI.getDefault().getLog()
                    .log(new Status(IStatus.ERROR, EGitMylynUI.PLUGIN_ID, "failed to get repo url", ex)); //$NON-NLS-1$
        }
        return null;
    }

    private static String getRepoUrl(Repository repo) {
        String configuredUrl = repo.getConfig().getString(BUGTRACK_SECTION, null, BUGTRACK_URL);
        String originUrl = repo.getConfig().getString(ConfigConstants.CONFIG_REMOTE_SECTION,
                Constants.DEFAULT_REMOTE_NAME, ConfigConstants.CONFIG_KEY_URL);
        return configuredUrl != null ? configuredUrl : originUrl;
    }

    private TaskRepository getTaskRepositoryByHost(String host) {
        List<TaskRepository> repositories = TasksUiPlugin.getRepositoryManager().getAllRepositories();
        if (repositories == null || repositories.isEmpty())
            return null;

        if (repositories.size() == 1)
            return repositories.iterator().next();

        for (TaskRepository repository : repositories) {
            if (!repository.isOffline()) {
                try {
                    URL url = new URL(repository.getRepositoryUrl());

                    if (isSameHosts(host, url.getHost()))
                        return repository;
                } catch (MalformedURLException e) {
                    // We cannot do anything.
                }
            }
        }
        return null;
    }

    private boolean isSameHosts(final String name1, final String name2) {
        String hostname1 = name1 == null ? "" : name1.trim(); //$NON-NLS-1$
        String hostname2 = name2 == null ? "" : name2.trim(); //$NON-NLS-1$

        if (hostname1.equals(hostname2))
            return true;

        String localHost = "localhost"; //$NON-NLS-1$
        String resolvedHostName;
        try {
            resolvedHostName = InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException ex) {
            resolvedHostName = localHost;
        }

        if (hostname1.length() == 0)
            hostname1 = resolvedHostName;

        if (hostname2.length() == 0)
            hostname2 = resolvedHostName;

        if (hostname1.equals(hostname2))
            return true;

        if ((hostname1.equals(localHost) && hostname2.equals(resolvedHostName))
                || (hostname1.equals(resolvedHostName) && hostname2.equals(localHost)))
            return true;

        return false;
    }

}