/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation 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:
* IBM Corporation - initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.search;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.search.ui.IQueryListener;
import org.eclipse.search.ui.ISearchQuery;
import org.eclipse.search.ui.ISearchResultViewPart;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
public class InternalSearchUI {
//The shared instance.
private static InternalSearchUI fgInstance;
// contains all running jobs
private HashMap fSearchJobs;
private QueryManager fSearchResultsManager;
// private PositionTracker fPositionTracker;
//
// private SearchViewManager fSearchViewManager;
public static final Object FAMILY_SEARCH = new Object();
private class SearchJobRecord {
public ISearchQuery query;
public Job job;
public boolean isRunning;
public SearchJobRecord(ISearchQuery job) {
this.query = job;
this.isRunning = false;
this.job = null;
}
}
private class InternalSearchJob extends Job {
private SearchJobRecord fSearchJobRecord;
public InternalSearchJob(SearchJobRecord sjr) {
super(sjr.query.getLabel());
fSearchJobRecord = sjr;
}
protected IStatus run(IProgressMonitor monitor) {
fSearchJobRecord.job = this;
searchJobStarted(fSearchJobRecord);
IStatus status = null;
int origPriority = Thread.currentThread().getPriority();
try {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
} catch (SecurityException e) {
}
try {
status = fSearchJobRecord.query.run(monitor);
} finally {
try {
Thread.currentThread().setPriority(origPriority);
} catch (SecurityException e) {
}
searchJobFinished(fSearchJobRecord);
}
fSearchJobRecord.job = null;
return status;
}
public boolean belongsTo(Object family) {
return family == org.eclipse.search2.internal.ui.InternalSearchUI.FAMILY_SEARCH;
}
}
private void searchJobStarted(SearchJobRecord record) {
record.isRunning = true;
getSearchManager().queryStarting(record.query);
}
private void searchJobFinished(SearchJobRecord record) {
record.isRunning = false;
fSearchJobs.remove(record);
getSearchManager().queryFinished(record.query);
}
/**
* The constructor.
*/
public InternalSearchUI() {
fgInstance = this;
fSearchJobs = new HashMap();
fSearchResultsManager = new QueryManager();
// fPositionTracker = new PositionTracker();
// fSearchViewManager = new SearchViewManager(fSearchResultsManager);
// PlatformUI.getWorkbench().getProgressService().registerIconForFamily(SearchPluginImages.DESC_VIEW_SEARCHRES, FAMILY_SEARCH);
}
/**
* @return returns the shared instance.
*/
public static InternalSearchUI getInstance() {
if (fgInstance == null)
fgInstance = new InternalSearchUI();
return fgInstance;
}
// public ISearchResultViewPart getSearchView() {
// return getSearchViewManager().getActiveSearchView();
// }
// private IWorkbenchSiteProgressService getProgressService() {
// ISearchResultViewPart view = getSearchView();
// if (view != null) {
// IWorkbenchPartSite site = view.getSite();
// if (site != null)
// return (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class);
// }
// return null;
// }
public boolean runSearchInBackground(ISearchQuery query, ISearchResultViewPart view) {
if (isQueryRunning(query))
return false;
// // prepare view
// if (view == null) {
// getSearchViewManager().activateSearchView(true);
// } else {
// getSearchViewManager().activateSearchView(view);
// }
addQuery(query);
SearchJobRecord sjr = new SearchJobRecord(query);
fSearchJobs.put(query, sjr);
Job job = new InternalSearchJob(sjr);
job.setPriority(Job.BUILD);
job.setUser(true);
// IWorkbenchSiteProgressService service= getProgressService();
// if (service != null) {
// service.schedule(job, 0, true);
// } else {
job.schedule();
// }
return true;
}
public boolean isQueryRunning(ISearchQuery query) {
SearchJobRecord sjr = (SearchJobRecord)fSearchJobs.get(query);
return sjr != null && sjr.isRunning;
}
public IStatus runSearchInForeground(IRunnableContext context, final ISearchQuery query, ISearchResultViewPart view) {
if (isQueryRunning(query)) {
return Status.CANCEL_STATUS;
}
// // prepare view
// if (view == null) {
// getSearchViewManager().activateSearchView(true);
// } else {
// getSearchViewManager().activateSearchView(view);
// }
addQuery(query);
SearchJobRecord sjr = new SearchJobRecord(query);
fSearchJobs.put(query, sjr);
//
// if (context == null)
// context= new ProgressMonitorDialog(null);
return doRunSearchInForeground(sjr, context);
}
/**
* Run a runnable. Convert all thrown exceptions to either
* InterruptedException or InvocationTargetException
*/
private static void runInCurrentThread(IRunnableWithProgress runnable,
IProgressMonitor progressMonitor) throws InterruptedException,
InvocationTargetException {
try {
if (runnable != null) {
runnable.run(progressMonitor);
}
} catch (InvocationTargetException e) {
throw e;
} catch (InterruptedException e) {
throw e;
} catch (OperationCanceledException e) {
throw new InterruptedException();
} catch (ThreadDeath e) {
// Make sure to propagate ThreadDeath, or threads will never fully
// terminate
throw e;
} catch (RuntimeException e) {
throw new InvocationTargetException(e);
} catch (Error e) {
throw new InvocationTargetException(e);
}
}
private IStatus doRunSearchInForeground(final SearchJobRecord rec, IRunnableContext context) {
try {
runInCurrentThread(new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
searchJobStarted(rec);
try {
IStatus status = rec.query.run(monitor);
if (status.matches(IStatus.CANCEL)) {
throw new InterruptedException();
}
if (!status.isOK()) {
throw new InvocationTargetException(new CoreException(status));
}
} catch (OperationCanceledException e) {
throw new InterruptedException();
} finally {
searchJobFinished(rec);
}
}
}, new NullProgressMonitor());
} catch (InvocationTargetException e) {
Throwable innerException = e.getTargetException();
if (innerException instanceof CoreException) {
return ((CoreException)innerException).getStatus();
}
return new Status(IStatus.ERROR, "SearchPlugin.getID()", 0, "An unexpected exception occurred during search", innerException);
} catch (InterruptedException e) {
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
public static void shutdown() {
InternalSearchUI instance = fgInstance;
if (instance != null)
instance.doShutdown();
}
private void doShutdown() {
Iterator jobRecs = fSearchJobs.values().iterator();
while (jobRecs.hasNext()) {
SearchJobRecord element = (SearchJobRecord)jobRecs.next();
if (element.job != null)
element.job.cancel();
}
// fPositionTracker.dispose();
// fSearchViewManager.dispose(fSearchResultsManager);
}
public void cancelSearch(ISearchQuery job) {
SearchJobRecord rec = (SearchJobRecord)fSearchJobs.get(job);
if (rec != null && rec.job != null)
rec.job.cancel();
}
public QueryManager getSearchManager() {
return fSearchResultsManager;
}
// public SearchViewManager getSearchViewManager() {
// return fSearchViewManager;
// }
//
// public PositionTracker getPositionTracker() {
// return fPositionTracker;
// }
public void addQueryListener(IQueryListener l) {
getSearchManager().addQueryListener(l);
}
public ISearchQuery[] getQueries() {
return getSearchManager().getQueries();
}
public void removeQueryListener(IQueryListener l) {
getSearchManager().removeQueryListener(l);
}
public void removeQuery(ISearchQuery query) {
if (query == null) {
throw new IllegalArgumentException();
}
cancelSearch(query);
getSearchManager().removeQuery(query);
fSearchJobs.remove(query);
}
public void addQuery(ISearchQuery query) {
if (query == null) {
throw new IllegalArgumentException();
}
establishHistoryLimit();
getSearchManager().addQuery(query);
}
private void establishHistoryLimit() {
// int historyLimit= SearchPreferencePage.getHistoryLimit();
// QueryManager searchManager= getSearchManager();
// if (historyLimit >= searchManager.getSize()) {
// return;
// }
// int numberQueriesNotShown= 0;
// SearchViewManager searchViewManager= getSearchViewManager();
// ISearchQuery[] queries= searchManager.getQueries();
// for (int i= 0; i < queries.length; i++) {
// ISearchQuery query= queries[i];
// if (!searchViewManager.isShown(query)) {
// if (++numberQueriesNotShown >= historyLimit) {
// removeQuery(query);
// }
// }
// }
}
public void removeAllQueries() {
for (Iterator queries = fSearchJobs.keySet().iterator(); queries.hasNext(); ) {
ISearchQuery query = (ISearchQuery)queries.next();
cancelSearch(query);
}
fSearchJobs.clear();
getSearchManager().removeAll();
}
// public void showSearchResult(SearchView searchView, ISearchResult result, boolean openInNew) {
// if (openInNew)
// searchView= (SearchView)getSearchViewManager().activateSearchView(true, openInNew);
// showSearchResult(searchView, result);
// }
//
// private void showSearchResult(SearchView searchView, ISearchResult result) {
// getSearchManager().touch(result.getQuery());
// searchView.showSearchResult(result);
// }
}