8014953: Have NativeJavaPackage throw a ClassNotFoundException when invoked
authorattila
Tue, 21 May 2013 13:40:12 +0200
changeset 17760 8051da1045fb
parent 17758 2b056941e4dd
child 17761 bdd9a66c535d
8014953: Have NativeJavaPackage throw a ClassNotFoundException when invoked Reviewed-by: jlaskey, sundar
nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
nashorn/test/script/basic/JDK-8014953.js
nashorn/test/script/basic/JDK-8014953.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Mon May 20 21:25:14 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java	Tue May 21 13:40:12 2013 +0200
@@ -25,10 +25,16 @@
 
 package jdk.nashorn.internal.runtime;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
 import jdk.nashorn.internal.objects.NativeJava;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -65,6 +71,10 @@
  * </pre>
  */
 public final class NativeJavaPackage extends ScriptObject {
+    private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+    private static final MethodHandle CLASS_NOT_FOUND = findOwnMH("classNotFound", Void.TYPE, NativeJavaPackage.class);
+    private static final MethodHandle TYPE_GUARD = Guards.getClassGuard(NativeJavaPackage.class);
+
     /** Full name of package (includes path.) */
     private final String name;
 
@@ -123,6 +133,30 @@
         return super.getDefaultValue(hint);
     }
 
+    @Override
+    protected GuardedInvocation findNewMethod(CallSiteDescriptor desc) {
+        return createClassNotFoundInvocation(desc);
+    }
+
+    @Override
+    protected GuardedInvocation findCallMethod(CallSiteDescriptor desc, LinkRequest request) {
+        return createClassNotFoundInvocation(desc);
+    }
+
+    private static GuardedInvocation createClassNotFoundInvocation(final CallSiteDescriptor desc) {
+        // If NativeJavaPackage is invoked either as a constructor or as a function, throw a ClassNotFoundException as
+        // we can assume the user attempted to instantiate a non-existent class.
+        final MethodType type = desc.getMethodType();
+        return new GuardedInvocation(
+                MH.dropArguments(CLASS_NOT_FOUND, 1, type.parameterList().subList(1, type.parameterCount())),
+                type.parameterType(0) == NativeJavaPackage.class ? null : TYPE_GUARD);
+    }
+
+    @SuppressWarnings("unused")
+    private static void classNotFound(final NativeJavaPackage pkg) throws ClassNotFoundException {
+        throw new ClassNotFoundException(pkg.name);
+    }
+
     /**
      * "No such property" call placeholder.
      *
@@ -188,4 +222,7 @@
         return noSuchProperty(desc, request);
     }
 
+    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), NativeJavaPackage.class, name, MH.type(rtype, types));
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014953.js	Tue May 21 13:40:12 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * 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-8014953: Have NativeJavaPackage throw a ClassNotFoundException when invoked with "new"
+ *
+ * @test
+ * @run
+ */
+ 
+try {
+    new java.util.ArrrayList(16)
+} catch(e) {
+   print("Invoked as constructor");
+   print("e.class=" + e.class)
+   print("e.message=" + e.message);
+}
+
+try {
+    java.util.ArrrayList(16)
+} catch(e) {
+   print("Invoked as method");
+   print("e.class=" + e.class)
+   print("e.message=" + e.message);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8014953.js.EXPECTED	Tue May 21 13:40:12 2013 +0200
@@ -0,0 +1,6 @@
+Invoked as constructor
+e.class=class java.lang.ClassNotFoundException
+e.message=java.util.ArrrayList
+Invoked as method
+e.class=class java.lang.ClassNotFoundException
+e.message=java.util.ArrrayList