/*******************************************************************************
* Copyright (c) 2012 Wind River Systems 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.tcf.debug.test;
import java.util.Iterator;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceNotFoundElement;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.debug.ui.sourcelookup.CommonSourceNotFoundEditor;
import org.eclipse.debug.ui.sourcelookup.CommonSourceNotFoundEditorInput;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelListener;
import org.eclipse.tcf.services.ILineNumbers.CodeArea;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;
/**
*
*/
public class SourceDisplayListener implements IPartListener, IAnnotationModelListener {
private static final String ANNOTATION_TOP_FRAME = "org.eclipse.tcf.debug.top_frame";
private IWorkbenchPage fPage;
private IEditorPart fActiveEditor;
private IPath fExpectedFile;
private int fExpectedLine;
private boolean fFileFound = false;
private boolean fAnnotationFound = false;
private IAnnotationModel fAnnotationModel = null;
private int fTimeoutInterval = 60000;
private long fTimeoutTime;
public SourceDisplayListener() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
fPage = window.getActivePage();
fPage.addPartListener(this);
fPage.getWorkbenchWindow().getShell().getDisplay().asyncExec(new Runnable() {
public void run() {
partBroughtToTop(fPage.getActiveEditor());
}
});
}
public void dispose() {
if (fAnnotationModel != null) {
fAnnotationModel.removeAnnotationModelListener(this);
fAnnotationModel = null;
}
fPage.removePartListener(this);
}
public void reset() {
fFileFound = false;
fAnnotationFound = false;
fTimeoutTime = System.currentTimeMillis() + fTimeoutInterval;
}
public void setCodeArea(CodeArea area) {
fExpectedFile = new Path(area.file);
fExpectedLine = area.start_line;
checkFile();
}
public boolean isTimedOut() {
return fTimeoutInterval > 0 && fTimeoutTime < System.currentTimeMillis();
}
public void waitTillFinished() throws InterruptedException {
synchronized(this) {
while(!isFinished()) {
wait(100);
}
}
}
public synchronized boolean isFinished() {
if (isTimedOut()) {
throw new RuntimeException("Timed Out: " + toString());
}
return fFileFound && fAnnotationFound;
}
public void partActivated(IWorkbenchPart part) {
partBroughtToTop(part);
}
public void partBroughtToTop(IWorkbenchPart part) {
fActiveEditor = null;
if (fAnnotationModel != null) {
fAnnotationModel.removeAnnotationModelListener(this);
}
if (part instanceof IEditorPart) {
fActiveEditor = ((IEditorPart)part);
checkFile();
}
}
public void partClosed(IWorkbenchPart part) {
}
public void partDeactivated(IWorkbenchPart part) {
}
public void partOpened(IWorkbenchPart part) {
}
public void modelChanged(IAnnotationModel model) {
checkAnnotations();
}
private synchronized void checkFile() {
if (fActiveEditor == null) return;
IEditorInput input = fActiveEditor.getEditorInput();
IPath location = null;
if (input instanceof IFileEditorInput) {
IFile file = ((IFileEditorInput)input).getFile();
location = file.getLocation();
} else if (input instanceof FileStoreEditorInput) {
location = URIUtil.toPath(((FileStoreEditorInput)input).getURI());
} else if (input instanceof CommonSourceNotFoundEditorInput) {
Object artifact = ((CommonSourceNotFoundEditorInput)input).getArtifact();
if (artifact instanceof CSourceNotFoundElement) {
location = new Path( ((CSourceNotFoundElement)artifact).getFile() );
}
}
if (location != null && fExpectedFile != null &&
location.lastSegment().equals(fExpectedFile.lastSegment()))
{
fFileFound = true;
if (fActiveEditor instanceof ITextEditor) {
IDocumentProvider docProvider = ((ITextEditor)fActiveEditor).getDocumentProvider();
fAnnotationModel = docProvider.getAnnotationModel(fActiveEditor.getEditorInput());
fAnnotationModel.addAnnotationModelListener(this);
checkAnnotations();
} else if (fActiveEditor instanceof CommonSourceNotFoundEditor) {
// No annotation will be painted if source not found.
fAnnotationFound = true;
}
}
}
private synchronized void checkAnnotations() {
Position expectedPosition = calcExpectedPosition();
if (checkTopFrameAnnotation(expectedPosition)) {
fAnnotationFound = true;
}
}
private Position calcExpectedPosition() {
if (fActiveEditor instanceof ITextEditor) {
IDocument doc = ((ITextEditor)fActiveEditor).getDocumentProvider().getDocument(fActiveEditor.getEditorInput());
if (doc == null) return null;
try {
IRegion region = doc.getLineInformation(fExpectedLine - 1);
return new Position(region.getOffset(), region.getLength());
} catch (BadLocationException e) {
}
}
return null;
}
private boolean checkTopFrameAnnotation(Position pos) {
if (fAnnotationModel == null) return false;
for (Iterator<?> itr = fAnnotationModel.getAnnotationIterator(); itr.hasNext();) {
Annotation ann = (Annotation)itr.next();
if ( ANNOTATION_TOP_FRAME.equals(ann.getType()) ) {
// Compare requested line to annotation location.
if (pos.equals(fAnnotationModel.getPosition(ann))) {
return true;
}
}
}
return false;
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer("Source Display Listener");
buf.append("\n\t");
buf.append("fExpectedFile = ");
buf.append( fExpectedFile );
buf.append(" (found=");
buf.append(fFileFound);
buf.append(")");
buf.append("\n\t");
buf.append("fExpectedLine = ");
buf.append( fExpectedLine );
buf.append(" (found=");
buf.append(fAnnotationFound);
buf.append(")");
return buf.toString();
}
}