aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorattila <none@none>2013-07-03 18:10:12 +0200
committerattila <none@none>2013-07-03 18:10:12 +0200
commitd53579fabe624578ab70b04afdd793f92438e81e (patch)
tree71f305f578c0f87ee9234aed53efa0abada45f3e
parentf5d80c52a24b1434af8f7a3f6cf0a7666c964ddb (diff)
8017768: allow dot as inner class name separator for Java.type
Reviewed-by: jlaskey, sundar
-rw-r--r--docs/JavaScriptingProgrammersGuide.html9
-rw-r--r--src/jdk/nashorn/internal/objects/NativeJava.java45
-rw-r--r--test/script/basic/JDK-8017768.js35
-rw-r--r--test/script/basic/JDK-8017768.js.EXPECTED4
-rw-r--r--test/src/jdk/nashorn/test/models/OuterClass.java4
5 files changed, 91 insertions, 6 deletions
diff --git a/docs/JavaScriptingProgrammersGuide.html b/docs/JavaScriptingProgrammersGuide.html
index 18ae823d..dd74d749 100644
--- a/docs/JavaScriptingProgrammersGuide.html
+++ b/docs/JavaScriptingProgrammersGuide.html
@@ -501,14 +501,19 @@ or
var anArrayListWithSize = new ArrayList(16)
</code></pre>
-In the special case of inner classes, you need to use the JVM fully qualified name, meaning using $ sign in the class name:
+In the special case of inner classes, you can either use the JVM fully qualified name, meaning using the dollar sign in the class name, or you can use the dot:
<pre><code>
var ftype = Java.type("java.awt.geom.Arc2D$Float")
</code></pre>
+and
+
+<pre><code>
+ var ftype = Java.type("java.awt.geom.Arc2D.Float")
+</code></pre>
-However, once you retrieved the outer class, you can access the inner class as a property on it:
+both work. Note however that using the dollar sign is faster, as Java.type first tries to resolve the class name as it is originally specified, and the internal JVM names for inner classes use the dollar sign. If you use the dot, Java.type will internally get a ClassNotFoundException and subsequently retry by changing the last dot to dollar sign. As a matter of fact, it'll keep replacing dots with dollar signs until it either successfully loads the class or runs out of all dots in the name. This way it can correctly resolve and load even multiply nested inner classes with the dot notation. Again, this will be slower than using the dollar signs in the name. An alternative way to access the inner class is as a property of the outer class:
<pre><code>
var arctype = Java.type("java.awt.geom.Arc2D")
diff --git a/src/jdk/nashorn/internal/objects/NativeJava.java b/src/jdk/nashorn/internal/objects/NativeJava.java
index 288770b4..8303c393 100644
--- a/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -39,6 +39,7 @@ import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.ListAdapter;
import jdk.nashorn.internal.runtime.PropertyMap;
@@ -105,12 +106,22 @@ public final class NativeJava {
* var anArrayList = new ArrayList
* var anArrayListWithSize = new ArrayList(16)
* </pre>
- * In the special case of inner classes, you need to use the JVM fully qualified name, meaning using {@code $} sign
- * in the class name:
+ * In the special case of inner classes, you can either use the JVM fully qualified name, meaning using {@code $}
+ * sign in the class name, or you can use the dot:
* <pre>
* var ftype = Java.type("java.awt.geom.Arc2D$Float")
* </pre>
- * However, once you retrieved the outer class, you can access the inner class as a property on it:
+ * and
+ * <pre>
+ * var ftype = Java.type("java.awt.geom.Arc2D.Float")
+ * </pre>
+ * both work. Note however that using the dollar sign is faster, as Java.type first tries to resolve the class name
+ * as it is originally specified, and the internal JVM names for inner classes use the dollar sign. If you use the
+ * dot, Java.type will internally get a ClassNotFoundException and subsequently retry by changing the last dot to
+ * dollar sign. As a matter of fact, it'll keep replacing dots with dollar signs until it either successfully loads
+ * the class or runs out of all dots in the name. This way it can correctly resolve and load even multiply nested
+ * inner classes with the dot notation. Again, this will be slower than using the dollar signs in the name. An
+ * alternative way to access the inner class is as a property of the outer class:
* <pre>
* var arctype = Java.type("java.awt.geom.Arc2D")
* var ftype = arctype.Float
@@ -390,7 +401,33 @@ public final class NativeJava {
private static Class<?> simpleType(final String typeName) throws ClassNotFoundException {
final Class<?> primClass = TypeUtilities.getPrimitiveTypeByName(typeName);
- return primClass != null ? primClass : Global.getThisContext().findClass(typeName);
+ if(primClass != null) {
+ return primClass;
+ }
+ final Context ctx = Global.getThisContext();
+ try {
+ return ctx.findClass(typeName);
+ } catch(ClassNotFoundException e) {
+ // The logic below compensates for a frequent user error - when people use dot notation to separate inner
+ // class names, i.e. "java.lang.Character.UnicodeBlock" vs."java.lang.Character$UnicodeBlock". The logic
+ // below will try alternative class names, replacing dots at the end of the name with dollar signs.
+ final StringBuilder nextName = new StringBuilder(typeName);
+ int lastDot = nextName.length();
+ for(;;) {
+ lastDot = nextName.lastIndexOf(".", lastDot - 1);
+ if(lastDot == -1) {
+ // Exhausted the search space, class not found - rethrow the original exception.
+ throw e;
+ }
+ nextName.setCharAt(lastDot, '$');
+ try {
+ return ctx.findClass(nextName.toString());
+ } catch(ClassNotFoundException cnfe) {
+ // Intentionally ignored, so the loop retries with the next name
+ }
+ }
+ }
+
}
private static Class<?> arrayType(final String typeName) throws ClassNotFoundException {
diff --git a/test/script/basic/JDK-8017768.js b/test/script/basic/JDK-8017768.js
new file mode 100644
index 00000000..c91f6d1f
--- /dev/null
+++ b/test/script/basic/JDK-8017768.js
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010, 2013, 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.
+ */
+
+/**
+ * JDK-8017768: Allow use of dot notation for inner class names.
+ *
+ * @test
+ * @run
+ */
+
+print(Java.type("java.awt.geom.Arc2D.Float") === Java.type("java.awt.geom.Arc2D$Float"))
+var iisc = Java.type("jdk.nashorn.test.models.OuterClass$InnerStaticClass$InnerInnerStaticClass")
+print(Java.type("jdk.nashorn.test.models.OuterClass.InnerStaticClass.InnerInnerStaticClass") === iisc)
+print(Java.type("jdk.nashorn.test.models.OuterClass$InnerStaticClass.InnerInnerStaticClass") === iisc)
+print(Java.type("jdk.nashorn.test.models.OuterClass.InnerStaticClass$InnerInnerStaticClass") === iisc)
diff --git a/test/script/basic/JDK-8017768.js.EXPECTED b/test/script/basic/JDK-8017768.js.EXPECTED
new file mode 100644
index 00000000..1140ff52
--- /dev/null
+++ b/test/script/basic/JDK-8017768.js.EXPECTED
@@ -0,0 +1,4 @@
+true
+true
+true
+true
diff --git a/test/src/jdk/nashorn/test/models/OuterClass.java b/test/src/jdk/nashorn/test/models/OuterClass.java
index 5db86f28..fc280f65 100644
--- a/test/src/jdk/nashorn/test/models/OuterClass.java
+++ b/test/src/jdk/nashorn/test/models/OuterClass.java
@@ -33,6 +33,10 @@ public class OuterClass {
}
public static class InnerStaticClass {
+
+ public static class InnerInnerStaticClass {
+ }
+
private final String value;
public InnerStaticClass(String value) {