com.microsoft.tfs.client.common.ui.compare.TFSItemContentComparator.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.tfs.client.common.ui.compare.TFSItemContentComparator.java

Source

// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See License.txt in the repository root.

package com.microsoft.tfs.client.common.ui.compare;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.compare.IStreamContentAccessor;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;

import com.microsoft.tfs.client.common.ui.framework.compare.ContentComparator;
import com.microsoft.tfs.client.common.ui.framework.compare.ContentComparisonResult;
import com.microsoft.tfs.client.common.util.ProgressMonitorTaskMonitorAdapter;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.Item;
import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.ItemType;
import com.microsoft.tfs.util.ArrayUtils;
import com.microsoft.tfs.util.HashUtils;
import com.microsoft.tfs.util.tasks.CanceledException;
import com.microsoft.tfs.util.tasks.TaskMonitorService;

public class TFSItemContentComparator implements ContentComparator {
    private static final Log log = LogFactory.getLog(TFSItemContentComparator.class);

    public static final TFSItemContentComparator INSTANCE = new TFSItemContentComparator();

    @Override
    public ContentComparisonResult contentsEqual(final Object input1, final Object input2,
            final IProgressMonitor monitor) {
        // server-server compare
        if (input1 instanceof TFSItemNode && input2 instanceof TFSItemNode) {
            return tfsItemNodesCompare((TFSItemNode) input1, (TFSItemNode) input2, monitor);
        }
        // server-local compare
        else if (input1 instanceof TFSItemNode) {
            return tfsItemCompareToLocalFile((TFSItemNode) input1, input2, monitor);
        }
        // local-server compare
        else if (input2 instanceof TFSItemNode) {
            return tfsItemCompareToLocalFile((TFSItemNode) input2, input1, monitor);
        }
        // local-local compare
        else {
            return localFileNodesCompare(input1, input2, monitor);
        }
    }

    /**
     * Compare two tfs item based on MD5 hash
     *
     * @param node1
     * @param node2
     * @param monitor
     * @return
     */
    private ContentComparisonResult tfsItemNodesCompare(final TFSItemNode node1, final TFSItemNode node2,
            final IProgressMonitor monitor) {
        final Item item1 = node1.getItem();
        final Item item2 = node2.getItem();

        if (item1.getItemType() == ItemType.FOLDER || item2.getItemType() == ItemType.FOLDER) {
            return ContentComparisonResult.EQUAL;
        }

        final byte[] hash1 = item1.getContentHashValue();
        final byte[] hash2 = item2.getContentHashValue();
        return compareByHash(hash1, hash2);
    }

    /**
     * Compare tfsItem with local file based on MD5 hash
     *
     * @param tfsItemNode
     * @param obj
     * @param monitor
     * @return
     */
    private ContentComparisonResult tfsItemCompareToLocalFile(final TFSItemNode tfsItemNode, final Object obj,
            final IProgressMonitor monitor) {
        final Item item = tfsItemNode.getItem();

        if (item.getItemType() == ItemType.FOLDER) {
            return ContentComparisonResult.EQUAL;
        }

        final byte[] itemHash = item.getContentHashValue();

        final byte[] otherItemHash = getItemHash(obj, monitor);

        return compareByHash(itemHash, otherItemHash);
    }

    /**
     * Compare two local file resource based on MD5 hash
     *
     * @param obj1
     * @param obj2
     * @param monitor
     * @return
     */
    private ContentComparisonResult localFileNodesCompare(final Object obj1, final Object obj2,
            final IProgressMonitor monitor) {
        final byte[] hash1 = getItemHash(obj1, monitor);
        final byte[] hash2 = getItemHash(obj2, monitor);
        return compareByHash(hash1, hash2);
    }

    /**
     *
     * @param hash1
     * @param hash2
     * @return
     */
    private ContentComparisonResult compareByHash(final byte[] hash1, final byte[] hash2) {
        if (hash1 == null || hash2 == null) {
            return ContentComparisonResult.UNKNOWN;
        }

        return Arrays.equals(hash1, hash2) ? ContentComparisonResult.EQUAL : ContentComparisonResult.NOT_EQUAL;
    }

    private byte[] getItemHash(final Object obj, final IProgressMonitor monitor) {
        if (obj instanceof TFSItemNode) {
            final TFSItemNode tfsItemNode = (TFSItemNode) obj;
            if (tfsItemNode.getItem().getItemType() == ItemType.FOLDER) {
                return null;
            }
            return tfsItemNode.getItem().getContentHashValue();
        }

        if (obj instanceof IStreamContentAccessor) {
            long startTime = 0;
            if (log.isTraceEnabled()) {
                startTime = System.currentTimeMillis();
                final String messageFormat = "hashing InputStream from [{0}]"; //$NON-NLS-1$
                final String message = MessageFormat.format(messageFormat, obj);
                log.trace(message);
            }

            final IStreamContentAccessor streamContentAccessor = (IStreamContentAccessor) obj;
            InputStream inputStream;
            try {
                inputStream = streamContentAccessor.getContents();
            } catch (final CoreException e) {
                if (log.isDebugEnabled()) {
                    log.debug("couldn't access InputStream", e); //$NON-NLS-1$
                }

                return null;
            }
            if (inputStream == null) {
                return null;
            }
            TaskMonitorService.pushTaskMonitor(new ProgressMonitorTaskMonitorAdapter(monitor));
            try {
                final byte[] hash = HashUtils.hashStream(inputStream, HashUtils.ALGORITHM_MD5,
                        TaskMonitorService.getTaskMonitor());

                if (log.isTraceEnabled()) {
                    final long elapsed = System.currentTimeMillis() - startTime;
                    final String messageFormat = "result ({0} ms): {1}"; //$NON-NLS-1$
                    final String message = MessageFormat.format(messageFormat, elapsed,
                            ArrayUtils.byteArrayToHexString(hash));

                    log.trace(message);
                }

                return hash;
            } catch (final CanceledException e) {
                throw new OperationCanceledException();
            } catch (final IOException e) {
                if (log.isDebugEnabled()) {
                    log.debug("hashing InputStream failed", e); //$NON-NLS-1$
                }

                return null;
            } finally {
                TaskMonitorService.popTaskMonitor(false);
            }
        }

        return null;
    }
}