Skip to content
This repository was archived by the owner on Sep 2, 2022. It is now read-only.

Commit 7afb01d

Browse files
committed
8258373: Update the text handling in the JPasswordField
Reviewed-by: kizune, prr, psadhukhan
1 parent cbc3fee commit 7afb01d

File tree

7 files changed

+393
-1
lines changed

7 files changed

+393
-1
lines changed

src/java.desktop/share/classes/javax/swing/JPasswordField.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,30 @@ public String getText(int offs, int len) throws BadLocationException {
280280
return super.getText(offs, len);
281281
}
282282

283+
@Override
284+
@BeanProperty(bound = false, description = "the text of this component")
285+
public void setText(String t) {
286+
// overwrite the old data first
287+
Document doc = getDocument();
288+
int nleft = doc.getLength();
289+
Segment text = new Segment();
290+
// we would like to get direct data array access, not a copy of it
291+
text.setPartialReturn(true);
292+
int offs = 0;
293+
try {
294+
while (nleft > 0) {
295+
doc.getText(offs, nleft, text);
296+
Arrays.fill(text.array, text.offset,
297+
text.count + text.offset, '\u0000');
298+
nleft -= text.count;
299+
offs += text.count;
300+
}
301+
} catch (BadLocationException ignored) {
302+
// we tried
303+
}
304+
super.setText(t);
305+
}
306+
283307
/**
284308
* Returns the text contained in this <code>TextComponent</code>.
285309
* If the underlying document is <code>null</code>, will give a

src/java.desktop/share/classes/javax/swing/text/GapContent.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package javax.swing.text;
2626

27+
import java.util.Arrays;
2728
import java.util.Vector;
2829
import java.io.IOException;
2930
import java.io.ObjectInputStream;
@@ -103,6 +104,12 @@ protected int getArrayLength() {
103104
return carray.length;
104105
}
105106

107+
@Override
108+
void resize(int nsize) {
109+
char[] carray = (char[]) getArray();
110+
super.resize(nsize);
111+
Arrays.fill(carray, '\u0000');
112+
}
106113
// --- AbstractDocument.Content methods -------------------------
107114

108115
/**
@@ -195,23 +202,27 @@ public void getChars(int where, int len, Segment chars) throws BadLocationExcept
195202
if ((where + len) <= g0) {
196203
// below gap
197204
chars.array = array;
205+
chars.copy = false;
198206
chars.offset = where;
199207
} else if (where >= g0) {
200208
// above gap
201209
chars.array = array;
210+
chars.copy = false;
202211
chars.offset = g1 + where - g0;
203212
} else {
204213
// spans the gap
205214
int before = g0 - where;
206215
if (chars.isPartialReturn()) {
207216
// partial return allowed, return amount before the gap
208217
chars.array = array;
218+
chars.copy = false;
209219
chars.offset = where;
210220
chars.count = before;
211221
return;
212222
}
213223
// partial return not allowed, must copy
214224
chars.array = new char[len];
225+
chars.copy = true;
215226
chars.offset = 0;
216227
System.arraycopy(array, where, chars.array, 0, before);
217228
System.arraycopy(array, g1, chars.array, before, len - before);

src/java.desktop/share/classes/javax/swing/text/Segment.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,11 @@ public class Segment implements Cloneable, CharacterIterator, CharSequence {
6161
*/
6262
public int count;
6363

64+
/**
65+
* Whether the array is a copy of data or not.
66+
*/
67+
boolean copy;
68+
6469
private boolean partialReturn;
6570

