8039137: KSS: JTextComponent.isProcessInputMethodEventOverridden
Reviewed-by: alexsch, serb
This commit is contained in:
parent
b04364a90e
commit
002763f0fc
@ -119,13 +119,13 @@ public abstract class Cache<K,V> {
|
||||
synchronized (this.queue) {
|
||||
// synchronized search improves stability
|
||||
// we must create and add new value if there are no needed entry
|
||||
int index = index(hash, this.table);
|
||||
current = getEntryValue(key, hash, this.table[index]);
|
||||
current = getEntryValue(key, hash, this.table[index(hash, this.table)]);
|
||||
if (current != null) {
|
||||
return current;
|
||||
}
|
||||
V value = create(key);
|
||||
Objects.requireNonNull(value, "value");
|
||||
int index = index(hash, this.table);
|
||||
this.table[index] = new CacheEntry<>(hash, key, value, this.table[index]);
|
||||
if (++this.size >= this.threshold) {
|
||||
if (this.table.length == MAXIMUM_CAPACITY) {
|
||||
|
@ -24,18 +24,16 @@
|
||||
*/
|
||||
package javax.swing.text;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import com.sun.beans.util.Cache;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import java.beans.Transient;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
@ -1193,47 +1191,6 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if <code>klass</code> is NOT a JTextComponent and it or
|
||||
* one of its superclasses (stoping at JTextComponent) overrides
|
||||
* <code>processInputMethodEvent</code>. It is assumed this will be
|
||||
* invoked from within a <code>doPrivileged</code>, and it is also
|
||||
* assumed <code>klass</code> extends <code>JTextComponent</code>.
|
||||
*/
|
||||
private static Boolean isProcessInputMethodEventOverridden(Class<?> klass) {
|
||||
if (klass == JTextComponent.class) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
Boolean retValue = overrideMap.get(klass.getName());
|
||||
|
||||
if (retValue != null) {
|
||||
return retValue;
|
||||
}
|
||||
Boolean sOverriden = isProcessInputMethodEventOverridden(
|
||||
klass.getSuperclass());
|
||||
|
||||
if (sOverriden.booleanValue()) {
|
||||
// If our superclass has overriden it, then by definition klass
|
||||
// overrides it.
|
||||
overrideMap.put(klass.getName(), sOverriden);
|
||||
return sOverriden;
|
||||
}
|
||||
// klass's superclass didn't override it, check for an override in
|
||||
// klass.
|
||||
try {
|
||||
Class[] classes = new Class[1];
|
||||
classes[0] = InputMethodEvent.class;
|
||||
|
||||
Method m = klass.getDeclaredMethod("processInputMethodEvent",
|
||||
classes);
|
||||
retValue = Boolean.TRUE;
|
||||
} catch (NoSuchMethodException nsme) {
|
||||
retValue = Boolean.FALSE;
|
||||
}
|
||||
overrideMap.put(klass.getName(), retValue);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the current color used to render the
|
||||
* caret.
|
||||
@ -3916,7 +3873,33 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A
|
||||
* Maps from class name to Boolean indicating if
|
||||
* <code>processInputMethodEvent</code> has been overriden.
|
||||
*/
|
||||
private static Map<String, Boolean> overrideMap;
|
||||
private static Cache<Class<?>,Boolean> METHOD_OVERRIDDEN
|
||||
= new Cache<Class<?>,Boolean>(Cache.Kind.WEAK, Cache.Kind.STRONG) {
|
||||
/**
|
||||
* Returns {@code true} if the specified {@code type} extends {@link JTextComponent}
|
||||
* and the {@link JTextComponent#processInputMethodEvent} method is overridden.
|
||||
*/
|
||||
@Override
|
||||
public Boolean create(final Class<?> type) {
|
||||
if (JTextComponent.class == type) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if (get(type.getSuperclass())) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
return AccessController.doPrivileged(
|
||||
new PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
try {
|
||||
type.getDeclaredMethod("processInputMethodEvent", InputMethodEvent.class);
|
||||
return Boolean.TRUE;
|
||||
} catch (NoSuchMethodException exception) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of this <code>JTextComponent</code>.
|
||||
@ -4941,38 +4924,15 @@ public abstract class JTextComponent extends JComponent implements Scrollable, A
|
||||
*/
|
||||
private boolean shouldSynthensizeKeyEvents() {
|
||||
if (!checkedInputOverride) {
|
||||
// Checks whether the client code overrides processInputMethodEvent.
|
||||
// If it is overridden, need not to generate KeyTyped events for committed text.
|
||||
// If it's not, behave as an passive input method client.
|
||||
needToSendKeyTypedEvent = !METHOD_OVERRIDDEN.get(getClass());
|
||||
checkedInputOverride = true;
|
||||
needToSendKeyTypedEvent =
|
||||
!isProcessInputMethodEventOverridden();
|
||||
}
|
||||
return needToSendKeyTypedEvent;
|
||||
}
|
||||
|
||||
//
|
||||
// Checks whether the client code overrides processInputMethodEvent. If it is overridden,
|
||||
// need not to generate KeyTyped events for committed text. If it's not, behave as an
|
||||
// passive input method client.
|
||||
//
|
||||
private boolean isProcessInputMethodEventOverridden() {
|
||||
if (overrideMap == null) {
|
||||
overrideMap = Collections.synchronizedMap(new HashMap<String, Boolean>());
|
||||
}
|
||||
Boolean retValue = overrideMap.get(getClass().getName());
|
||||
|
||||
if (retValue != null) {
|
||||
return retValue.booleanValue();
|
||||
}
|
||||
Boolean ret = AccessController.doPrivileged(new
|
||||
PrivilegedAction<Boolean>() {
|
||||
public Boolean run() {
|
||||
return isProcessInputMethodEventOverridden(
|
||||
JTextComponent.this.getClass());
|
||||
}
|
||||
});
|
||||
|
||||
return ret.booleanValue();
|
||||
}
|
||||
|
||||
//
|
||||
// Checks whether a composed text in this text component
|
||||
//
|
||||
|
83
jdk/test/java/beans/Introspector/TestCacheRecursion.java
Normal file
83
jdk/test/java/beans/Introspector/TestCacheRecursion.java
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 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.
|
||||
*/
|
||||
|
||||
import com.sun.beans.util.Cache;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8039137
|
||||
* @summary Tests Cache recursion
|
||||
* @author Sergey Malenkov
|
||||
* @compile -XDignore.symbol.file TestCacheRecursion.java
|
||||
* @run main TestCacheRecursion
|
||||
*/
|
||||
|
||||
public class TestCacheRecursion {
|
||||
private static boolean ERROR;
|
||||
private static final Cache<Class<?>,Boolean> CACHE
|
||||
= new Cache<Class<?>,Boolean>(Cache.Kind.WEAK, Cache.Kind.STRONG) {
|
||||
@Override
|
||||
public Boolean create(Class<?> type) {
|
||||
if (ERROR) {
|
||||
throw new Error("not initialized");
|
||||
}
|
||||
type = type.getSuperclass();
|
||||
return (type != null) && get(type);
|
||||
}
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
CACHE.get(Z.class);
|
||||
ERROR = true;
|
||||
for (Class<?> type = Z.class; type != null; type = type.getSuperclass()) {
|
||||
CACHE.get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private class A {}
|
||||
private class B extends A {}
|
||||
private class C extends B {}
|
||||
private class D extends C {}
|
||||
private class E extends D {}
|
||||
private class F extends E {}
|
||||
private class G extends F {}
|
||||
private class H extends G {}
|
||||
private class I extends H {}
|
||||
private class J extends I {}
|
||||
private class K extends J {}
|
||||
private class L extends K {}
|
||||
private class M extends L {}
|
||||
private class N extends M {}
|
||||
private class O extends N {}
|
||||
private class P extends O {}
|
||||
private class Q extends P {}
|
||||
private class R extends Q {}
|
||||
private class S extends R {}
|
||||
private class T extends S {}
|
||||
private class U extends T {}
|
||||
private class V extends U {}
|
||||
private class W extends V {}
|
||||
private class X extends W {}
|
||||
private class Y extends X {}
|
||||
private class Z extends Y {}
|
||||
}
|
Loading…
Reference in New Issue
Block a user