/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved. | |
*/ | |
package org.eclipse.search.internal.core.text; | |
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.InputStreamReader; | |
import java.io.Reader; | |
import java.io.StringReader; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.HashSet; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Set; | |
import org.eclipse.core.resources.IFile; | |
import org.eclipse.core.resources.IProject; | |
import org.eclipse.core.resources.IResource; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IProgressMonitor; | |
import org.eclipse.core.runtime.IStatus; | |
import org.eclipse.core.runtime.OperationCanceledException; | |
import org.eclipse.core.runtime.Platform; | |
import org.eclipse.core.runtime.Status; | |
import org.eclipse.ui.IEditorInput; | |
import org.eclipse.ui.IEditorPart; | |
import org.eclipse.ui.IFileEditorInput; | |
import org.eclipse.ui.IWorkbench; | |
import org.eclipse.ui.IWorkbenchPage; | |
import org.eclipse.ui.IWorkbenchWindow; | |
import org.eclipse.ui.texteditor.ITextEditor; | |
import org.eclipse.search.ui.SearchUI; | |
import org.eclipse.search.internal.core.ISearchScope; | |
import org.eclipse.search.internal.ui.SearchMessages; | |
import org.eclipse.search.internal.ui.SearchPlugin; | |
import org.eclipse.search.internal.ui.util.StringMatcher; | |
/** | |
* The visitor that does the actual work. | |
*/ | |
public class TextSearchVisitor extends TypedResourceVisitor { | |
protected static final int fgLF= '\n'; | |
protected static final int fgCR= '\r'; | |
private String fPattern; | |
private ISearchScope fScope; | |
private ITextSearchResultCollector fCollector; | |
private String fOptions; | |
private IEditorPart[] fDirtyEditors; | |
private IProgressMonitor fProgressMonitor; | |
private StringMatcher fMatcher; | |
private String fErrorMessage; | |
protected int fPushbackChar; | |
protected boolean fPushback; | |
public TextSearchVisitor(String pattern, String options, ISearchScope scope, ITextSearchResultCollector collector) | |
throws CoreException { | |
fPattern= pattern; | |
fScope= scope; | |
fCollector= collector; | |
fPushback= false; | |
if (options != null) | |
fOptions= options; | |
else | |
fOptions= ""; //$NON-NLS-1$ | |
fProgressMonitor= collector.getProgressMonitor(); | |
fMatcher= new StringMatcher(pattern, options.indexOf('i') != -1, false); | |
} | |
public void process(Collection projects) throws CoreException { | |
Iterator i= projects.iterator(); | |
while(i.hasNext()) { | |
IProject project= (IProject)i.next(); | |
project.accept(this); | |
} | |
} | |
/** | |
* Returns an array of all editors that have an unsaved content. If the identical content is | |
* presented in more than one editor, only one of those editor parts is part of the result. | |
* | |
* @return an array of all dirty editor parts. | |
*/ | |
private IEditorPart[] getDirtyEditors() { | |
Set inputs= new HashSet(7); | |
List result= new ArrayList(0); | |
IWorkbench workbench= SearchPlugin.getDefault().getWorkbench(); | |
IWorkbenchWindow[] windows= workbench.getWorkbenchWindows(); | |
for (int i= 0; i < windows.length; i++) { | |
IWorkbenchPage[] pages= windows[i].getPages(); | |
for (int x= 0; x < pages.length; x++) { | |
IEditorPart[] editors= pages[x].getEditors(); | |
for (int z= 0; z < editors.length; z++) { | |
IEditorPart editor= editors[z]; | |
IEditorInput input= editor.getEditorInput(); | |
if (editor.isDirty() && !inputs.contains(input)) { | |
inputs.add(input); | |
result.add(editor); | |
} | |
} | |
} | |
} | |
return (IEditorPart[])result.toArray(new IEditorPart[result.size()]); | |
} | |
protected boolean visitFile(IFile file) throws CoreException { | |
if (! fScope.encloses(file)) | |
return false; | |
try { | |
BufferedReader reader= null; | |
ITextEditor editor= findDirtyEditorFor(file); | |
if (editor != null) { | |
String s= editor.getDocumentProvider().getDocument(editor.getEditorInput()).get(); | |
reader= new BufferedReader(new StringReader(s)); | |
} else { | |
InputStream stream= file.getContents(false); | |
reader= new BufferedReader(new InputStreamReader(stream)); | |
} | |
StringBuffer sb= new StringBuffer(100); | |
int lineCounter= 1; | |
int charCounter=0; | |
boolean eof= false; | |
try { | |
while (!eof) { | |
int eolStrLength= readLine(reader, sb); | |
int lineLength= sb.length(); | |
int start= 0; | |
eof= eolStrLength == -1; | |
String line= sb.toString(); | |
StringMatcher.Position match; | |
while (start < lineLength) { | |
if ((match= fMatcher.find(line, start, lineLength)) != null) { | |
start= charCounter + match.getStart(); | |
int length= match.getEnd() - match.getStart(); | |
fCollector.accept(file, line.trim(), start, length, lineCounter); | |
start= match.getEnd(); | |
} | |
else // no match in this line | |
start= lineLength; | |
} | |
charCounter+= lineLength + eolStrLength; | |
lineCounter++; | |
} | |
} finally { | |
if (reader != null) | |
reader.close(); | |
} | |
} catch (IOException e) { | |
String message= SearchMessages.getFormattedString("TextSearchVisitor.error", file.getFullPath()); //$NON-NLS-1$ | |
throw new CoreException(new Status(IStatus.ERROR, SearchUI.PLUGIN_ID, Platform.PLUGIN_ERROR, message, e)); | |
} | |
finally { | |
fProgressMonitor.worked(1); | |
if (fProgressMonitor.isCanceled()) | |
throw new OperationCanceledException(SearchMessages.getString("TextSearchVisitor.canceled")); //$NON-NLS-1$ | |
} | |
return true; | |
} | |
private ITextEditor findDirtyEditorFor(IFile file) { | |
int i= 0; | |
while (i < fDirtyEditors.length) { | |
IEditorPart dirtyEditor= fDirtyEditors[i]; | |
IEditorInput input= dirtyEditor.getEditorInput(); | |
if (input instanceof IFileEditorInput && dirtyEditor instanceof ITextEditor) | |
if (((IFileEditorInput)input).getFile().equals(file)) | |
return (ITextEditor)dirtyEditor; | |
i++; | |
} | |
return null; | |
} | |
protected int readLine(BufferedReader reader, StringBuffer sb) throws IOException { | |
int ch= -1; | |
sb.setLength(0); | |
if (fPushback) { | |
ch= fPushbackChar; | |
fPushback= false; | |
} | |
else | |
ch= reader.read(); | |
while (ch >= 0) { | |
if (ch == fgLF) | |
return 1; | |
if (ch == fgCR) { | |
ch= reader.read(); | |
if (ch == fgLF) | |
return 2; | |
else { | |
fPushbackChar= ch; | |
fPushback= true; | |
return 1; | |
} | |
} | |
sb.append((char)ch); | |
ch= reader.read(); | |
} | |
return -1; | |
} | |
/* | |
* @see IResourceVisitor#visit(IResource) | |
*/ | |
public boolean visit(IResource resource) throws CoreException { | |
fDirtyEditors= getDirtyEditors(); | |
return super.visit(resource); | |
} | |
} | |