# HG changeset patch # User aghaisas # Date 1468406136 -19800 # Node ID 882e635693491bcd7eb1289cd4263fe171d3e486 # Parent 6178820cadaf0a062ce52a80dfd2f5296d31d155 6567433: JComponent.updateUI() may create StackOverflowError Reviewed-by: alexsch, rchamyal diff -r 6178820cadaf -r 882e63569349 jdk/src/java.desktop/share/classes/javax/swing/JComboBox.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JComboBox.java Wed Jul 13 12:24:24 2016 +0300 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JComboBox.java Wed Jul 13 16:05:36 2016 +0530 @@ -168,6 +168,9 @@ // Flag to ensure the we don't get multiple ActionEvents on item selection. private boolean selectingItem = false; + // Flag to indicate UI update is in progress + private transient boolean updateInProgress; + /** * Creates a JComboBox that takes its items from an * existing ComboBoxModel. Since the @@ -268,11 +271,18 @@ * @see JComponent#updateUI */ public void updateUI() { - setUI((ComboBoxUI)UIManager.getUI(this)); + if (!updateInProgress) { + updateInProgress = true; + try { + setUI((ComboBoxUI)UIManager.getUI(this)); - ListCellRenderer renderer = getRenderer(); - if (renderer instanceof Component) { - SwingUtilities.updateComponentTreeUI((Component)renderer); + ListCellRenderer renderer = getRenderer(); + if (renderer instanceof Component) { + SwingUtilities.updateComponentTreeUI((Component)renderer); + } + } finally { + updateInProgress = false; + } } } diff -r 6178820cadaf -r 882e63569349 jdk/src/java.desktop/share/classes/javax/swing/JList.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JList.java Wed Jul 13 12:24:24 2016 +0300 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JList.java Wed Jul 13 16:05:36 2016 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -338,6 +338,11 @@ private transient DropLocation dropLocation; /** + * Flag to indicate UI update is in progress + */ + private transient boolean updateInProgress; + + /** * A subclass of TransferHandler.DropLocation representing * a drop location for a JList. * @@ -531,11 +536,18 @@ * @see SwingUtilities#updateComponentTreeUI */ public void updateUI() { - setUI((ListUI)UIManager.getUI(this)); - - ListCellRenderer renderer = getCellRenderer(); - if (renderer instanceof Component) { - SwingUtilities.updateComponentTreeUI((Component)renderer); + if (!updateInProgress) { + updateInProgress = true; + try { + setUI((ListUI)UIManager.getUI(this)); + + ListCellRenderer renderer = getCellRenderer(); + if (renderer instanceof Component) { + SwingUtilities.updateComponentTreeUI((Component)renderer); + } + } finally { + updateInProgress = false; + } } } diff -r 6178820cadaf -r 882e63569349 jdk/src/java.desktop/share/classes/javax/swing/JTable.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Wed Jul 13 12:24:24 2016 +0300 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java Wed Jul 13 16:05:36 2016 +0530 @@ -455,6 +455,11 @@ private transient DropLocation dropLocation; /** + * Flag to indicate UI update is in progress + */ + private transient boolean updateInProgress; + + /** * A subclass of TransferHandler.DropLocation representing * a drop location for a JTable. * @@ -3621,36 +3626,46 @@ * @see JComponent#updateUI */ public void updateUI() { - // Update the UIs of the cell renderers, cell editors and header renderers. - TableColumnModel cm = getColumnModel(); - for(int column = 0; column < cm.getColumnCount(); column++) { - TableColumn aColumn = cm.getColumn(column); - SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer()); - SwingUtilities.updateRendererOrEditorUI(aColumn.getCellEditor()); - SwingUtilities.updateRendererOrEditorUI(aColumn.getHeaderRenderer()); - } - - // Update the UIs of all the default renderers. - Enumeration defaultRenderers = defaultRenderersByColumnClass.elements(); - while (defaultRenderers.hasMoreElements()) { - SwingUtilities.updateRendererOrEditorUI(defaultRenderers.nextElement()); - } - - // Update the UIs of all the default editors. - Enumeration defaultEditors = defaultEditorsByColumnClass.elements(); - while (defaultEditors.hasMoreElements()) { - SwingUtilities.updateRendererOrEditorUI(defaultEditors.nextElement()); - } - - // Update the UI of the table header - if (tableHeader != null && tableHeader.getParent() == null) { - tableHeader.updateUI(); - } - - // Update UI applied to parent ScrollPane - configureEnclosingScrollPaneUI(); - - setUI((TableUI)UIManager.getUI(this)); + if (updateInProgress) { + return; + } + + updateInProgress = true; + + try { + // Update the UIs of the cell renderers, cell editors and header renderers. + TableColumnModel cm = getColumnModel(); + for(int column = 0; column < cm.getColumnCount(); column++) { + TableColumn aColumn = cm.getColumn(column); + SwingUtilities.updateRendererOrEditorUI(aColumn.getCellRenderer()); + SwingUtilities.updateRendererOrEditorUI(aColumn.getCellEditor()); + SwingUtilities.updateRendererOrEditorUI(aColumn.getHeaderRenderer()); + } + + // Update the UIs of all the default renderers. + Enumeration defaultRenderers = defaultRenderersByColumnClass.elements(); + while (defaultRenderers.hasMoreElements()) { + SwingUtilities.updateRendererOrEditorUI(defaultRenderers.nextElement()); + } + + // Update the UIs of all the default editors. + Enumeration defaultEditors = defaultEditorsByColumnClass.elements(); + while (defaultEditors.hasMoreElements()) { + SwingUtilities.updateRendererOrEditorUI(defaultEditors.nextElement()); + } + + // Update the UI of the table header + if (tableHeader != null && tableHeader.getParent() == null) { + tableHeader.updateUI(); + } + + // Update UI applied to parent ScrollPane + configureEnclosingScrollPaneUI(); + + setUI((TableUI)UIManager.getUI(this)); + } finally { + updateInProgress = false; + } } /** diff -r 6178820cadaf -r 882e63569349 jdk/src/java.desktop/share/classes/javax/swing/JTree.java --- a/jdk/src/java.desktop/share/classes/javax/swing/JTree.java Wed Jul 13 12:24:24 2016 +0300 +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTree.java Wed Jul 13 16:05:36 2016 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -321,6 +321,11 @@ private transient DropLocation dropLocation; /** + * Flag to indicate UI update is in progress + */ + private transient boolean updateInProgress; + + /** * A subclass of TransferHandler.DropLocation representing * a drop location for a JTree. * @@ -713,10 +718,19 @@ * @see JComponent#updateUI */ public void updateUI() { - setUI((TreeUI)UIManager.getUI(this)); - - SwingUtilities.updateRendererOrEditorUI(getCellRenderer()); - SwingUtilities.updateRendererOrEditorUI(getCellEditor()); + if (!updateInProgress) { + + updateInProgress = true; + + try { + setUI((TreeUI)UIManager.getUI(this)); + + SwingUtilities.updateRendererOrEditorUI(getCellRenderer()); + SwingUtilities.updateRendererOrEditorUI(getCellEditor()); + } finally { + updateInProgress = false; + } + } } diff -r 6178820cadaf -r 882e63569349 jdk/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java --- a/jdk/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java Wed Jul 13 12:24:24 2016 +0300 +++ b/jdk/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java Wed Jul 13 16:05:36 2016 +0530 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,6 +118,11 @@ */ private TableCellRenderer defaultRenderer; + /** + * Flag to indicate UI update is in progress + */ + private transient boolean updateInProgress; + // // Constructors // @@ -475,11 +480,18 @@ * @see JComponent#updateUI */ public void updateUI(){ - setUI((TableHeaderUI)UIManager.getUI(this)); + if (!updateInProgress) { + updateInProgress = true; + try { + setUI((TableHeaderUI)UIManager.getUI(this)); - TableCellRenderer renderer = getDefaultRenderer(); - if (renderer instanceof Component) { - SwingUtilities.updateComponentTreeUI((Component)renderer); + TableCellRenderer renderer = getDefaultRenderer(); + if (renderer instanceof Component) { + SwingUtilities.updateComponentTreeUI((Component)renderer); + } + } finally { + updateInProgress = false; + } } } diff -r 6178820cadaf -r 882e63569349 jdk/test/javax/swing/JComboBox/6567433/UpdateUIRecursionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JComboBox/6567433/UpdateUIRecursionTest.java Wed Jul 13 16:05:36 2016 +0530 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6567433 + * + * @summary JComboBox.updateUI() invokes updateUI() on its cellrenderer via + * SwingUtilities.updateComponentTreeUI(). + * If the cellrenderer is a parent of this JComboBox the method recurses + * endless. + * This test tests that the fix is effective in avoiding recursion. + * + * @run main/othervm UpdateUIRecursionTest + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; + +public class UpdateUIRecursionTest extends JFrame implements ListCellRenderer { + JComboBox combo; + DefaultListCellRenderer renderer; + + public UpdateUIRecursionTest() { + super("UpdateUIRecursionTest"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(400, 400); + + String[] listData = { + "First", "Second", "Third", "Fourth", "Fifth", "Sixth" + }; + + combo = new JComboBox(listData); + combo.setRenderer(this); + renderer = new DefaultListCellRenderer(); + getContentPane().add(new JScrollPane(combo), BorderLayout.CENTER); + + setVisible(true); + } + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + UpdateUIRecursionTest obj = new UpdateUIRecursionTest(); + + obj.test(); + + obj.disposeUI(); + } + }); + } + + public void test() { + combo.updateUI(); + } + + public void disposeUI() { + setVisible(false); + dispose(); + } + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + return renderer.getListCellRendererComponent(list, value, index, + isSelected, cellHasFocus); + } +} + diff -r 6178820cadaf -r 882e63569349 jdk/test/javax/swing/JList/6567433/UpdateUIRecursionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JList/6567433/UpdateUIRecursionTest.java Wed Jul 13 16:05:36 2016 +0530 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6567433 + * + * @summary JList.updateUI() for invokes updateUI() on its cellrenderer via + * SwingUtilities.updateComponentTreeUI(). + * If the cellrenderer is a parent of this JList the method recurses + * endless. + * This test tests that the fix is effective in avoiding recursion. + * + * @run main/othervm UpdateUIRecursionTest + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JFrame; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.ListCellRenderer; +import javax.swing.SwingUtilities; + +public class UpdateUIRecursionTest extends JFrame implements ListCellRenderer { + JList list; + DefaultListCellRenderer renderer; + + public UpdateUIRecursionTest() { + super("UpdateUIRecursionTest"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(400, 400); + + String[] listData = { + "First", "Second", "Third", "Fourth", "Fifth", "Sixth" + }; + + list = new JList(listData); + list.setCellRenderer(this); + renderer = new DefaultListCellRenderer(); + getContentPane().add(new JScrollPane(list), BorderLayout.CENTER); + + setVisible(true); + } + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + UpdateUIRecursionTest obj = new UpdateUIRecursionTest(); + + obj.test(); + + obj.disposeUI(); + } + }); + } + + public void test() { + list.updateUI(); + } + + public void disposeUI() { + setVisible(false); + dispose(); + } + + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + return renderer.getListCellRendererComponent(list, value, index, + isSelected, cellHasFocus); + } +} + diff -r 6178820cadaf -r 882e63569349 jdk/test/javax/swing/JTable/6567433/UpdateUIRecursionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTable/6567433/UpdateUIRecursionTest.java Wed Jul 13 16:05:36 2016 +0530 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6567433 + * + * @summary JTable.updateUI() invokes updateUI() on its TableCellrenderer via + * SwingUtilities.updateRendererOrEditorUI(). + * If the TableCellrenderer is a parent of this JTable the method recurses + * endless. + * This test tests that the fix is effective in avoiding recursion. + * + * @run main/othervm UpdateUIRecursionTest + */ + + +import java.awt.BorderLayout; +import java.awt.Component; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; + +public class UpdateUIRecursionTest extends JFrame implements TableCellRenderer { + JTable table; + DefaultTableCellRenderer renderer; + + public UpdateUIRecursionTest() { + super("UpdateUIRecursionTest"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(400, 400); + + String[] columnNames = { + "First Name", + "Last Name", + "Sport", + "# of Years", + "Vegetarian"}; + + Object[][] data = { + {"Mary", "Campione", + "Snowboarding", new Integer(5), new Boolean(false)}, + {"Alison", "Huml", + "Rowing", new Integer(3), new Boolean(true)}, + {"Kathy", "Walrath", + "Knitting", new Integer(2), new Boolean(false)}, + {"Sharon", "Zakhour", + "Speed reading", new Integer(20), new Boolean(true)}, + {"Philip", "Milne", + "Pool", new Integer(10), new Boolean(false)} + }; + + + table = new JTable(data, columnNames); + + renderer = new DefaultTableCellRenderer(); + getContentPane().add(new JScrollPane(table), BorderLayout.CENTER); + table.setDefaultRenderer(table.getColumnClass(1), this); + + setVisible(true); + } + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + UpdateUIRecursionTest obj = new UpdateUIRecursionTest(); + + obj.test(); + + obj.disposeUI(); + } + }); + } + + public void test() { + table.updateUI(); + } + + public void disposeUI() { + setVisible(false); + dispose(); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, + int row, int column) + { + return renderer.getTableCellRendererComponent(table, value, isSelected, + hasFocus, row, column); + } +} diff -r 6178820cadaf -r 882e63569349 jdk/test/javax/swing/JTableHeader/6567433/UpdateUIRecursionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTableHeader/6567433/UpdateUIRecursionTest.java Wed Jul 13 16:05:36 2016 +0530 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6567433 + * + * @summary JTableHeader.updateUI() invokes updateUI() on its TableCellrenderer via + * SwingUtilities.updateComponentTreeUI(). + * If the Tablecellrenderer is a parent of this JTableHeader, the method recurses + * endless. + * This test tests that the fix is effective in avoiding recursion. + * + * @run main/othervm UpdateUIRecursionTest + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; + +public class UpdateUIRecursionTest extends JFrame implements TableCellRenderer { + JTable table; + + public UpdateUIRecursionTest() { + super("UpdateUIRecursionTest"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(400, 400); + + String[] columnNames = { + "First Name", + "Last Name", + "Sport", + "# of Years", + "Vegetarian"}; + + Object[][] data = { + {"Mary", "Campione", + "Snowboarding", new Integer(5), new Boolean(false)}, + {"Alison", "Huml", + "Rowing", new Integer(3), new Boolean(true)}, + {"Kathy", "Walrath", + "Knitting", new Integer(2), new Boolean(false)}, + {"Sharon", "Zakhour", + "Speed reading", new Integer(20), new Boolean(true)}, + {"Philip", "Milne", + "Pool", new Integer(10), new Boolean(false)} + }; + + JTableHeader tableHeader = new JTableHeader(); + table = new JTable(data, columnNames); + table.setTableHeader(tableHeader); + tableHeader.setDefaultRenderer(this); + + getContentPane().add(new JScrollPane(table), BorderLayout.CENTER); + + setVisible(true); + } + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + UpdateUIRecursionTest obj = new UpdateUIRecursionTest(); + + obj.test(); + + obj.disposeUI(); + } + }); + } + + public void test() { + SwingUtilities.updateComponentTreeUI(this); + } + + public void disposeUI() { + setVisible(false); + dispose(); + } + + public Component getTableCellRendererComponent(JTable table, Object value, + boolean isSelected, boolean hasFocus, int row, int col) { + return new JLabel(String.valueOf(value)); + } +} + + diff -r 6178820cadaf -r 882e63569349 jdk/test/javax/swing/JTree/6567433/UpdateUIRecursionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTree/6567433/UpdateUIRecursionTest.java Wed Jul 13 16:05:36 2016 +0530 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6567433 + * + * @summary JTree.updateUI() invokes updateUI() on its TreeCellrenderer via + * SwingUtilities.updateRendererOrEditorUI(). + * If the TreeCellrenderer is a parent of this JTree, the method recurses + * endless. + * This test tests that the fix is effective in avoiding recursion. + * + * @run main/othervm UpdateUIRecursionTest + */ + +import java.awt.BorderLayout; +import java.awt.Component; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.DefaultTreeCellRenderer; + +public class UpdateUIRecursionTest extends JFrame implements TreeCellRenderer { + JTree tree; + DefaultTreeCellRenderer renderer; + + public UpdateUIRecursionTest() { + super("UpdateUIRecursionTest"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(400, 400); + + String[] listData = { + "First", "Second", "Third", "Fourth", "Fifth", "Sixth" + }; + + tree = new JTree(listData); + renderer = new DefaultTreeCellRenderer(); + getContentPane().add(new JScrollPane(tree), BorderLayout.CENTER); + tree.setCellRenderer(this); + + setVisible(true); + } + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + UpdateUIRecursionTest obj = new UpdateUIRecursionTest(); + + obj.test(); + + obj.disposeUI(); + } + }); + } + + public void test() { + tree.updateUI(); + } + + public void disposeUI() { + setVisible(false); + dispose(); + } + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean selected, boolean expanded, boolean leaf, + int row, boolean hasFocus) + { + return renderer.getTreeCellRendererComponent(tree, value, leaf, + expanded, leaf, row, hasFocus); + } +}