Java tutorial
/******************************************************************************* * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br> * * 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 *******************************************************************************/ package org.eclipse.egit.ui.internal.history; import java.io.IOException; import org.eclipse.egit.ui.Activator; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; /** * This class executes the search function for the find toolbar. Only one thread * is executed at a time. * <p> * This class maintains a <code>globalThreadIx</code> internal variable that * is incremented for each new thread started and the current running thread * constantly checks this variable. If the current thread has the same value as * <code>globalThreadIx</code> it continues executing, if it has a lower value * it means that a more recent search needs to be done and the current isn't * necessary any more, so the current thread returns. * </p> * <p> * To avoid consuming all the memory in the system, this class limits the * maximum results it stores. * </p> * * @see FindToolbar * @see FindResults */ public class FindToolbarThread extends Thread { private static final Object EXEC_LOCK = new Object(); private static final int MAX_RESULTS = 20000; String pattern; SWTCommit[] fileRevisions; FindToolbar toolbar; boolean ignoreCase; boolean findInCommitId; boolean findInComments; boolean findInAuthor; boolean findInCommitter; boolean findInReference; private volatile static int globalThreadIx = 0; private int currentThreadIx; /** * Creates a new object and increments the internal * <code>globalThreadIx</code> variable causing any earlier running thread * to return. */ public FindToolbarThread() { super("history_find_thread" + ++globalThreadIx); //$NON-NLS-1$ currentThreadIx = globalThreadIx; } @Override public void run() { synchronized (EXEC_LOCK) { execFind(); } } private void execFind() { // If it isn't the last event, just ignore it. if (currentThreadIx < globalThreadIx) { return; } FindResults findResults = toolbar.findResults; findResults.clear(); boolean maxResultsOverflow = false; if (pattern.length() > 0 && fileRevisions != null) { String findPattern = pattern; if (ignoreCase) { findPattern = pattern.toLowerCase(); } long lastUIUpdate = System.currentTimeMillis(); int totalRevisions = fileRevisions.length; int totalMatches = 0; boolean notFound = true; for (int i = 0; i < totalRevisions; i++) { // If a new find event was generated, ends the current thread. if (toolbar.getDisplay().isDisposed() || currentThreadIx < globalThreadIx) { return; } // Updates the toolbar with in process info. if (System.currentTimeMillis() - lastUIUpdate > 500) { final int percentage = (int) (((i + 1F) / totalRevisions) * 100); toolbar.getDisplay().asyncExec(new Runnable() { @Override public void run() { if (toolbar.isDisposed()) { return; } toolbar.progressUpdate(percentage); } }); lastUIUpdate = System.currentTimeMillis(); } // Finds for the pattern in the revision history. notFound = true; SWTCommit revision = fileRevisions[i]; try { revision.parseBody(); } catch (IOException e) { Activator.error("Error parsing body", e); //$NON-NLS-1$ continue; } if (findInCommitId) { String contentId = revision.getId().name(); if (contentId != null) { if (ignoreCase) { contentId = contentId.toLowerCase(); } if (contentId.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } } if (findInComments && notFound) { String comment = revision.getFullMessage(); if (comment != null) { if (ignoreCase) { comment = comment.toLowerCase(); } if (comment.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } } if (findInAuthor && notFound) { String author = revision.getAuthorIdent().getName(); if (author != null) { if (ignoreCase) { author = author.toLowerCase(); } if (author.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } if (notFound) { String email = revision.getAuthorIdent().getEmailAddress(); if (email != null) { if (ignoreCase) { email = email.toLowerCase(); } if (email.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } } } if (findInCommitter && notFound) { String committer = revision.getCommitterIdent().getName(); if (committer != null) { if (ignoreCase) { committer = committer.toLowerCase(); } if (committer.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } if (notFound) { String email = revision.getCommitterIdent().getEmailAddress(); if (email != null) { if (ignoreCase) { email = email.toLowerCase(); } if (email.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } } } if (findInReference && notFound) { if (revision.getRefCount() > 0) { for (int j = 0; j < revision.getRefCount(); j++) { Ref ref = revision.getRef(j); String refName = ref.getName(); refName = Repository.shortenRefName(refName); if (ignoreCase) refName = refName.toLowerCase(); if (refName.indexOf(findPattern) != -1) { totalMatches++; findResults.add(i, revision); notFound = false; } } } } if (totalMatches == MAX_RESULTS) { maxResultsOverflow = true; break; } } } // Updates the toolbar with the result find info. final boolean overflow = maxResultsOverflow; toolbar.getDisplay().syncExec(new Runnable() { @Override public void run() { if (toolbar.isDisposed()) { return; } toolbar.findCompletionUpdate(pattern, overflow); } }); } static void updateGlobalThreadIx() { ++globalThreadIx; } }