-
Bug
-
Resolution: Cannot Reproduce
-
P5
-
1.2.2, 1.3.0, 6
-
generic, x86, sparc
-
generic, other, solaris_2.6
JTable.editCellAt(-1,-1) should throw IllegalArgumentException not an ArrayIndexOutOfBoundsException: -1 < 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 < 0
at java.lang.Throwable.fillInStackTrace(Native Method)
at java.lang.Throwable.fillInStackTrace(Compiled Code)
at java.lang.Throwable.<init>(Compiled Code)
at java.lang.Exception.<init>(Compiled Code)
at java.lang.RuntimeException.<init>(RuntimeException.java:47)
at java.lang.IndexOutOfBoundsException.<init>(IndexOutOfBoundsException.java:44)
at java.lang.ArrayIndexOutOfBoundsException.<init>(ArrayIndexOutOfBoundsException.java:53)
at java.util.Vector.elementAt(Compiled Code)
at javax.swing.table.DefaultTableColumnModel.getColumn(Compiled Code)
at javax.swing.JTable.getCellEditor(JTable.java:2939)
at javax.swing.JTable.editCellAt(JTable.java:2024)
at javax.swing.JTable.editCellAt(JTable.java:1996)
at GetEditorComponent.main(GetEditorComponent.java:109
Testcase:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JTable;
import javax.swing.table.*;
public class GetEditorComponent extends JFrame {
static Object[][] data = {
{"Mary", "Campione",
"Snowboarding", new Integer(5), new Boolean(false)},
{"Alison", "Huml",
"Rowing", new Integer(3), new Boolean(true)},
{"Kathy", "Walrath",
"Chasing toddlers", new Integer(2), new Boolean(false)},
{"Mark", "Andrews",
"Speed reading", new Integer(20), new Boolean(true)},
{"Angela", "Lih",
"Teaching high school", new Integer(4), new Boolean(false)}
};
static String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
static final JTable table = new JTable(data, columnNames);
public GetEditorComponent() {
super("Table Tests");
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this window.
getContentPane().add(scrollPane, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args) {
GetEditorComponent frame = new GetEditorComponent();
boolean tests = true;
//System.out.println(((JTextField)table.getEditorComponent()).getText());
if (table.getEditorComponent() != null) {
System.out.println("Test 1: Failed!!");
System.out.println("Expected: null , Returned: "+table.getEditorComponent());
tests = false;
}
else {
System.out.println("Test 1: Passed!!");
}
table.editCellAt(1,1);
if (!(((JTextField)table.getEditorComponent()).getText().equals("Huml"))) {
System.out.println("Test 2: Failed!!");
System.out.println("Expected: Huml , Returned: "+((JTextField)table.getEditorComponent()).getText());
tests = false;
}
else {
System.out.println("Test 2: Passed!!");
}
try {
table.editCellAt(-1,-1);
} catch(ArrayIndexOutOfBoundsException ae) {
System.out.println("Test 3: This test Failed to throw an IllegalArgumentException");
ae.printStackTrace();
tests = false;
}
catch(IllegalArgumentException ie) {
System.out.println("Test 3: Passed!");
}
if(!tests)
System.exit(1);
else
System.exit(0);
}
}
Name: skT88420 Date: 12/20/99
java version "1.3beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3beta-0)
Java(TM) HotSpot Client VM (build 1.3beta-0, mixed mode)
use fireTableCellUpdated frome an AbstractTableModel and pass it to int's [its?]
this.fireTableCellUpdated(1,2);
java.lang.ArrayIndexOutOfBoundsException: -1 < 0
at java.util.Vector.elementAt<Vector.java:419>
at
javax.swing.table.DefaultTableColumnModel.getColumn<DefaultTableColumnModel.java
:267
at javax.swing.JTable.getCellRect<JTable.java:1780>
at javax.swing.JTable.tabelChanged<JTable.java:2549>
at
javax.swing.table.AbstractTableModel.fireTableCellUpdated<AbstractTableModel.jav
a:222>
at
javax.swing.table.AbstractTableModel.fireTableCellUpdated.<AbstractTableModel.ja
va:205>
(Review ID: 99171)
======================================================================
Suggested fix provided by java.net member leouser:
A DESCRIPTION OF THE FIX :
BUG ID: 4291560 JTable.editCellAt(-1,-1) should throw IllegalArgumentException not AIOB
JDK VERSION: jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
FILES AFFECTED: javax.swing.JTable
Discusion(embedded in test case as well):
/**
* BUG ID 4291560 JTable.editCellAt(-1,-1) should throw IllegalArgumentException not AIOB
* This bug no longer exists, in fact the editCellAt method returns false
* for these values, the issue has been resolved. But the spirit of the bug
* is still in place. The JTable is not described as a front end to an array,
* its a JTable! Several methods throw ArrayIndexOutOfBounds exceptions. This
* is the wrong exception to toss to any clients if they are misbehaving. Hence
* I have selected methods that take row,column arguments and applied tests to
* them. The client will get an IllegalArgumentException now instead of a AIOB
* exception. The message will be clear as to what went wrong as well. Actually
* the test includes not just < 0 but also that the value < then its repective
* dimensions size. It should be clear from now on what went wrong. This also
* hides the implementation from the client as well. They should not have
* to think in terms of the array when they get an Exception but in terms of
* the contract.
*
* ANTI-RATIONALE: it will slow down some operations as the test is conducted.
*
* TESTING STRATEGY:
* prove that < 0 values toss exceptions and values greater than the
* column's and row's sizes toss exceptions. Prove legal values do
* not toss exceptions.
*
* A NOTE ON WARNINGS:
* I have eliminted 10+ warnings from the compilation of the JTable. There
* are some like the UIDefaults being used for the Hashtable that probably
* cannont be eliminated while that class is employed. If we switched
* to just a Hashtable then we could probably generify it correctly and eliminate
* the warnings.
*
* JDK VERSION:
* jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
*
* FILE AFFECTED: javax.swing.JTable
* test ran succesfully on a SUSE 7.3 Linux distribution
*
* Brian Harry
* ###@###.###
* Wed Jan 11, 2006
*
*/
UNIFIED DIFF:
--- /home/nstuff/java6/jdk1.6.0/javax/swing/JTable.java Thu Dec 15 02:17:37 2005
+++ /home/javarefs/javax/swing/JTable.java Wed Jan 11 12:31:09 2006
@@ -183,6 +183,7 @@
//
// Static Constants
//
+ static final long serialVersionUID = -7636743696842802177L;
/**
* @see #getUIClassID
@@ -636,6 +637,7 @@
*/
public JTable(final Object[][] rowData, final Object[] columnNames) {
this(new AbstractTableModel() {
+ static final long serialVersionUID = 3489013428671730120L;
public String getColumnName(int column) { return columnNames[column].toString(); }
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
@@ -1678,9 +1680,9 @@
if (!forDrop && state != null) {
clearSelection();
- int[] rows = (int[])((int[][])state)[0];
- int[] cols = (int[])((int[][])state)[1];
- int[] anchleads = (int[])((int[][])state)[2];
+ int[] rows = ((int[][])state)[0];
+ int[] cols = ((int[][])state)[1];
+ int[] anchleads = ((int[][])state)[2];
for (int i = 0; i < rows.length; i++) {
addRowSelectionInterval(rows[i], rows[i]);
@@ -2259,8 +2261,12 @@
* @return true if <code>row</code> and <code>column</code> are valid indices
* and the cell at index <code>(row, column)</code> is selected,
* where the first row and first column are at index 0
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
*/
public boolean isCellSelected(int row, int column) {
+ checkRowColumn(row, column);
if (!getRowSelectionAllowed() && !getColumnSelectionAllowed()) {
return false;
}
@@ -2635,12 +2641,28 @@
* @param row the row whose value is to be queried
* @param column the column whose value is to be queried
* @return the Object at the specified cell
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
*/
public Object getValueAt(int row, int column) {
+ checkRowColumn(row, column);
return getModel().getValueAt(convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
+ private void checkRowColumn(int row, int column){
+ if (row < 0)
+ throw new IllegalArgumentException("row must have an index >= 0 was " + row);
+ else if(column < 0)
+ throw new IllegalArgumentException("column must have an index >= 0 was " + column);
+ else if(row >= getRowCount())
+ throw new IllegalArgumentException("row must be < getRowCount() was " + row);
+ else if(column >= getColumnCount())
+ throw new IllegalArgumentException("column must be < getColumnCount() was " + column);
+
+ }
+
/**
* Sets the value for the cell in the table model at <code>row</code>
* and <code>column</code>.
@@ -2658,9 +2680,13 @@
* @param aValue the new value
* @param row the row of the cell to be changed
* @param column the column of the cell to be changed
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see #getValueAt
*/
public void setValueAt(Object aValue, int row, int column) {
+ checkRowColumn(row, column);
getModel().setValueAt(aValue, convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
@@ -2682,9 +2708,13 @@
* @param row the row whose value is to be queried
* @param column the column whose value is to be queried
* @return true if the cell is editable
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see #setValueAt
*/
public boolean isCellEditable(int row, int column) {
+ checkRowColumn(row, column);
return getModel().isCellEditable(convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
@@ -5328,6 +5358,7 @@
* Default Renderers
**/
static class NumberRenderer extends DefaultTableCellRenderer.UIResource {
+ static final long serialVersionUID = 1060206325840761774L;
public NumberRenderer() {
super();
setHorizontalAlignment(JLabel.RIGHT);
@@ -5335,6 +5366,7 @@
}
static class DoubleRenderer extends NumberRenderer {
+ static final long serialVersionUID = 1674361569623087628L;
NumberFormat formatter;
public DoubleRenderer() { super(); }
@@ -5347,6 +5379,7 @@
}
static class DateRenderer extends DefaultTableCellRenderer.UIResource {
+ static final long serialVersionUID = 1127156928504609172L;
DateFormat formatter;
public DateRenderer() { super(); }
@@ -5359,6 +5392,7 @@
}
static class IconRenderer extends DefaultTableCellRenderer.UIResource {
+ static final long serialVersionUID = 1827488161207459271L;
public IconRenderer() {
super();
setHorizontalAlignment(JLabel.CENTER);
@@ -5369,6 +5403,7 @@
static class BooleanRenderer extends JCheckBox implements TableCellRenderer, UIResource
{
+ static final long serialVersionUID = -6514652581882111685L;
private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public BooleanRenderer() {
@@ -5424,7 +5459,7 @@
* Default Editors
*/
static class GenericEditor extends DefaultCellEditor {
-
+ static final long serialVersionUID = 1610870512073123683L;
Class[] argTypes = new Class[]{String.class};
java.lang.reflect.Constructor constructor;
Object value;
@@ -5487,13 +5522,14 @@
}
static class NumberEditor extends GenericEditor {
-
+ static final long serialVersionUID = -1513302533261375866L;
public NumberEditor() {
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
}
static class BooleanEditor extends DefaultCellEditor {
+ static final long serialVersionUID = 9146800834153813719L;
public BooleanEditor() {
super(new JCheckBox());
JCheckBox checkBox = (JCheckBox)getComponent();
@@ -5650,11 +5686,15 @@
* @return the assigned renderer; if <code>null</code>
* returns the default renderer
* for this type of object
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see javax.swing.table.DefaultTableCellRenderer
* @see javax.swing.table.TableColumn#setCellRenderer
* @see #setDefaultRenderer
*/
public TableCellRenderer getCellRenderer(int row, int column) {
+ checkRowColumn(row, column);
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null) {
@@ -5731,9 +5771,13 @@
* @return the editor for this cell;
* if <code>null</code> return the default editor for
* this type of cell
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see DefaultCellEditor
*/
public TableCellEditor getCellEditor(int row, int column) {
+ checkRowColumn(row, column);
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellEditor editor = tableColumn.getCellEditor();
if (editor == null) {
@@ -5766,7 +5810,8 @@
row, column);
if (comp instanceof JComponent) {
JComponent jComp = (JComponent)comp;
- if (jComp.getNextFocusableComponent() == null) {
+ FocusTraversalPolicy ftp = getFocusTraversalPolicy();
+ if ( ftp.getComponentAfter(getParent(), this) == null) {
jComp.setNextFocusableComponent(this);
}
}
@@ -6560,6 +6605,7 @@
implements AccessibleSelection, ListSelectionListener, TableModelListener,
TableColumnModelListener, CellEditorListener, PropertyChangeListener,
AccessibleExtendedTable {
+ static final long serialVersionUID = -1960919093900809477L;
int lastSelectedRow;
int lastSelectedCol;
@@ -8623,7 +8669,7 @@
} else {
Component c = getCurrentComponent();
if (c != null) {
- return c.isFocusTraversable();
+ return c.isFocusable();
} else {
return false;
}
@@ -9475,7 +9521,7 @@
} else {
Component c = getCurrentComponent();
if (c != null) {
- return c.isFocusTraversable();
+ return c.isFocusable();
} else {
return false;
}
JUnit TESTCASE :
import junit.framework.TestCase;
import junit.textui.TestRunner;
import static java.lang.System.out;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;
/**
* BUG ID 4291560 JTable.editCellAt(-1,-1) should throw IllegalArgumentException not AIOB
* This bug no longer exists, in fact the editCellAt method returns false
* for these values, the issue has been resolved. But the spirit of the bug
* is still in place. The JTable is not described as a front end to an array,
* its a JTable! Several methods throw ArrayIndexOutOfBounds exceptions. This
* is the wrong exception to toss to any clients if they are misbehaving. Hence
* I have selected methods that take row,column arguments and applied tests to
* them. The client will get an IllegalArgumentException now instead of a AIOB
* exception. The message will be clear as to what went wrong as well. Actually
* the test includes not just < 0 but also that the value < then its repective
* dimensions size. It should be clear from now on what went wrong. This also
* hides the implementation from the client as well. They should not have
* to think in terms of the array when they get an Exception but in terms of
* the contract.
*
* ANTI-RATIONALE: it will slow down some operations as the test is conducted.
*
* TESTING STRATEGY:
* prove that < 0 values toss exceptions and values greater than the
* column's and row's sizes toss exceptions. Prove legal values do
* not toss exceptions.
*
* A NOTE ON WARNINGS:
* I have eliminted 10+ warnings from the compilation of the JTable. There
* are some like the UIDefaults being used for the Hashtable that probably
* cannont be eliminated while that class is employed. If we switched
* to just a Hashtable then we could probably generify it correctly and eliminate
* the warnings.
*
* JDK VERSION:
* jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
*
* FILE AFFECTED: javax.swing.JTable
* test ran succesfully on a SUSE 7.3 Linux distribution
*
* Brian Harry
* ###@###.###
* Wed Jan 11, 2006
*
*/
public class TestTable extends TestCase{
public TestTable(String method){
super(method);
}
public void testTable(){
out.println();
out.println("Testing Illegal indices for JTable...");
Vector<Vector<Integer>> v = new Vector<Vector<Integer>>();
for(int i = 0; i < 10; i++){
Vector<Integer> v2 = new Vector<Integer>();
for(int j = 0; j < 10; j++)
v2.add(j);
v.add(v2);
}
Vector<String> names = new Vector<String>();
for(int i = 0; i < 10; i ++)
names.add(String.valueOf(i));
DefaultTableModel dtm = new DefaultTableModel(v,names );
JTable jt = new JTable(dtm);
try{
jt.setValueAt(100,-1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for -1, -1 setValueAt as planned");
}
try{
jt.setValueAt(100,20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 setValueAt as planned");
}
try{
jt.isCellEditable(1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 1, -1 isCellEditable as planned");
}
try{
jt.isCellEditable(20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 isCellEditable as planned");
}
try{
jt.getCellRenderer(-1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for -1, -1 getCellRenderer as planned");
}
try{
jt.getCellRenderer(20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 getCellRenderer as planned");
}
try{
jt.getCellEditor(-1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for -1, -1 getCellEditor as planned");
}
try{
jt.getCellEditor(20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 getCellEditor as planned");
}
try{
jt.getValueAt(-1,-1);
}
[too long to put here...truncated...]
refer to attached file 623943.txt for the rest
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1 < 0
at java.lang.Throwable.fillInStackTrace(Native Method)
at java.lang.Throwable.fillInStackTrace(Compiled Code)
at java.lang.Throwable.<init>(Compiled Code)
at java.lang.Exception.<init>(Compiled Code)
at java.lang.RuntimeException.<init>(RuntimeException.java:47)
at java.lang.IndexOutOfBoundsException.<init>(IndexOutOfBoundsException.java:44)
at java.lang.ArrayIndexOutOfBoundsException.<init>(ArrayIndexOutOfBoundsException.java:53)
at java.util.Vector.elementAt(Compiled Code)
at javax.swing.table.DefaultTableColumnModel.getColumn(Compiled Code)
at javax.swing.JTable.getCellEditor(JTable.java:2939)
at javax.swing.JTable.editCellAt(JTable.java:2024)
at javax.swing.JTable.editCellAt(JTable.java:1996)
at GetEditorComponent.main(GetEditorComponent.java:109
Testcase:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JTable;
import javax.swing.table.*;
public class GetEditorComponent extends JFrame {
static Object[][] data = {
{"Mary", "Campione",
"Snowboarding", new Integer(5), new Boolean(false)},
{"Alison", "Huml",
"Rowing", new Integer(3), new Boolean(true)},
{"Kathy", "Walrath",
"Chasing toddlers", new Integer(2), new Boolean(false)},
{"Mark", "Andrews",
"Speed reading", new Integer(20), new Boolean(true)},
{"Angela", "Lih",
"Teaching high school", new Integer(4), new Boolean(false)}
};
static String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};
static final JTable table = new JTable(data, columnNames);
public GetEditorComponent() {
super("Table Tests");
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this window.
getContentPane().add(scrollPane, BorderLayout.CENTER);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static void main(String[] args) {
GetEditorComponent frame = new GetEditorComponent();
boolean tests = true;
//System.out.println(((JTextField)table.getEditorComponent()).getText());
if (table.getEditorComponent() != null) {
System.out.println("Test 1: Failed!!");
System.out.println("Expected: null , Returned: "+table.getEditorComponent());
tests = false;
}
else {
System.out.println("Test 1: Passed!!");
}
table.editCellAt(1,1);
if (!(((JTextField)table.getEditorComponent()).getText().equals("Huml"))) {
System.out.println("Test 2: Failed!!");
System.out.println("Expected: Huml , Returned: "+((JTextField)table.getEditorComponent()).getText());
tests = false;
}
else {
System.out.println("Test 2: Passed!!");
}
try {
table.editCellAt(-1,-1);
} catch(ArrayIndexOutOfBoundsException ae) {
System.out.println("Test 3: This test Failed to throw an IllegalArgumentException");
ae.printStackTrace();
tests = false;
}
catch(IllegalArgumentException ie) {
System.out.println("Test 3: Passed!");
}
if(!tests)
System.exit(1);
else
System.exit(0);
}
}
Name: skT88420 Date: 12/20/99
java version "1.3beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3beta-0)
Java(TM) HotSpot Client VM (build 1.3beta-0, mixed mode)
use fireTableCellUpdated frome an AbstractTableModel and pass it to int's [its?]
this.fireTableCellUpdated(1,2);
java.lang.ArrayIndexOutOfBoundsException: -1 < 0
at java.util.Vector.elementAt<Vector.java:419>
at
javax.swing.table.DefaultTableColumnModel.getColumn<DefaultTableColumnModel.java
:267
at javax.swing.JTable.getCellRect<JTable.java:1780>
at javax.swing.JTable.tabelChanged<JTable.java:2549>
at
javax.swing.table.AbstractTableModel.fireTableCellUpdated<AbstractTableModel.jav
a:222>
at
javax.swing.table.AbstractTableModel.fireTableCellUpdated.<AbstractTableModel.ja
va:205>
(Review ID: 99171)
======================================================================
Suggested fix provided by java.net member leouser:
A DESCRIPTION OF THE FIX :
BUG ID: 4291560 JTable.editCellAt(-1,-1) should throw IllegalArgumentException not AIOB
JDK VERSION: jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
FILES AFFECTED: javax.swing.JTable
Discusion(embedded in test case as well):
/**
* BUG ID 4291560 JTable.editCellAt(-1,-1) should throw IllegalArgumentException not AIOB
* This bug no longer exists, in fact the editCellAt method returns false
* for these values, the issue has been resolved. But the spirit of the bug
* is still in place. The JTable is not described as a front end to an array,
* its a JTable! Several methods throw ArrayIndexOutOfBounds exceptions. This
* is the wrong exception to toss to any clients if they are misbehaving. Hence
* I have selected methods that take row,column arguments and applied tests to
* them. The client will get an IllegalArgumentException now instead of a AIOB
* exception. The message will be clear as to what went wrong as well. Actually
* the test includes not just < 0 but also that the value < then its repective
* dimensions size. It should be clear from now on what went wrong. This also
* hides the implementation from the client as well. They should not have
* to think in terms of the array when they get an Exception but in terms of
* the contract.
*
* ANTI-RATIONALE: it will slow down some operations as the test is conducted.
*
* TESTING STRATEGY:
* prove that < 0 values toss exceptions and values greater than the
* column's and row's sizes toss exceptions. Prove legal values do
* not toss exceptions.
*
* A NOTE ON WARNINGS:
* I have eliminted 10+ warnings from the compilation of the JTable. There
* are some like the UIDefaults being used for the Hashtable that probably
* cannont be eliminated while that class is employed. If we switched
* to just a Hashtable then we could probably generify it correctly and eliminate
* the warnings.
*
* JDK VERSION:
* jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
*
* FILE AFFECTED: javax.swing.JTable
* test ran succesfully on a SUSE 7.3 Linux distribution
*
* Brian Harry
* ###@###.###
* Wed Jan 11, 2006
*
*/
UNIFIED DIFF:
--- /home/nstuff/java6/jdk1.6.0/javax/swing/JTable.java Thu Dec 15 02:17:37 2005
+++ /home/javarefs/javax/swing/JTable.java Wed Jan 11 12:31:09 2006
@@ -183,6 +183,7 @@
//
// Static Constants
//
+ static final long serialVersionUID = -7636743696842802177L;
/**
* @see #getUIClassID
@@ -636,6 +637,7 @@
*/
public JTable(final Object[][] rowData, final Object[] columnNames) {
this(new AbstractTableModel() {
+ static final long serialVersionUID = 3489013428671730120L;
public String getColumnName(int column) { return columnNames[column].toString(); }
public int getRowCount() { return rowData.length; }
public int getColumnCount() { return columnNames.length; }
@@ -1678,9 +1680,9 @@
if (!forDrop && state != null) {
clearSelection();
- int[] rows = (int[])((int[][])state)[0];
- int[] cols = (int[])((int[][])state)[1];
- int[] anchleads = (int[])((int[][])state)[2];
+ int[] rows = ((int[][])state)[0];
+ int[] cols = ((int[][])state)[1];
+ int[] anchleads = ((int[][])state)[2];
for (int i = 0; i < rows.length; i++) {
addRowSelectionInterval(rows[i], rows[i]);
@@ -2259,8 +2261,12 @@
* @return true if <code>row</code> and <code>column</code> are valid indices
* and the cell at index <code>(row, column)</code> is selected,
* where the first row and first column are at index 0
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
*/
public boolean isCellSelected(int row, int column) {
+ checkRowColumn(row, column);
if (!getRowSelectionAllowed() && !getColumnSelectionAllowed()) {
return false;
}
@@ -2635,12 +2641,28 @@
* @param row the row whose value is to be queried
* @param column the column whose value is to be queried
* @return the Object at the specified cell
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
*/
public Object getValueAt(int row, int column) {
+ checkRowColumn(row, column);
return getModel().getValueAt(convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
+ private void checkRowColumn(int row, int column){
+ if (row < 0)
+ throw new IllegalArgumentException("row must have an index >= 0 was " + row);
+ else if(column < 0)
+ throw new IllegalArgumentException("column must have an index >= 0 was " + column);
+ else if(row >= getRowCount())
+ throw new IllegalArgumentException("row must be < getRowCount() was " + row);
+ else if(column >= getColumnCount())
+ throw new IllegalArgumentException("column must be < getColumnCount() was " + column);
+
+ }
+
/**
* Sets the value for the cell in the table model at <code>row</code>
* and <code>column</code>.
@@ -2658,9 +2680,13 @@
* @param aValue the new value
* @param row the row of the cell to be changed
* @param column the column of the cell to be changed
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see #getValueAt
*/
public void setValueAt(Object aValue, int row, int column) {
+ checkRowColumn(row, column);
getModel().setValueAt(aValue, convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
@@ -2682,9 +2708,13 @@
* @param row the row whose value is to be queried
* @param column the column whose value is to be queried
* @return true if the cell is editable
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see #setValueAt
*/
public boolean isCellEditable(int row, int column) {
+ checkRowColumn(row, column);
return getModel().isCellEditable(convertRowIndexToModel(row),
convertColumnIndexToModel(column));
}
@@ -5328,6 +5358,7 @@
* Default Renderers
**/
static class NumberRenderer extends DefaultTableCellRenderer.UIResource {
+ static final long serialVersionUID = 1060206325840761774L;
public NumberRenderer() {
super();
setHorizontalAlignment(JLabel.RIGHT);
@@ -5335,6 +5366,7 @@
}
static class DoubleRenderer extends NumberRenderer {
+ static final long serialVersionUID = 1674361569623087628L;
NumberFormat formatter;
public DoubleRenderer() { super(); }
@@ -5347,6 +5379,7 @@
}
static class DateRenderer extends DefaultTableCellRenderer.UIResource {
+ static final long serialVersionUID = 1127156928504609172L;
DateFormat formatter;
public DateRenderer() { super(); }
@@ -5359,6 +5392,7 @@
}
static class IconRenderer extends DefaultTableCellRenderer.UIResource {
+ static final long serialVersionUID = 1827488161207459271L;
public IconRenderer() {
super();
setHorizontalAlignment(JLabel.CENTER);
@@ -5369,6 +5403,7 @@
static class BooleanRenderer extends JCheckBox implements TableCellRenderer, UIResource
{
+ static final long serialVersionUID = -6514652581882111685L;
private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public BooleanRenderer() {
@@ -5424,7 +5459,7 @@
* Default Editors
*/
static class GenericEditor extends DefaultCellEditor {
-
+ static final long serialVersionUID = 1610870512073123683L;
Class[] argTypes = new Class[]{String.class};
java.lang.reflect.Constructor constructor;
Object value;
@@ -5487,13 +5522,14 @@
}
static class NumberEditor extends GenericEditor {
-
+ static final long serialVersionUID = -1513302533261375866L;
public NumberEditor() {
((JTextField)getComponent()).setHorizontalAlignment(JTextField.RIGHT);
}
}
static class BooleanEditor extends DefaultCellEditor {
+ static final long serialVersionUID = 9146800834153813719L;
public BooleanEditor() {
super(new JCheckBox());
JCheckBox checkBox = (JCheckBox)getComponent();
@@ -5650,11 +5686,15 @@
* @return the assigned renderer; if <code>null</code>
* returns the default renderer
* for this type of object
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see javax.swing.table.DefaultTableCellRenderer
* @see javax.swing.table.TableColumn#setCellRenderer
* @see #setDefaultRenderer
*/
public TableCellRenderer getCellRenderer(int row, int column) {
+ checkRowColumn(row, column);
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null) {
@@ -5731,9 +5771,13 @@
* @return the editor for this cell;
* if <code>null</code> return the default editor for
* this type of cell
+ * @throws IllegalArgumentException if the row or column is < 0.
+ * It is also thrown if the row is greater than its size
+ * or the column is greater than its size.
* @see DefaultCellEditor
*/
public TableCellEditor getCellEditor(int row, int column) {
+ checkRowColumn(row, column);
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellEditor editor = tableColumn.getCellEditor();
if (editor == null) {
@@ -5766,7 +5810,8 @@
row, column);
if (comp instanceof JComponent) {
JComponent jComp = (JComponent)comp;
- if (jComp.getNextFocusableComponent() == null) {
+ FocusTraversalPolicy ftp = getFocusTraversalPolicy();
+ if ( ftp.getComponentAfter(getParent(), this) == null) {
jComp.setNextFocusableComponent(this);
}
}
@@ -6560,6 +6605,7 @@
implements AccessibleSelection, ListSelectionListener, TableModelListener,
TableColumnModelListener, CellEditorListener, PropertyChangeListener,
AccessibleExtendedTable {
+ static final long serialVersionUID = -1960919093900809477L;
int lastSelectedRow;
int lastSelectedCol;
@@ -8623,7 +8669,7 @@
} else {
Component c = getCurrentComponent();
if (c != null) {
- return c.isFocusTraversable();
+ return c.isFocusable();
} else {
return false;
}
@@ -9475,7 +9521,7 @@
} else {
Component c = getCurrentComponent();
if (c != null) {
- return c.isFocusTraversable();
+ return c.isFocusable();
} else {
return false;
}
JUnit TESTCASE :
import junit.framework.TestCase;
import junit.textui.TestRunner;
import static java.lang.System.out;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;
/**
* BUG ID 4291560 JTable.editCellAt(-1,-1) should throw IllegalArgumentException not AIOB
* This bug no longer exists, in fact the editCellAt method returns false
* for these values, the issue has been resolved. But the spirit of the bug
* is still in place. The JTable is not described as a front end to an array,
* its a JTable! Several methods throw ArrayIndexOutOfBounds exceptions. This
* is the wrong exception to toss to any clients if they are misbehaving. Hence
* I have selected methods that take row,column arguments and applied tests to
* them. The client will get an IllegalArgumentException now instead of a AIOB
* exception. The message will be clear as to what went wrong as well. Actually
* the test includes not just < 0 but also that the value < then its repective
* dimensions size. It should be clear from now on what went wrong. This also
* hides the implementation from the client as well. They should not have
* to think in terms of the array when they get an Exception but in terms of
* the contract.
*
* ANTI-RATIONALE: it will slow down some operations as the test is conducted.
*
* TESTING STRATEGY:
* prove that < 0 values toss exceptions and values greater than the
* column's and row's sizes toss exceptions. Prove legal values do
* not toss exceptions.
*
* A NOTE ON WARNINGS:
* I have eliminted 10+ warnings from the compilation of the JTable. There
* are some like the UIDefaults being used for the Hashtable that probably
* cannont be eliminated while that class is employed. If we switched
* to just a Hashtable then we could probably generify it correctly and eliminate
* the warnings.
*
* JDK VERSION:
* jdk-6-rc-bin-b64-linux-i586-15_dec_2005.bin
*
* FILE AFFECTED: javax.swing.JTable
* test ran succesfully on a SUSE 7.3 Linux distribution
*
* Brian Harry
* ###@###.###
* Wed Jan 11, 2006
*
*/
public class TestTable extends TestCase{
public TestTable(String method){
super(method);
}
public void testTable(){
out.println();
out.println("Testing Illegal indices for JTable...");
Vector<Vector<Integer>> v = new Vector<Vector<Integer>>();
for(int i = 0; i < 10; i++){
Vector<Integer> v2 = new Vector<Integer>();
for(int j = 0; j < 10; j++)
v2.add(j);
v.add(v2);
}
Vector<String> names = new Vector<String>();
for(int i = 0; i < 10; i ++)
names.add(String.valueOf(i));
DefaultTableModel dtm = new DefaultTableModel(v,names );
JTable jt = new JTable(dtm);
try{
jt.setValueAt(100,-1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for -1, -1 setValueAt as planned");
}
try{
jt.setValueAt(100,20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 setValueAt as planned");
}
try{
jt.isCellEditable(1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 1, -1 isCellEditable as planned");
}
try{
jt.isCellEditable(20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 isCellEditable as planned");
}
try{
jt.getCellRenderer(-1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for -1, -1 getCellRenderer as planned");
}
try{
jt.getCellRenderer(20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 getCellRenderer as planned");
}
try{
jt.getCellEditor(-1,-1);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for -1, -1 getCellEditor as planned");
}
try{
jt.getCellEditor(20,20);
}
catch(IllegalArgumentException x){
out.println( "Thrown IllegalArgumentException for 20, 20 getCellEditor as planned");
}
try{
jt.getValueAt(-1,-1);
}
[too long to put here...truncated...]
refer to attached file 623943.txt for the rest