Bug 87074 [Viewers] TableViewer and SWT.VIRTUAL: ArrayOutOfBoundsException in ConcurrentTableUpdator
[SWT and JFace from Eclipse 3.1 M5a] To reproduce, run the attached code, hit "END" to jump to the end of the table, and start navigating upwards with the up arrow. The first element in the viewable area will be blank; hitting ENTER on it causes the following: java.lang.ArrayIndexOutOfBoundsException: 179 at org.eclipse.jface.viewers.deferred.ConcurrentTableUpdator.updateTable(ConcurrentTableUpdator.java:362) at org.eclipse.jface.viewers.deferred.ConcurrentTableUpdator.checkVisibleRange(ConcurrentTableUpdator.java:289) at org.eclipse.jface.viewers.deferred.BackgroundContentProvider.checkVisibleRange(BackgroundContentProvider.java:442) at org.eclipse.jface.viewers.deferred.DeferredContentProvider.updateElement(DeferredContentProvider.java:198) at org.eclipse.jface.viewers.TableViewer$1.handleEvent(TableViewer.java:105) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:82) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:842) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:866) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:851) at org.eclipse.swt.widgets.Table.checkData(Table.java:195) at org.eclipse.swt.widgets.Table.wmNotifyChild(Table.java:3581) at org.eclipse.swt.widgets.Control.WM_NOTIFY(Control.java:3553) at org.eclipse.swt.widgets.Composite.WM_NOTIFY(Composite.java:994) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3075) at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1493) at org.eclipse.swt.widgets.Display.windowProc(Display.java:3480) at org.eclipse.swt.internal.win32.OS.CallWindowProcW(Native Method) at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:1543) at org.eclipse.swt.widgets.Table.callWindowProc(Table.java:173) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3109) at org.eclipse.swt.widgets.Display.windowProc(Display.java:3480) at org.eclipse.swt.internal.win32.OS.CallWindowProcW(Native Method) at org.eclipse.swt.internal.win32.OS.CallWindowProc(OS.java:1543) at org.eclipse.swt.widgets.Table.callWindowProc(Table.java:173) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3109) at org.eclipse.swt.widgets.Display.windowProc(Display.java:3480) at org.eclipse.swt.internal.win32.OS.SendMessageW(Native Method) at org.eclipse.swt.internal.win32.OS.SendMessage(OS.java:2184) at org.eclipse.swt.widgets.Table.setRedraw(Table.java:2492) at org.eclipse.jface.viewers.TableViewer.inputChanged(TableViewer.java:662) at org.eclipse.jface.viewers.ContentViewer.setInput(ContentViewer.java:248) at org.eclipse.jface.viewers.StructuredViewer.setInput(StructuredViewer.java:1323) at com.sdm.hw.client.swt.tests.DeferredContentProviderTest$1.widgetDefaultSelected(DeferredContentProviderTest.java:99) at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:96) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:82) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:842) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:2908) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2541) at org.eclipse.jface.window.Window.runEventLoop(Window.java:718) at org.eclipse.jface.window.Window.open(Window.java:696) at com.sdm.hw.client.swt.tests.DeferredContentProviderTest.main(DeferredContentProviderTest.java:67) The code in question: --- package com.sdm.hw.client.swt.tests; import java.util.Comparator; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.deferred.DeferredContentProvider; import org.eclipse.jface.viewers.deferred.SetModel; import org.eclipse.jface.window.ApplicationWindow; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; /** * Works with JFace 20050215-2100 and later. Won't compile with a version earlier than 20050125-0800. * @author sue */ public class DeferredContentProviderTest extends ApplicationWindow { private static final int HEIGHT = 200; private static final int WIDTH = 400; private class MyTableLabelProvider implements ITableLabelProvider { public void addListener(ILabelProviderListener listener) {} public void dispose() {} public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { return (String) element; } public boolean isLabelProperty(Object element, String property) { return false; } public void removeListener(ILabelProviderListener listener) {} } private class MyComparator implements Comparator { public int compare(Object o1, Object o2) { int i1 = Integer.parseInt(((String) o1).substring(8)); int i2 = Integer.parseInt(((String) o2).substring(8)); return i1-i2; } } private ITableLabelProvider labelProvider = new MyTableLabelProvider(); private IContentProvider contentProvider = new DeferredContentProvider(new MyComparator()); private SetModel model = new SetModel(); public static void main(String[] args) { System.out.println( "To recreate the ArrayIndexOutOfBounds bug:\n" + "- Press End to navigate to the end of the table\n" + "- Scroll upwards with the arrow keys; the element at the top of the visible area will be blank\n" + "- Press enter on the blank item to call viewer.setInput()\n" + "- Behaviour happens intermittently; scroll up and try a different element if the first one\n" + " doesn't immediately throw the exception."); new DeferredContentProviderTest().open(); } public DeferredContentProviderTest() { super(null); setBlockOnOpen(true); } protected void configureShell(Shell shell) { super.configureShell(shell); shell.setText("Virtual Table test program"); } protected Control createContents(Composite parent) { Table table = new Table(parent, SWT.VIRTUAL); TableColumn column = new TableColumn(table, SWT.NONE); column.setWidth(WIDTH); final TableViewer viewer = new TableViewer(table); viewer.setContentProvider(contentProvider); viewer.setLabelProvider(labelProvider); viewer.setInput(model); String[] string = new String[200]; for (int i=0; i<200; i++) { string[i] = "element#" + i; } model.addAll(string); table.addSelectionListener(new SelectionAdapter() { public void widgetDefaultSelected(SelectionEvent e) { System.out.println("calling viewer.setInput()"); viewer.setInput(model); } }); return table; } protected Point getInitialSize() { return new Point(WIDTH, HEIGHT); } }
bundles/org.eclipse.jface/src/org/eclipse/jface/viewers/deferred/BackgroundContentProvider.java
/**
	 * Sorting message string
	 */
    private static final String SORTING = JFaceResources.getString("Sorting"); 
    /**