8133453: Deprecate AWTKeyStroke.registerSubclass(Class) method
Reviewed-by: serb, azvegint
This commit is contained in:
parent
69e41447a6
commit
2c3b2dd68e
@ -32,12 +32,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.io.Serializable;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Field;
|
||||
import sun.swing.SwingAccessor;
|
||||
|
||||
/**
|
||||
* An <code>AWTKeyStroke</code> represents a key action on the
|
||||
@ -80,21 +77,6 @@ public class AWTKeyStroke implements Serializable {
|
||||
//A key withing the cache
|
||||
private static AWTKeyStroke APP_CONTEXT_KEYSTROKE_KEY = new AWTKeyStroke();
|
||||
|
||||
/*
|
||||
* Reads keystroke class from AppContext and if null, puts there the
|
||||
* AWTKeyStroke class.
|
||||
* Must be called under locked AWTKeyStroke
|
||||
*/
|
||||
private static Class<AWTKeyStroke> getAWTKeyStrokeClass() {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<AWTKeyStroke> clazz = (Class<AWTKeyStroke>)AppContext.getAppContext().get(AWTKeyStroke.class);
|
||||
if (clazz == null) {
|
||||
clazz = AWTKeyStroke.class;
|
||||
AppContext.getAppContext().put(AWTKeyStroke.class, AWTKeyStroke.class);
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
private char keyChar = KeyEvent.CHAR_UNDEFINED;
|
||||
private int keyCode = KeyEvent.VK_UNDEFINED;
|
||||
private int modifiers;
|
||||
@ -160,92 +142,15 @@ public class AWTKeyStroke implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new class which the factory methods in
|
||||
* <code>AWTKeyStroke</code> will use when generating new
|
||||
* instances of <code>AWTKeyStroke</code>s. After invoking this
|
||||
* method, the factory methods will return instances of the specified
|
||||
* Class. The specified Class must be either <code>AWTKeyStroke</code>
|
||||
* or derived from <code>AWTKeyStroke</code>, and it must have a
|
||||
* no-arg constructor. The constructor can be of any accessibility,
|
||||
* including <code>private</code>. This operation
|
||||
* flushes the current <code>AWTKeyStroke</code> cache.
|
||||
* The method has no effect and is only left present to avoid introducing
|
||||
* a binary incompatibility.
|
||||
*
|
||||
* @param subclass the new Class of which the factory methods should create
|
||||
* instances
|
||||
* @throws IllegalArgumentException if subclass is <code>null</code>,
|
||||
* or if subclass does not have a no-arg constructor
|
||||
* @throws ClassCastException if subclass is not
|
||||
* <code>AWTKeyStroke</code>, or a class derived from
|
||||
* <code>AWTKeyStroke</code>
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
protected static void registerSubclass(Class<?> subclass) {
|
||||
if (subclass == null) {
|
||||
throw new IllegalArgumentException("subclass cannot be null");
|
||||
}
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<AWTKeyStroke> keyStrokeClass = (Class)AppContext.getAppContext().get(AWTKeyStroke.class);
|
||||
if (keyStrokeClass != null && keyStrokeClass.equals(subclass)){
|
||||
// Already registered
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!AWTKeyStroke.class.isAssignableFrom(subclass)) {
|
||||
throw new ClassCastException("subclass is not derived from AWTKeyStroke");
|
||||
}
|
||||
|
||||
Constructor<?> ctor = getCtor(subclass);
|
||||
|
||||
String couldNotInstantiate = "subclass could not be instantiated";
|
||||
|
||||
if (ctor == null) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
}
|
||||
try {
|
||||
AWTKeyStroke stroke = (AWTKeyStroke)ctor.newInstance((Object[]) null);
|
||||
if (stroke == null) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
}
|
||||
} catch (NoSuchMethodError e) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
} catch (ExceptionInInitializerError e) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalArgumentException(couldNotInstantiate);
|
||||
}
|
||||
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
AppContext.getAppContext().put(AWTKeyStroke.class, subclass);
|
||||
AppContext.getAppContext().remove(APP_CONTEXT_CACHE_KEY);
|
||||
AppContext.getAppContext().remove(APP_CONTEXT_KEYSTROKE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
/* returns no-arg Constructor for class with accessible flag. No security
|
||||
threat as accessible flag is set only for this Constructor object,
|
||||
not for Class constructor.
|
||||
*/
|
||||
private static Constructor<?> getCtor(final Class<?> clazz)
|
||||
{
|
||||
Constructor<?> ctor = AccessController.doPrivileged(new PrivilegedAction<Constructor<?>>() {
|
||||
public Constructor<?> run() {
|
||||
try {
|
||||
Constructor<?> ctor = clazz.getDeclaredConstructor((Class<?>[]) null);
|
||||
if (ctor != null) {
|
||||
ctor.setAccessible(true);
|
||||
}
|
||||
return ctor;
|
||||
} catch (SecurityException e) {
|
||||
} catch (NoSuchMethodException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return ctor;
|
||||
}
|
||||
|
||||
private static synchronized AWTKeyStroke getCachedStroke
|
||||
@ -261,18 +166,10 @@ public class AWTKeyStroke implements Serializable {
|
||||
}
|
||||
|
||||
if (cacheKey == null) {
|
||||
try {
|
||||
Class<AWTKeyStroke> clazz = getAWTKeyStrokeClass();
|
||||
cacheKey = (AWTKeyStroke)getCtor(clazz).newInstance((Object[]) null);
|
||||
AppContext.getAppContext().put(APP_CONTEXT_KEYSTROKE_KEY, cacheKey);
|
||||
} catch (InstantiationException e) {
|
||||
assert(false);
|
||||
} catch (IllegalAccessException e) {
|
||||
assert(false);
|
||||
} catch (InvocationTargetException e) {
|
||||
assert(false);
|
||||
}
|
||||
cacheKey = SwingAccessor.getKeyStrokeAccessor().create();
|
||||
AppContext.getAppContext().put(APP_CONTEXT_KEYSTROKE_KEY, cacheKey);
|
||||
}
|
||||
|
||||
cacheKey.keyChar = keyChar;
|
||||
cacheKey.keyCode = keyCode;
|
||||
cacheKey.modifiers = mapNewModifiers(mapOldModifiers(modifiers));
|
||||
@ -806,11 +703,9 @@ public class AWTKeyStroke implements Serializable {
|
||||
*/
|
||||
protected Object readResolve() throws java.io.ObjectStreamException {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
if (getClass().equals(getAWTKeyStrokeClass())) {
|
||||
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
|
||||
}
|
||||
|
||||
return getCachedStroke(keyChar, keyCode, modifiers, onKeyRelease);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private static int mapOldModifiers(int modifiers) {
|
||||
|
@ -26,6 +26,7 @@ package javax.swing;
|
||||
|
||||
import java.awt.AWTKeyStroke;
|
||||
import java.awt.event.KeyEvent;
|
||||
import sun.swing.SwingAccessor;
|
||||
|
||||
/**
|
||||
* A KeyStroke represents a key action on the keyboard, or equivalent input
|
||||
@ -70,6 +71,16 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
*/
|
||||
private static final long serialVersionUID = -9060180771037902530L;
|
||||
|
||||
static {
|
||||
SwingAccessor.setKeyStrokeAccessor(new SwingAccessor.KeyStrokeAccessor() {
|
||||
|
||||
@Override
|
||||
public KeyStroke create() {
|
||||
return new KeyStroke();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private KeyStroke() {
|
||||
}
|
||||
private KeyStroke(char keyChar, int keyCode, int modifiers,
|
||||
@ -87,7 +98,6 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
*/
|
||||
public static KeyStroke getKeyStroke(char keyChar) {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
registerSubclass(KeyStroke.class);
|
||||
return (KeyStroke)getAWTKeyStroke(keyChar);
|
||||
}
|
||||
}
|
||||
@ -148,7 +158,6 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
*/
|
||||
public static KeyStroke getKeyStroke(Character keyChar, int modifiers) {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
registerSubclass(KeyStroke.class);
|
||||
return (KeyStroke)getAWTKeyStroke(keyChar, modifiers);
|
||||
}
|
||||
}
|
||||
@ -199,7 +208,6 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
public static KeyStroke getKeyStroke(int keyCode, int modifiers,
|
||||
boolean onKeyRelease) {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
registerSubclass(KeyStroke.class);
|
||||
return (KeyStroke)getAWTKeyStroke(keyCode, modifiers,
|
||||
onKeyRelease);
|
||||
}
|
||||
@ -247,7 +255,6 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
*/
|
||||
public static KeyStroke getKeyStroke(int keyCode, int modifiers) {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
registerSubclass(KeyStroke.class);
|
||||
return (KeyStroke)getAWTKeyStroke(keyCode, modifiers);
|
||||
}
|
||||
}
|
||||
@ -266,7 +273,6 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
*/
|
||||
public static KeyStroke getKeyStrokeForEvent(KeyEvent anEvent) {
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
registerSubclass(KeyStroke.class);
|
||||
return (KeyStroke)getAWTKeyStrokeForEvent(anEvent);
|
||||
}
|
||||
}
|
||||
@ -307,7 +313,6 @@ public class KeyStroke extends AWTKeyStroke {
|
||||
return null;
|
||||
}
|
||||
synchronized (AWTKeyStroke.class) {
|
||||
registerSubclass(KeyStroke.class);
|
||||
try {
|
||||
return (KeyStroke)getAWTKeyStroke(s);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
@ -97,6 +97,14 @@ public final class SwingAccessor {
|
||||
int ownerX, int ownerY);
|
||||
}
|
||||
|
||||
/*
|
||||
* An accessor for the KeyStroke class
|
||||
*/
|
||||
public interface KeyStrokeAccessor {
|
||||
|
||||
KeyStroke create();
|
||||
}
|
||||
|
||||
/**
|
||||
* The javax.swing.text.JTextComponent class accessor object.
|
||||
*/
|
||||
@ -185,4 +193,26 @@ public final class SwingAccessor {
|
||||
public static void setPopupFactoryAccessor(PopupFactoryAccessor popupFactoryAccessor) {
|
||||
SwingAccessor.popupFactoryAccessor = popupFactoryAccessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The KeyStroke class accessor object.
|
||||
*/
|
||||
private static KeyStrokeAccessor keyStrokeAccessor;
|
||||
|
||||
/**
|
||||
* Retrieve the accessor object for the KeyStroke class.
|
||||
*/
|
||||
public static KeyStrokeAccessor getKeyStrokeAccessor() {
|
||||
if (keyStrokeAccessor == null) {
|
||||
unsafe.ensureClassInitialized(KeyStroke.class);
|
||||
}
|
||||
return keyStrokeAccessor;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the accessor object for the KeyStroke class.
|
||||
*/
|
||||
public static void setKeyStrokeAccessor(KeyStrokeAccessor accessor) {
|
||||
SwingAccessor.keyStrokeAccessor = accessor;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 java.awt.AWTKeyStroke;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8133453
|
||||
* @summary Remove AWTKeyStroke.registerSubclass(Class) method
|
||||
* @author Alexander Scherbatiy
|
||||
* @run main/othervm TestAWTKeyStroke
|
||||
* @run main/othervm/policy=policy -Djava.security.manager TestAWTKeyStroke
|
||||
*/
|
||||
public class TestAWTKeyStroke {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
int modifiers = InputEvent.CTRL_MASK | InputEvent.CTRL_DOWN_MASK;
|
||||
checkAWTKeyStroke('A', modifiers, true);
|
||||
checkKeyStroke('B', modifiers, false);
|
||||
checkAWTKeyStroke('C', modifiers, false);
|
||||
checkKeyStroke('D', modifiers, true);
|
||||
checkSerializedKeyStrokes('E', modifiers, true);
|
||||
}
|
||||
|
||||
private static void checkAWTKeyStroke(int keyCode, int modifiers,
|
||||
boolean onKeyRelease) throws Exception {
|
||||
|
||||
AWTKeyStroke awtKeyStroke1 = AWTKeyStroke.getAWTKeyStroke(
|
||||
keyCode, modifiers, onKeyRelease);
|
||||
|
||||
checkAWTKeyStroke(awtKeyStroke1, keyCode, modifiers, onKeyRelease);
|
||||
|
||||
AWTKeyStroke awtKeyStroke2 = AWTKeyStroke.getAWTKeyStroke(
|
||||
keyCode, modifiers, onKeyRelease);
|
||||
|
||||
if (awtKeyStroke1 != awtKeyStroke2) {
|
||||
throw new RuntimeException("AWTKeyStroke is not cached!");
|
||||
}
|
||||
|
||||
checkSerializedKeyStroke(awtKeyStroke1);
|
||||
}
|
||||
|
||||
private static void checkKeyStroke(int keyCode, int modifiers,
|
||||
boolean onKeyRelease) throws Exception {
|
||||
|
||||
KeyStroke keyStroke1 = KeyStroke.getKeyStroke(
|
||||
keyCode, modifiers, onKeyRelease);
|
||||
checkAWTKeyStroke(keyStroke1, keyCode, modifiers, onKeyRelease);
|
||||
|
||||
KeyStroke keyStroke2 = KeyStroke.getKeyStroke(
|
||||
keyCode, modifiers, onKeyRelease);
|
||||
|
||||
if (keyStroke1 != keyStroke2) {
|
||||
throw new RuntimeException("KeyStroke is not cached!");
|
||||
}
|
||||
|
||||
checkSerializedKeyStroke(keyStroke1);
|
||||
}
|
||||
|
||||
private static void checkSerializedKeyStrokes(int keyCode, int modifiers,
|
||||
boolean onKeyRelease) throws Exception {
|
||||
|
||||
AWTKeyStroke awtKeyStroke = AWTKeyStroke.getAWTKeyStroke(
|
||||
keyCode, modifiers, onKeyRelease);
|
||||
|
||||
KeyStroke keyStroke = KeyStroke.getKeyStroke(
|
||||
keyCode, modifiers, onKeyRelease);
|
||||
|
||||
if (awtKeyStroke != getSerializedAWTKeyStroke(awtKeyStroke)) {
|
||||
throw new RuntimeException("Serialized AWTKeyStroke is not cached!");
|
||||
}
|
||||
|
||||
awtKeyStroke = AWTKeyStroke.getAWTKeyStroke(
|
||||
keyCode, modifiers, !onKeyRelease);
|
||||
|
||||
if (!keyStroke.equals(getSerializedAWTKeyStroke(keyStroke))) {
|
||||
throw new RuntimeException("Serialized KeyStroke is not cached!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkAWTKeyStroke(AWTKeyStroke awtKeyStroke,
|
||||
int keyCode, int modifiers, boolean onKeyRelease) {
|
||||
|
||||
if (awtKeyStroke.getKeyCode() != keyCode) {
|
||||
throw new RuntimeException("Wrong key code!");
|
||||
}
|
||||
|
||||
if (awtKeyStroke.getModifiers() != modifiers) {
|
||||
throw new RuntimeException("Wrong modifiers!");
|
||||
}
|
||||
|
||||
if (awtKeyStroke.isOnKeyRelease() != onKeyRelease) {
|
||||
throw new RuntimeException("Wrong on key release!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkSerializedKeyStroke(AWTKeyStroke keyStroke)
|
||||
throws Exception {
|
||||
if (keyStroke != getSerializedAWTKeyStroke(keyStroke)) {
|
||||
throw new RuntimeException("New instance is returned during"
|
||||
+ " serialization!");
|
||||
}
|
||||
}
|
||||
|
||||
private static AWTKeyStroke getSerializedAWTKeyStroke(AWTKeyStroke keyStroke)
|
||||
throws Exception {
|
||||
|
||||
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutput out = new ObjectOutputStream(bos)) {
|
||||
out.writeObject(keyStroke);
|
||||
byte[] bytes = bos.toByteArray();
|
||||
|
||||
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
|
||||
ObjectInput in = new ObjectInputStream(bis)) {
|
||||
return (AWTKeyStroke) in.readObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
grant {
|
||||
};
|
Loading…
Reference in New Issue
Block a user