8038092: Re-examine Bidi reflective dependency on java.awt.font

Reviewed-by: alanb
This commit is contained in:
Naoto Sato 2014-07-03 16:19:39 -07:00
parent 7f1cf5327f
commit e3479393de
7 changed files with 166 additions and 72 deletions

View File

@ -0,0 +1,57 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package java.awt.font;
import java.lang.reflect.Field;
import sun.misc.JavaAWTFontAccess;
class JavaAWTFontAccessImpl implements sun.misc.JavaAWTFontAccess {
// java.awt.font.TextAttribute constants
public Object getTextAttributeConstant(String name) {
switch (name) {
case "RUN_DIRECTION":
case "NUMERIC_SHAPING":
case "BIDI_EMBEDDING":
case "RUN_DIRECTION_LTR":
try {
Field f = TextAttribute.class.getField(name);
return f.get(null);
} catch (NoSuchFieldException | IllegalAccessException x) {
throw new AssertionError(x);
}
}
throw new AssertionError("Constant name is not recognized");
}
// java.awt.font.NumericShaper
public void shape(Object shaper, char[] text, int start, int count) {
assert shaper instanceof NumericShaper;
((NumericShaper)shaper).shape(text, start,count);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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
@ -31,6 +31,7 @@ import java.util.Arrays;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.Set;
import sun.misc.SharedSecrets;
/**
* The <code>NumericShaper</code> class is used to convert Latin-1 (European)
@ -134,6 +135,14 @@ import java.util.Set;
*/
public final class NumericShaper implements java.io.Serializable {
// For access from java.text.Bidi
static {
if (SharedSecrets.getJavaAWTFontAccess() == null) {
SharedSecrets.setJavaAWTFontAccess(new JavaAWTFontAccessImpl());
}
}
/**
* A {@code NumericShaper.Range} represents a Unicode range of a
* script having its own decimal digits. For example, the {@link

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 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
@ -44,6 +44,7 @@ import java.io.InvalidObjectException;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.Map;
import java.util.HashMap;
import sun.misc.SharedSecrets;
/**
* The <code>TextAttribute</code> class defines attribute keys and
@ -257,6 +258,13 @@ public final class TextAttribute extends Attribute {
private static final Map<String, TextAttribute>
instanceMap = new HashMap<String, TextAttribute>(29);
// For access from java.text.Bidi
static {
if (SharedSecrets.getJavaAWTFontAccess() == null) {
SharedSecrets.setJavaAWTFontAccess(new JavaAWTFontAccessImpl());
}
}
/**
* Constructs a <code>TextAttribute</code> with the specified name.
* @param name the attribute name to assign to this

View File

@ -0,0 +1,39 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
/**
* SharedSecrets interface used for the access from java.text.Bidi
*/
package sun.misc;
public interface JavaAWTFontAccess {
// java.awt.font.TextAttribute constants
public Object getTextAttributeConstant(String name);
// java.awt.font.NumericShaper
public void shape(Object shaper, char[] text, int start, int count);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
@ -55,6 +55,7 @@ public class SharedSecrets {
private static JavaSecurityAccess javaSecurityAccess;
private static JavaUtilZipFileAccess javaUtilZipFileAccess;
private static JavaAWTAccess javaAWTAccess;
private static JavaAWTFontAccess javaAWTFontAccess;
private static JavaBeansIntrospectorAccess javaBeansIntrospectorAccess;
public static JavaUtilJarAccess javaUtilJarAccess() {
@ -180,12 +181,19 @@ public class SharedSecrets {
public static JavaAWTAccess getJavaAWTAccess() {
// this may return null in which case calling code needs to
// provision for.
if (javaAWTAccess == null) {
return null;
}
return javaAWTAccess;
}
public static void setJavaAWTFontAccess(JavaAWTFontAccess jafa) {
javaAWTFontAccess = jafa;
}
public static JavaAWTFontAccess getJavaAWTFontAccess() {
// this may return null in which case calling code needs to
// provision for.
return javaAWTFontAccess;
}
public static JavaBeansIntrospectorAccess getJavaBeansIntrospectorAccess() {
return javaBeansIntrospectorAccess;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 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
@ -54,13 +54,12 @@ package sun.text.bidi;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.text.AttributedCharacterIterator;
import java.text.Bidi;
import java.util.Arrays;
import java.util.MissingResourceException;
import sun.misc.JavaAWTFontAccess;
import sun.misc.SharedSecrets;
import sun.text.normalizer.UBiDiProps;
import sun.text.normalizer.UCharacter;
import sun.text.normalizer.UTF16;
@ -3446,7 +3445,13 @@ public class BidiBase {
* java.awt.font.TextAttribute without creating a static dependency.
*/
private static class TextAttributeConstants {
private static final Class<?> clazz = getClass("java.awt.font.TextAttribute");
// Make sure to load the AWT's TextAttribute class before using the constants, if any.
static {
try {
Class.forName("java.awt.font.TextAttribute", true, null);
} catch (ClassNotFoundException e) {}
}
static final JavaAWTFontAccess jafa = SharedSecrets.getJavaAWTFontAccess();
/**
* TextAttribute instances (or a fake Attribute type if
@ -3462,88 +3467,41 @@ public class BidiBase {
/**
* TextAttribute.RUN_DIRECTION_LTR
*/
static final Boolean RUN_DIRECTION_LTR = (clazz == null) ?
Boolean.FALSE : (Boolean)getStaticField(clazz, "RUN_DIRECTION_LTR");
private static Class<?> getClass(String name) {
try {
return Class.forName(name, true, null);
} catch (ClassNotFoundException e) {
return null;
}
}
private static Object getStaticField(Class<?> clazz, String name) {
try {
Field f = clazz.getField(name);
return f.get(null);
} catch (NoSuchFieldException | IllegalAccessException x) {
throw new AssertionError(x);
}
}
static final Boolean RUN_DIRECTION_LTR = (jafa == null) ?
Boolean.FALSE : (Boolean)jafa.getTextAttributeConstant("RUN_DIRECTION_LTR");
@SuppressWarnings("serial")
private static AttributedCharacterIterator.Attribute
getTextAttribute(String name)
{
if (clazz == null) {
if (jafa == null) {
// fake attribute
return new AttributedCharacterIterator.Attribute(name) { };
} else {
return (AttributedCharacterIterator.Attribute)getStaticField(clazz, name);
return (AttributedCharacterIterator.Attribute)jafa.getTextAttributeConstant(name);
}
}
}
/**
* A class that provides access to java.awt.font.NumericShaping without
* A class that provides access to java.awt.font.NumericShaper without
* creating a static dependency.
*/
private static class NumericShapings {
private static final Class<?> clazz =
getClass("java.awt.font.NumericShaper");
private static final Method shapeMethod =
getMethod(clazz, "shape", char[].class, int.class, int.class);
private static Class<?> getClass(String name) {
// Make sure to load the AWT's NumericShaper class before calling shape, if any.
static {
try {
return Class.forName(name, true, null);
} catch (ClassNotFoundException e) {
return null;
}
}
private static Method getMethod(Class<?> clazz,
String name,
Class<?>... paramTypes)
{
if (clazz != null) {
try {
return clazz.getMethod(name, paramTypes);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
} else {
return null;
}
Class.forName("java.awt.font.NumericShaper", true, null);
} catch (ClassNotFoundException e) {}
}
static final JavaAWTFontAccess jafa = SharedSecrets.getJavaAWTFontAccess();
/**
* Invokes NumericShaping shape(text,start,count) method.
*/
static void shape(Object shaper, char[] text, int start, int count) {
if (shapeMethod == null)
throw new AssertionError("Should not get here");
try {
shapeMethod.invoke(shaper, text, start, count);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof RuntimeException)
throw (RuntimeException)cause;
throw new AssertionError(e);
} catch (IllegalAccessException iae) {
throw new AssertionError(iae);
if (jafa != null) {
jafa.shape(shaper, text, start, count);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 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
@ -23,8 +23,11 @@
/*
* @test
* @bug 7051769
* @bug 7051769 8038092
* @summary verify that Bidi.toString() returns the corect result.
* The second run is intended to test lazy SharedSectets init for 8038092
* @run main Bug7051769
* @run main/othervm -DpreloadBidi=true Bug7051769
*/
import java.awt.font.*;
import java.text.*;
@ -32,6 +35,18 @@ import java.util.*;
public class Bug7051769 {
static {
if (System.getProperty("preloadBidi", "").equals("true")) {
// Make sure the SharedSecret is lazily initialized correctly
try {
Class.forName("sun.text.bidi.BidiBase");
System.out.println("BidiBase class has been pre-loaded.");
} catch (ClassNotFoundException e) {
System.out.println("BidiBase class could not be pre-loaded.");
}
}
}
private static boolean err = false;
public static void main(String[] args) {