/******************************************************************************* * Copyright (c) 2000, 2015 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 *******************************************************************************/ package org.eclipse.search.internal.ui; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IMarkerDelta; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.IResourceChangeListener; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.search.internal.ui.util.ExceptionHandler; import org.eclipse.search.ui.IGroupByKeyComputer; import org.eclipse.search.ui.SearchUI; /** * Manage search results * @deprecated old search */ @Deprecated public class SearchManager implements IResourceChangeListener { static SearchManager fgDefault; Search fCurrentSearch= null; private SearchManager() { SearchPlugin.getWorkspace().addResourceChangeListener(this); } private HashSet<SearchResultViewer> fListeners= new HashSet<>(); private LinkedList<Search> fPreviousSearches= new LinkedList<>(); private boolean fIsRemoveAll= false; public static synchronized SearchManager getDefault() { if (fgDefault == null) fgDefault= new SearchManager(); return fgDefault; } public void dispose() { SearchPlugin.getWorkspace().removeResourceChangeListener(this); } /** * Returns the list with previous searches (ISearch). * @return previous searches */ LinkedList<Search> getPreviousSearches() { return fPreviousSearches; } /** * Returns the list with current (last) results * @return the current results */ ArrayList<SearchResultViewEntry> getCurrentResults() { if (fCurrentSearch == null) return new ArrayList<>(0); return (ArrayList<SearchResultViewEntry>)fCurrentSearch.getResults(); } public Search getCurrentSearch() { return fCurrentSearch; } void removeAllSearches() { SearchPlugin.getWorkspace().removeResourceChangeListener(this); WorkspaceModifyOperation op= new WorkspaceModifyOperation(null) { @Override protected void execute(IProgressMonitor monitor) throws CoreException { monitor.beginTask(SearchMessages.SearchManager_updating, 100); SearchPlugin.getWorkspace().getRoot().deleteMarkers(SearchUI.SEARCH_MARKER, true, IResource.DEPTH_INFINITE); monitor.worked(100); monitor.done(); } }; boolean isAutoBuilding= SearchPlugin.setAutoBuilding(false); try { ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell()); dialog.run(true, true, op); } catch (InvocationTargetException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_deleteMarkers_title, SearchMessages.Search_Error_deleteMarkers_message); } catch (InterruptedException e) { // Do nothing. Operation has been canceled. } finally { SearchPlugin.getWorkspace().addResourceChangeListener(this); SearchPlugin.setAutoBuilding(isAutoBuilding); } // clear searches fPreviousSearches= new LinkedList<>(); fCurrentSearch= null; // update viewers Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) { SearchResultViewer viewer= iter.next(); handleAllSearchesRemoved(viewer); } } private void handleAllSearchesRemoved(SearchResultViewer viewer) { viewer.handleAllSearchesRemoved(); } void setCurrentSearch(final Search search) { if (fCurrentSearch == search) return; SearchPlugin.getWorkspace().removeResourceChangeListener(this); WorkspaceModifyOperation op= new WorkspaceModifyOperation(null) { @Override protected void execute(IProgressMonitor monitor) throws CoreException { internalSetCurrentSearch(search, monitor); } }; boolean isAutoBuilding= SearchPlugin.setAutoBuilding(false); try { ProgressMonitorDialog dialog= new ProgressMonitorDialog(getShell()); dialog.run(true, true, op); } catch (InvocationTargetException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_switchSearch_title, SearchMessages.Search_Error_switchSearch_message); } catch (InterruptedException e) { // Do nothing. Operation has been canceled. } finally { SearchPlugin.setAutoBuilding(isAutoBuilding); } getPreviousSearches().remove(search); getPreviousSearches().addFirst(search); } void internalSetCurrentSearch(final Search search, IProgressMonitor monitor) { if (fCurrentSearch != null) fCurrentSearch.backupMarkers(); final Search previousSearch= fCurrentSearch; fCurrentSearch= search; monitor.beginTask(SearchMessages.SearchManager_updating, getCurrentResults().size() + 20); // remove current search markers try { SearchPlugin.getWorkspace().getRoot().deleteMarkers(SearchUI.SEARCH_MARKER, true, IResource.DEPTH_INFINITE); } catch (CoreException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_deleteMarkers_title, SearchMessages.Search_Error_deleteMarkers_message); } monitor.worked(10); // add search markers Iterator<SearchResultViewEntry> iter= getCurrentResults().iterator(); ArrayList<SearchResultViewEntry> emptyEntries= new ArrayList<>(10); boolean filesChanged= false; boolean filesDeleted= false; IGroupByKeyComputer groupByKeyComputer= getCurrentSearch().getGroupByKeyComputer(); while (iter.hasNext()) { monitor.worked(1); SearchResultViewEntry entry= iter.next(); Iterator<Map<String, Object>> attrPerMarkerIter= entry.getAttributesPerMarker().iterator(); entry.clearMarkerList(); if (entry.getResource() == null || !entry.getResource().exists()) { emptyEntries.add(entry); filesDeleted= true; continue; } while (attrPerMarkerIter.hasNext()) { IMarker newMarker= null; try { newMarker= entry.getResource().createMarker(entry.getMarkerType()); } catch (CoreException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_createMarker_title, SearchMessages.Search_Error_createMarker_message); continue; } try { newMarker.setAttributes(attrPerMarkerIter.next()); if (groupByKeyComputer !=null && groupByKeyComputer.computeGroupByKey(newMarker) == null) { filesDeleted= true; newMarker.delete(); continue; } } catch (CoreException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_markerAttributeAccess_title, SearchMessages.Search_Error_markerAttributeAccess_message); } entry.add(newMarker); } if (entry.getMatchCount() == 0) emptyEntries.add(entry); else if (!filesChanged && entry.getResource().getModificationStamp() != entry.getModificationStamp()) filesChanged= true; } getCurrentResults().removeAll(emptyEntries); monitor.worked(10); String warningMessage= null; Display display= getDisplay(); if (filesChanged) warningMessage= SearchMessages.SearchManager_resourceChanged; if (filesDeleted) { if (warningMessage == null) warningMessage= ""; //$NON-NLS-1$ else warningMessage += "\n"; //$NON-NLS-1$ warningMessage += SearchMessages.SearchManager_resourceDeleted; } if (warningMessage != null) { if (display != null && !display.isDisposed()) { final String warningTitle= SearchMessages.SearchManager_resourceChangedWarning; final String warningMsg= warningMessage; display.syncExec(new Runnable() { @Override public void run() { MessageDialog.openWarning(getShell(), warningTitle, warningMsg); } }); } } // update viewers Iterator<SearchResultViewer> iter2= fListeners.iterator(); if (display != null && !display.isDisposed()) { final Viewer visibleViewer= ((SearchResultView)SearchUI.getSearchResultView()).getViewer(); while (iter2.hasNext()) { final SearchResultViewer viewer= iter2.next(); display.syncExec(new Runnable() { @Override public void run() { if (previousSearch != null && viewer == visibleViewer) previousSearch.setSelection(viewer.getSelection()); viewer.setInput(null); viewer.setPageId(search.getPageId()); viewer.setGotoMarkerAction(search.getGotoMarkerAction()); viewer.setContextMenuTarget(search.getContextMenuContributor()); viewer.setActionGroupFactory(null); viewer.setInput(getCurrentResults()); viewer.setActionGroupFactory(search.getActionGroupFactory()); viewer.setSelection(fCurrentSearch.getSelection(), true); } }); } } monitor.done(); } /** * Returns the number of matches * @return the number of matches */ int getCurrentItemCount() { if (fCurrentSearch != null) return fCurrentSearch.getItemCount(); return 0; } void removeAllResults() { fIsRemoveAll= true; try { SearchPlugin.getWorkspace().getRoot().deleteMarkers(SearchUI.SEARCH_MARKER, true, IResource.DEPTH_INFINITE); } catch (CoreException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_deleteMarkers_title, SearchMessages.Search_Error_deleteMarkers_message); fIsRemoveAll= false; } } void addNewSearch(final Search newSearch) { SearchPlugin.getWorkspace().removeResourceChangeListener(this); // Clear the viewers Iterator<SearchResultViewer> iter= fListeners.iterator(); Display display= getDisplay(); if (display != null && !display.isDisposed()) { final Viewer visibleViewer= ((SearchResultView)SearchUI.getSearchResultView()).getViewer(); while (iter.hasNext()) { final SearchResultViewer viewer= iter.next(); display.syncExec(new Runnable() { @Override public void run() { if (fCurrentSearch != null && viewer == visibleViewer) fCurrentSearch.setSelection(viewer.getSelection()); setNewSearch(viewer, newSearch); } }); } } if (fCurrentSearch != null) { if (fCurrentSearch.isSameSearch(newSearch)) getPreviousSearches().remove(fCurrentSearch); else fCurrentSearch.backupMarkers(); } fCurrentSearch= newSearch; getPreviousSearches().addFirst(fCurrentSearch); // Remove the markers try { SearchPlugin.getWorkspace().getRoot().deleteMarkers(SearchUI.SEARCH_MARKER, true, IResource.DEPTH_INFINITE); } catch (CoreException ex) { ExceptionHandler.handle(ex, SearchMessages.Search_Error_deleteMarkers_title, SearchMessages.Search_Error_deleteMarkers_message); } } void searchFinished(ArrayList<SearchResultViewEntry> results) { Assert.isNotNull(results); getCurrentSearch().setResults(results); Display display= getDisplay(); if (display == null || display.isDisposed()) return; if (Thread.currentThread() == display.getThread()) handleNewSearchResult(); else { display.syncExec(new Runnable() { @Override public void run() { handleNewSearchResult(); } }); } SearchPlugin.getWorkspace().addResourceChangeListener(this); } //--- Change event handling ------------------------------------------------- void addSearchChangeListener(SearchResultViewer viewer) { fListeners.add(viewer); } void removeSearchChangeListener(SearchResultViewer viewer) { Assert.isNotNull(viewer); fListeners.remove(viewer); } private final void handleSearchMarkersChanged(IMarkerDelta[] markerDeltas) { if (fIsRemoveAll) { handleRemoveAll(); fIsRemoveAll= false; return; } Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) iter.next().getControl().setRedraw(false); for (int i=0; i < markerDeltas.length; i++) { handleSearchMarkerChanged(markerDeltas[i]); } iter= fListeners.iterator(); while (iter.hasNext()) iter.next().getControl().setRedraw(true); } private void handleSearchMarkerChanged(IMarkerDelta markerDelta) { int kind= markerDelta.getKind(); // don't listen for adds will be done by ISearchResultView.addMatch(...) if (((kind & IResourceDelta.REMOVED) != 0)) handleRemoveMatch(markerDelta.getMarker()); else if ((kind & IResourceDelta.CHANGED) != 0) handleUpdateMatch(markerDelta.getMarker()); } private void handleRemoveAll() { if (fCurrentSearch != null) fCurrentSearch.removeResults(); Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) iter.next().handleRemoveAll(); } private void handleNewSearchResult() { Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) { SearchResultViewer viewer= iter.next(); viewer.setInput(getCurrentResults()); } } private void setNewSearch(SearchResultViewer viewer, Search search) { viewer.setInput(null); viewer.clearTitle(); viewer.setPageId(search.getPageId()); viewer.setGotoMarkerAction(search.getGotoMarkerAction()); viewer.setContextMenuTarget(search.getContextMenuContributor()); viewer.setActionGroupFactory(search.getActionGroupFactory()); } private void handleRemoveMatch(IMarker marker) { SearchResultViewEntry entry= findEntry(marker); if (entry != null) { entry.remove(marker); if (entry.getMatchCount() == 0) { getCurrentResults().remove(entry); Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) iter.next().handleRemoveMatch(entry); } else { Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) iter.next().handleUpdateMatch(entry, true); } } } private void handleUpdateMatch(IMarker marker) { SearchResultViewEntry entry= findEntry(marker); if (entry != null) { Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) iter.next().handleUpdateMatch(entry, false); } } private SearchResultViewEntry findEntry(IMarker marker) { Iterator<SearchResultViewEntry> entries= getCurrentResults().iterator(); while (entries.hasNext()) { SearchResultViewEntry entry= entries.next(); if (entry.contains(marker)) return entry; } return null; } /** * Received a resource event. Since the delta could be created in a * separate thread this methods post the event into the viewer's * display thread. * @param event the event */ @Override public final void resourceChanged(final IResourceChangeEvent event) { if (event == null) return; final IMarkerDelta[] markerDeltas= event.findMarkerDeltas(SearchUI.SEARCH_MARKER, true); if (markerDeltas == null || markerDeltas.length < 1) return; Display display= getDisplay(); if (display == null || display.isDisposed()) return; Runnable runnable= new Runnable() { @Override public void run() { if (getCurrentSearch() != null) { handleSearchMarkersChanged(markerDeltas); // update title and actions Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) { SearchResultViewer viewer= iter.next(); viewer.enableActions(); viewer.updateTitle(); } } } }; display.syncExec(runnable); } /** * Find and return a valid display * @return the display */ private Display getDisplay() { Iterator<SearchResultViewer> iter= fListeners.iterator(); while (iter.hasNext()) { Control control= ((Viewer)iter.next()).getControl(); if (control != null && !control.isDisposed()) { Display display= control.getDisplay(); if (display != null && !display.isDisposed()) return display; } } return null; } /** * Find and return a valid shell * @return the shell */ private Shell getShell() { return SearchPlugin.getActiveWorkbenchShell(); } }