6671
/**

src/java.desktop/share/classes/javax/swing/text/SegmentCache.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package javax.swing.text;
2626

2727
import java.util.ArrayList;
28+
import java.util.Arrays;
2829
import java.util.List;
2930

3031
/**
@@ -110,7 +111,11 @@ public Segment getSegment() {
110111
public void releaseSegment(Segment segment) {
111112
if (segment instanceof CachedSegment) {
112113
synchronized(this) {
114+
if (segment.copy) {
115+
Arrays.fill(segment.array, '\u0000');
116+
}
113117
segment.array = null;
118+
segment.copy = false;
114119
segment.count = 0;
115120
segments.add(segment);
116121
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.awt.EventQueue;
25+
import java.util.Arrays;
26+
import java.util.concurrent.atomic.AtomicInteger;
27+
28+
import javax.swing.JPasswordField;
29+
import javax.swing.event.DocumentEvent;
30+
import javax.swing.event.DocumentListener;
31+
32+
/**
33+
* @test
34+
* @bug 8258373
35+
*/
36+
public final class CheckCommonUseCases {
37+
38+
public static void main(String[] args) throws Exception {
39+
EventQueue.invokeAndWait(() -> {
40+
JPasswordField pf = new JPasswordField();
41+
// check that pf work if the new text is longer/shorter than the old
42+
checkDifferentTextLength(pf);
43+
// count the listeners called by the setText();
44+
countListeners(pf);
45+
});
46+
}
47+
48+
private static void countListeners(JPasswordField pf) {
49+
AtomicInteger insert = new AtomicInteger();
50+
AtomicInteger update = new AtomicInteger();
51+
AtomicInteger remove = new AtomicInteger();
52+
pf.getDocument().addDocumentListener(new DocumentListener() {
53+
@Override
54+
public void insertUpdate(DocumentEvent e) {
55+
insert.incrementAndGet();
56+
System.err.println("e = " + e);
57+
}
58+
59+
@Override
60+
public void removeUpdate(DocumentEvent e) {
61+
remove.incrementAndGet();
62+
System.err.println("e = " + e);
63+
}
64+
65+
@Override
66+
public void changedUpdate(DocumentEvent e) {
67+
update.incrementAndGet();
68+
System.err.println("e = " + e);
69+
}
70+
});
71+
// set the new text
72+
pf.setText("aaa");
73+
if (remove.get() != 0 || update.get() != 0 || insert.get() > 1) {
74+
System.err.println("remove = " + remove);
75+
System.err.println("update = " + update);
76+
System.err.println("insert = " + insert);
77+
throw new RuntimeException("Unexpected number of listeners");
78+
}
79+
insert.set(0);
80+
update.set(0);
81+
remove.set(0);
82+
83+
// replace the old text
84+
pf.setText("bbb");
85+
if (remove.get() > 1 || update.get() > 1 || insert.get() > 1) {
86+
System.err.println("remove = " + remove);
87+
System.err.println("update = " + update);
88+
System.err.println("insert = " + insert);
89+
throw new RuntimeException("Unexpected number of listeners");
90+
}
91+
insert.set(0);
92+
update.set(0);
93+
remove.set(0);
94+
95+
// remove the text
96+
pf.setText("");
97+
if (remove.get() > 1 || update.get() > 0 || insert.get() > 0) {
98+
System.err.println("remove = " + remove);
99+
System.err.println("update = " + update);
100+
System.err.println("insert = " + insert);
101+
throw new RuntimeException("Unexpected number of listeners");
102+
}
103+
}
104+
105+
private static void checkDifferentTextLength(JPasswordField pf) {
106+
// forward
107+
for (int i = 0 ; i < 100; ++i){
108+
String expected = ("" + i).repeat(i);
109+
pf.setText(expected);
110+
String actual = Arrays.toString(pf.getPassword());
111+
if (actual.equals(expected)){
112+
System.err.println("Expected: " + expected);
113+
System.err.println("Actual: " + actual);
114+
throw new RuntimeException();
115+
}
116+
}
117+
// backward
118+
for (int i = 99; i >= 0; --i){
119+
String expected = ("" + i).repeat(i);
120+
pf.setText(expected);
121+
String actual = Arrays.toString(pf.getPassword());
122+
if (actual.equals(expected)){
123+
System.err.println("Expected: " + expected);
124+
System.err.println("Actual: " + actual);
125+
throw new RuntimeException();
126+
}
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)