From 3c76988e0308b7a337271030e5a2bda360e4bf70 Mon Sep 17 00:00:00 2001 From: asvitkine Date: Sun, 16 Jul 2023 21:39:01 -0400 Subject: [PATCH] Fix ArrayIndexOutOfBoundsException in CommentPanel. This a follow-up to my change that narrowed the scope of the lock in this code. We're now seeing node.getLastChild() throw an index out of bounds, even though it's directly after a size check. This is likely due to a race. Instead of reading the children off the actual history tree, this changes the code to instead get this info directly from the event, which is more correct as well. It should fix the issue. --- .../strategy/triplea/ui/CommentPanel.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/game-app/game-headed/src/main/java/games/strategy/triplea/ui/CommentPanel.java b/game-app/game-headed/src/main/java/games/strategy/triplea/ui/CommentPanel.java index 8bd306aa994..5098c4ab10b 100644 --- a/game-app/game-headed/src/main/java/games/strategy/triplea/ui/CommentPanel.java +++ b/game-app/game-headed/src/main/java/games/strategy/triplea/ui/CommentPanel.java @@ -42,6 +42,9 @@ @Slf4j class CommentPanel extends JPanel { private static final long serialVersionUID = -9122162393288045888L; + + private static final Pattern COMMENT_PATTERN = Pattern.compile("^COMMENT: (.*)"); + private JTextPane text; private JScrollPane scrollPane; private JTextField nextMessage; @@ -134,16 +137,17 @@ public void treeStructureChanged(final TreeModelEvent e) { private void readHistoryTreeEvent(final TreeModelEvent e) { SwingAction.invokeNowOrLater( () -> { - final Document doc = text.getDocument(); - final HistoryNode node = (HistoryNode) e.getTreePath().getLastPathComponent(); - final TreeNode child = - node == null ? null : (node.getChildCount() > 0 ? node.getLastChild() : null); - final String title = - child != null - ? (child instanceof Event ? ((Event) child).getDescription() : child.toString()) - : (node != null ? node.getTitle() : ""); - final Pattern p = Pattern.compile("^COMMENT: (.*)"); - final Matcher m = p.matcher(title); + final Object[] children = e.getChildren(); + final Object child = + (children != null && children.length > 0) ? children[children.length - 1] : null; + final String title; + if (child != null) { + title = (child instanceof Event) ? ((Event) child).getDescription() : child.toString(); + } else { + final HistoryNode node = (HistoryNode) e.getTreePath().getLastPathComponent(); + title = (node != null) ? node.getTitle() : ""; + } + final Matcher m = COMMENT_PATTERN.matcher(title); if (m.matches()) { final GamePlayer gamePlayer; final String player; @@ -156,6 +160,7 @@ private void readHistoryTreeEvent(final TreeModelEvent e) { final Icon icon = iconMap.get(gamePlayer); try { // insert into ui document + final Document doc = text.getDocument(); final String prefix = " " + player + "(" + round + ") : "; text.insertIcon(icon); doc.insertString(doc.getLength(), prefix, bold);