1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.objects;
  27 
  28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  30 
  31 import java.lang.invoke.MethodHandles;
  32 import java.lang.reflect.Array;
  33 import java.util.ArrayList;
  34 import java.util.Collection;
  35 import java.util.Collections;
  36 import java.util.Deque;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Queue;
  40 import jdk.dynalink.SecureLookupSupplier;
  41 import jdk.dynalink.beans.BeansLinker;
  42 import jdk.dynalink.beans.StaticClass;
  43 import jdk.dynalink.linker.support.TypeUtilities;
  44 import jdk.nashorn.api.scripting.JSObject;
  45 import jdk.nashorn.api.scripting.ScriptObjectMirror;
  46 import jdk.nashorn.api.scripting.ScriptUtils;
  47 import jdk.nashorn.internal.objects.annotations.Attribute;
  48 import jdk.nashorn.internal.objects.annotations.Function;
  49 import jdk.nashorn.internal.objects.annotations.ScriptClass;
  50 import jdk.nashorn.internal.objects.annotations.Where;
  51 import jdk.nashorn.internal.runtime.Context;
  52 import jdk.nashorn.internal.runtime.JSType;
  53 import jdk.nashorn.internal.runtime.ListAdapter;
  54 import jdk.nashorn.internal.runtime.PropertyMap;
  55 import jdk.nashorn.internal.runtime.ScriptFunction;
  56 import jdk.nashorn.internal.runtime.ScriptObject;
  57 import jdk.nashorn.internal.runtime.ScriptRuntime;
  58 import jdk.nashorn.internal.runtime.linker.Bootstrap;
  59 import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
  60 
  61 /**
  62  * This class is the implementation for the {@code Java} global object exposed to programs running under Nashorn. This
  63  * object acts as the API entry point to Java platform specific functionality, dealing with creating new instances of
  64  * Java classes, subclassing Java classes, implementing Java interfaces, converting between Java arrays and ECMAScript
  65  * arrays, and so forth.
  66  */
  67 @ScriptClass("Java")
  68 public final class NativeJava {
  69     // initialized by nasgen
  70     @SuppressWarnings("unused")
  71     private static PropertyMap $nasgenmap$;
  72 
  73     private NativeJava() {
  74         // don't create me
  75         throw new UnsupportedOperationException();
  76     }
  77 
  78     /**
  79      * Returns true if the specified object is a Java type object, that is an instance of {@link StaticClass}.
  80      * @param self not used
  81      * @param type the object that is checked if it is a type object or not
  82      * @return tells whether given object is a Java type object or not.
  83      * @see #type(Object, Object)
  84      */
  85     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
  86     public static boolean isType(final Object self, final Object type) {
  87         return type instanceof StaticClass;
  88     }
  89 
  90     /**
  91      * Returns synchronized wrapper version of the given ECMAScript function.
  92      * @param self not used
  93      * @param func the ECMAScript function whose synchronized version is returned.
  94      * @param obj the object (i.e, lock) on which the function synchronizes.
  95      * @return synchronized wrapper version of the given ECMAScript function.
  96      */
  97     @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
  98     public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
  99         if (func instanceof ScriptFunction) {
 100             return ((ScriptFunction)func).createSynchronized(obj);
 101         }
 102 
 103         throw typeError("not.a.function", ScriptRuntime.safeToString(func));
 104     }
 105 
 106     /**
 107      * Returns true if the specified object is a Java method.
 108      * @param self not used
 109      * @param obj the object that is checked if it is a Java method object or not
 110      * @return tells whether given object is a Java method object or not.
 111      */
 112     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 113     public static boolean isJavaMethod(final Object self, final Object obj) {
 114         return Bootstrap.isDynamicMethod(obj);
 115     }
 116 
 117     /**
 118      * Returns true if the specified object is a java function (but not script function)
 119      * @param self not used
 120      * @param obj the object that is checked if it is a Java function or not
 121      * @return tells whether given object is a Java function or not
 122      */
 123     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 124     public static boolean isJavaFunction(final Object self, final Object obj) {
 125         return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
 126     }
 127 
 128     /**
 129      * Returns true if the specified object is a Java object but not a script object
 130      * @param self not used
 131      * @param obj the object that is checked
 132      * @return tells whether given object is a Java object but not a script object
 133      */
 134     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 135     public static boolean isJavaObject(final Object self, final Object obj) {
 136         return obj != null && !(obj instanceof ScriptObject);
 137     }
 138 
 139     /**
 140      * Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
 141      * @param self not used
 142      * @param obj the object that is checked if it is a ECMAScript object or not
 143      * @return tells whether given object is a ECMAScript object or not.
 144      */
 145     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 146     public static boolean isScriptObject(final Object self, final Object obj) {
 147         return obj instanceof ScriptObject;
 148     }
 149 
 150     /**
 151      * Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
 152      * @param self not used
 153      * @param obj the object that is checked if it is a ECMAScript function or not
 154      * @return tells whether given object is a ECMAScript function or not.
 155      */
 156     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 157     public static boolean isScriptFunction(final Object self, final Object obj) {
 158         return obj instanceof ScriptFunction;
 159     }
 160 
 161     /**
 162      * <p>
 163      * Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
 164      * used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
 165      * the objects that you can use with the {@code new} operator to create new instances of the class as well as to
 166      * access static members of the class. In Nashorn, {@code Class} objects are just regular Java objects that aren't
 167      * treated specially. Instead of them, {@link StaticClass} instances - which we sometimes refer to as "Java type
 168      * objects" are used as constructors with the {@code new} operator, and they expose static fields, properties, and
 169      * methods. While this might seem confusing at first, it actually closely matches the Java language: you use a
 170      * different expression (e.g. {@code java.io.File}) as an argument in "new" and to address statics, and it is
 171      * distinct from the {@code Class} object (e.g. {@code java.io.File.class}). Below we cover in details the
 172      * properties of the type objects.
 173      * </p>
 174      * <p><b>Constructing Java objects</b></p>
 175      * Examples:
 176      * <pre>
 177      * var arrayListType = Java.type("java.util.ArrayList")
 178      * var intType = Java.type("int")
 179      * var stringArrayType = Java.type("java.lang.String[]")
 180      * var int2DArrayType = Java.type("int[][]")
 181      * </pre>
 182      * Note that the name of the type is always a string for a fully qualified name. You can use any of these types to
 183      * create new instances, e.g.:
 184      * <pre>
 185      * var anArrayList = new Java.type("java.util.ArrayList")
 186      * </pre>
 187      * or
 188      * <pre>
 189      * var ArrayList = Java.type("java.util.ArrayList")
 190      * var anArrayList = new ArrayList
 191      * var anArrayListWithSize = new ArrayList(16)
 192      * </pre>
 193      * In the special case of inner classes, you can either use the JVM fully qualified name, meaning using {@code $}
 194      * sign in the class name, or you can use the dot:
 195      * <pre>
 196      * var ftype = Java.type("java.awt.geom.Arc2D$Float")
 197      * </pre>
 198      * and
 199      * <pre>
 200      * var ftype = Java.type("java.awt.geom.Arc2D.Float")
 201      * </pre>
 202      * both work. Note however that using the dollar sign is faster, as Java.type first tries to resolve the class name
 203      * as it is originally specified, and the internal JVM names for inner classes use the dollar sign. If you use the
 204      * dot, Java.type will internally get a ClassNotFoundException and subsequently retry by changing the last dot to
 205      * dollar sign. As a matter of fact, it'll keep replacing dots with dollar signs until it either successfully loads
 206      * the class or runs out of all dots in the name. This way it can correctly resolve and load even multiply nested
 207      * inner classes with the dot notation. Again, this will be slower than using the dollar signs in the name. An
 208      * alternative way to access the inner class is as a property of the outer class:
 209      * <pre>
 210      * var arctype = Java.type("java.awt.geom.Arc2D")
 211      * var ftype = arctype.Float
 212      * </pre>
 213      * <p>
 214      * You can access both static and non-static inner classes. If you want to create an instance of a non-static
 215      * inner class, remember to pass an instance of its outer class as the first argument to the constructor.
 216      * </p>
 217      * <p>
 218      * If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is
 219      * applicable to any of its public or protected constructors, but inserting a JavaScript object with functions
 220      * properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the
 221      * JavaScript function will provide implementation for all overloads. E.g.:
 222      * </p>
 223      * <pre>
 224      * var TimerTask =  Java.type("java.util.TimerTask")
 225      * var task = new TimerTask({ run: function() { print("Hello World!") } })
 226      * </pre>
 227      * <p>
 228      * Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to
 229      * invoking the constructor and passing the argument to it, so you can write the above example also as:
 230      * </p>
 231      * <pre>
 232      * var task = new TimerTask {
 233      *     run: function() {
 234      *       print("Hello World!")
 235      *     }
 236      * }
 237      * </pre>
 238      * <p>
 239      * which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract
 240      * type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share
 241      * the same overloaded name), then instead of an object, you can just pass a function, so the above example can
 242      * become even more simplified to:
 243      * </p>
 244      * <pre>
 245      * var task = new TimerTask(function() { print("Hello World!") })
 246      * </pre>
 247      * <p>
 248      * Note that in every one of these cases if you are trying to instantiate an abstract class that has constructors
 249      * that take some arguments, you can invoke those simply by specifying the arguments after the initial
 250      * implementation object or function.
 251      * </p>
 252      * <p>The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type,
 253      * you can just pass in a function object, and Nashorn will know what you meant:
 254      * </p>
 255      * <pre>
 256      * var timer = new Java.type("java.util.Timer")
 257      * timer.schedule(function() { print("Hello World!") })
 258      * </pre>
 259      * <p>
 260      * Here, {@code Timer.schedule()} expects a {@code TimerTask} as its argument, so Nashorn creates an instance of a
 261      * {@code TimerTask} subclass and uses the passed function to implement its only abstract method, {@code run()}. In
 262      * this usage though, you can't use non-default constructors; the type must be either an interface, or must have a
 263      * protected or public no-arg constructor.
 264      * </p>
 265      * <p>
 266      * You can also subclass non-abstract classes; for that you will need to use the {@link #extend(Object, Object...)}
 267      * method.
 268      * </p>
 269      * <p><b>Accessing static members</b></p>
 270      * Examples:
 271      * <pre>
 272      * var File = Java.type("java.io.File")
 273      * var pathSep = File.pathSeparator
 274      * var tmpFile1 = File.createTempFile("abcdefg", ".tmp")
 275      * var tmpFile2 = File.createTempFile("abcdefg", ".tmp", new File("/tmp"))
 276      * </pre>
 277      * Actually, you can even assign static methods to variables, so the above example can be rewritten as:
 278      * <pre>
 279      * var File = Java.type("java.io.File")
 280      * var createTempFile = File.createTempFile
 281      * var tmpFile1 = createTempFile("abcdefg", ".tmp")
 282      * var tmpFile2 = createTempFile("abcdefg", ".tmp", new File("/tmp"))
 283      * </pre>
 284      * If you need to access the actual {@code java.lang.Class} object for the type, you can use the {@code class}
 285      * property on the object representing the type:
 286      * <pre>
 287      * var File = Java.type("java.io.File")
 288      * var someFile = new File("blah")
 289      * print(File.class === someFile.getClass()) // prints true
 290      * </pre>
 291      * Of course, you can also use the {@code getClass()} method or its equivalent {@code class} property on any
 292      * instance of the class. Other way round, you can use the synthetic {@code static} property on any
 293      * {@code java.lang.Class} object to retrieve its type-representing object:
 294      * <pre>
 295      * var File = Java.type("java.io.File")
 296      * print(File.class.static === File) // prints true
 297      * </pre>
 298      * <p><b>{@code instanceof} operator</b></p>
 299      * The standard ECMAScript {@code instanceof} operator is extended to recognize Java objects and their type objects:
 300      * <pre>
 301      * var File = Java.type("java.io.File")
 302      * var aFile = new File("foo")
 303      * print(aFile instanceof File) // prints true
 304      * print(aFile instanceof File.class) // prints false - Class objects aren't type objects.
 305      * </pre>
 306      * @param self not used
 307      * @param objTypeName the object whose JS string value represents the type name. You can use names of primitive Java
 308      * types to obtain representations of them, and you can use trailing square brackets to represent Java array types.
 309      * @return the object representing the named type
 310      * @throws ClassNotFoundException if the class is not found
 311      */
 312     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 313     public static Object type(final Object self, final Object objTypeName) throws ClassNotFoundException {
 314         return type(objTypeName);
 315     }
 316 
 317     private static StaticClass type(final Object objTypeName) throws ClassNotFoundException {
 318         return StaticClass.forClass(type(JSType.toString(objTypeName)));
 319     }
 320 
 321     private static Class<?> type(final String typeName) throws ClassNotFoundException {
 322         if (typeName.endsWith("[]")) {
 323             return arrayType(typeName);
 324         }
 325 
 326         return simpleType(typeName);
 327     }
 328 
 329     /**
 330      * Returns name of a java type {@link StaticClass}.
 331      * @param self not used
 332      * @param type the type whose name is returned
 333      * @return name of the given type
 334      */
 335     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 336     public static Object typeName(final Object self, final Object type) {
 337         if (type instanceof StaticClass) {
 338             return ((StaticClass)type).getRepresentedClass().getName();
 339         } else if (type instanceof Class) {
 340             return ((Class<?>)type).getName();
 341         } else {
 342             return UNDEFINED;
 343         }
 344     }
 345 
 346     /**
 347      * Given a script object and a Java type, converts the script object into the desired Java type. Currently it
 348      * performs shallow creation of Java arrays, as well as wrapping of objects in Lists, Dequeues, Queues,
 349      * and Collections. If conversion is not possible or fails for some reason, TypeError is thrown.
 350      * Example:
 351      * <pre>
 352      * var anArray = [1, "13", false]
 353      * var javaIntArray = Java.to(anArray, "int[]")
 354      * print(javaIntArray[0]) // prints 1
 355      * print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
 356      * print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
 357      * </pre>
 358      * @param self not used
 359      * @param obj the script object. Can be null.
 360      * @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java
 361      * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
 362      * omitted).
 363      * @return a Java object whose value corresponds to the original script object's value. Specifically, for array
 364      * target types, returns a Java array of the same type with contents converted to the array's component type.
 365      * Converts recursively when the target type is multidimensional array. For {@link List}, {@link Deque},
 366      * {@link Queue}, or {@link Collection}, returns a live wrapper around the object, see {@link ListAdapter} for
 367      * details. Returns null if obj is null.
 368      * @throws ClassNotFoundException if the class described by objType is not found
 369      */
 370     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 371     public static Object to(final Object self, final Object obj, final Object objType) throws ClassNotFoundException {
 372         if (obj == null) {
 373             return null;
 374         }
 375 
 376         if (!(obj instanceof ScriptObject) && !(obj instanceof JSObject)) {
 377             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
 378         }
 379 
 380         final Class<?> targetClass;
 381         if(objType == UNDEFINED) {
 382             targetClass = Object[].class;
 383         } else {
 384             final StaticClass targetType;
 385             if(objType instanceof StaticClass) {
 386                 targetType = (StaticClass)objType;
 387             } else {
 388                 targetType = type(objType);
 389             }
 390             targetClass = targetType.getRepresentedClass();
 391         }
 392 
 393         if(targetClass.isArray()) {
 394             try {
 395                 if (self instanceof SecureLookupSupplier) {
 396                     return JSType.toJavaArrayWithLookup(obj, targetClass.getComponentType(), (SecureLookupSupplier)self);
 397                 }
 398                 return JSType.toJavaArray(obj, targetClass.getComponentType());
 399             } catch (final Exception exp) {
 400                 throw typeError(exp, "java.array.conversion.failed", targetClass.getName());
 401             }
 402         }
 403 
 404         if (targetClass == List.class || targetClass == Deque.class || targetClass == Queue.class || targetClass == Collection.class) {
 405             return ListAdapter.create(obj);
 406         }
 407 
 408         throw typeError("unsupported.java.to.type", targetClass.getName());
 409     }
 410 
 411     /**
 412      * Given a Java array or {@link Collection}, returns a JavaScript array with a shallow copy of its contents. Note
 413      * that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you
 414      * need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will
 415      * want to use this method. Example:
 416      * <pre>
 417      * var File = Java.type("java.io.File")
 418      * var listHomeDir = new File("~").listFiles()
 419      * var jsListHome = Java.from(listHomeDir)
 420      * var jpegModifiedDates = jsListHome
 421      *     .filter(function(val) { return val.getName().endsWith(".jpg") })
 422      *     .map(function(val) { return val.lastModified() })
 423      * </pre>
 424      * @param self not used
 425      * @param objArray the java array or collection. Can be null.
 426      * @return a JavaScript array with the copy of Java array's or collection's contents. Returns null if objArray is
 427      * null.
 428      */
 429     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 430     public static NativeArray from(final Object self, final Object objArray) {
 431         if (objArray == null) {
 432             return null;
 433         } else if (objArray instanceof Collection) {
 434             return new NativeArray(ScriptUtils.unwrapArray(((Collection<?>)objArray).toArray()));
 435         } else if (objArray instanceof Object[]) {
 436             return new NativeArray(ScriptUtils.unwrapArray(((Object[])objArray).clone()));
 437         } else if (objArray instanceof int[]) {
 438             return new NativeArray(((int[])objArray).clone());
 439         } else if (objArray instanceof double[]) {
 440             return new NativeArray(((double[])objArray).clone());
 441         } else if (objArray instanceof long[]) {
 442             return new NativeArray(((long[])objArray).clone());
 443         } else if (objArray instanceof byte[]) {
 444             return new NativeArray(copyArray((byte[])objArray));
 445         } else if (objArray instanceof short[]) {
 446             return new NativeArray(copyArray((short[])objArray));
 447         } else if (objArray instanceof char[]) {
 448             return new NativeArray(copyArray((char[])objArray));
 449         } else if (objArray instanceof float[]) {
 450             return new NativeArray(copyArray((float[])objArray));
 451         } else if (objArray instanceof boolean[]) {
 452             return new NativeArray(copyArray((boolean[])objArray));
 453         }
 454 
 455         throw typeError("cant.convert.to.javascript.array", objArray.getClass().getName());
 456     }
 457 
 458     /**
 459      * Return properties of the given object. Properties also include "method names".
 460      * This is meant for source code completion in interactive shells or editors.
 461      *
 462      * @param object the object whose properties are returned.
 463      * @return list of properties
 464      */
 465     public static List<String> getProperties(final Object object) {
 466         if (object instanceof StaticClass) {
 467             // static properties of the given class
 468             final Class<?> clazz = ((StaticClass)object).getRepresentedClass();
 469             final ArrayList<String> props = new ArrayList<>();
 470             try {
 471                 Bootstrap.checkReflectionAccess(clazz, true);
 472                 // Usually writable properties are a subset as 'write-only' properties are rare
 473                 props.addAll(BeansLinker.getReadableStaticPropertyNames(clazz));
 474                 props.addAll(BeansLinker.getStaticMethodNames(clazz));
 475             } catch (final Exception ignored) {}
 476             return props;
 477         } else if (object instanceof JSObject) {
 478             final JSObject jsObj = ((JSObject)object);
 479             final ArrayList<String> props = new ArrayList<>();
 480             props.addAll(jsObj.keySet());
 481             return props;
 482         } else if (object != null && object != UNDEFINED) {
 483             // instance properties of the given object
 484             final Class<?> clazz = object.getClass();
 485             final ArrayList<String> props = new ArrayList<>();
 486             try {
 487                 Bootstrap.checkReflectionAccess(clazz, false);
 488                 // Usually writable properties are a subset as 'write-only' properties are rare
 489                 props.addAll(BeansLinker.getReadableInstancePropertyNames(clazz));
 490                 props.addAll(BeansLinker.getInstanceMethodNames(clazz));
 491             } catch (final Exception ignored) {}
 492             return props;
 493         }
 494 
 495         // don't know about that object
 496         return Collections.<String>emptyList();
 497     }
 498 
 499     private static int[] copyArray(final byte[] in) {
 500         final int[] out = new int[in.length];
 501         for(int i = 0; i < in.length; ++i) {
 502             out[i] = in[i];
 503         }
 504         return out;
 505     }
 506 
 507     private static int[] copyArray(final short[] in) {
 508         final int[] out = new int[in.length];
 509         for(int i = 0; i < in.length; ++i) {
 510             out[i] = in[i];
 511         }
 512         return out;
 513     }
 514 
 515     private static int[] copyArray(final char[] in) {
 516         final int[] out = new int[in.length];
 517         for(int i = 0; i < in.length; ++i) {
 518             out[i] = in[i];
 519         }
 520         return out;
 521     }
 522 
 523     private static double[] copyArray(final float[] in) {
 524         final double[] out = new double[in.length];
 525         for(int i = 0; i < in.length; ++i) {
 526             out[i] = in[i];
 527         }
 528         return out;
 529     }
 530 
 531     private static Object[] copyArray(final boolean[] in) {
 532         final Object[] out = new Object[in.length];
 533         for(int i = 0; i < in.length; ++i) {
 534             out[i] = in[i];
 535         }
 536         return out;
 537     }
 538 
 539     private static Class<?> simpleType(final String typeName) throws ClassNotFoundException {
 540         final Class<?> primClass = TypeUtilities.getPrimitiveTypeByName(typeName);
 541         if(primClass != null) {
 542             return primClass;
 543         }
 544         final Context ctx = Global.getThisContext();
 545         try {
 546             return ctx.findClass(typeName);
 547         } catch(final ClassNotFoundException e) {
 548             // The logic below compensates for a frequent user error - when people use dot notation to separate inner
 549             // class names, i.e. "java.lang.Character.UnicodeBlock" vs."java.lang.Character$UnicodeBlock". The logic
 550             // below will try alternative class names, replacing dots at the end of the name with dollar signs.
 551             final StringBuilder nextName = new StringBuilder(typeName);
 552             int lastDot = nextName.length();
 553             for(;;) {
 554                 lastDot = nextName.lastIndexOf(".", lastDot - 1);
 555                 if(lastDot == -1) {
 556                     // Exhausted the search space, class not found - rethrow the original exception.
 557                     throw e;
 558                 }
 559                 nextName.setCharAt(lastDot, '$');
 560                 try {
 561                     return ctx.findClass(nextName.toString());
 562                 } catch(final ClassNotFoundException cnfe) {
 563                     // Intentionally ignored, so the loop retries with the next name
 564                 }
 565             }
 566         }
 567 
 568     }
 569 
 570     private static Class<?> arrayType(final String typeName) throws ClassNotFoundException {
 571         return Array.newInstance(type(typeName.substring(0, typeName.length() - 2)), 0).getClass();
 572     }
 573 
 574     /**
 575      * Returns a type object for a subclass of the specified Java class (or implementation of the specified interface)
 576      * that acts as a script-to-Java adapter for it. See {@link #type(Object, Object)} for a discussion of type objects,
 577      * and see {@link JavaAdapterFactory} for details on script-to-Java adapters. Note that you can also implement
 578      * interfaces and subclass abstract classes using {@code new} operator on a type object for an interface or abstract
 579      * class. However, to extend a non-abstract class, you will have to use this method. Example:
 580      * <pre>
 581      * var ArrayList = Java.type("java.util.ArrayList")
 582      * var ArrayListExtender = Java.extend(ArrayList)
 583      * var printSizeInvokedArrayList = new ArrayListExtender() {
 584      *     size: function() { print("size invoked!"); }
 585      * }
 586      * var printAddInvokedArrayList = new ArrayListExtender() {
 587      *     add: function(x, y) {
 588      *       if(typeof(y) === "undefined") {
 589      *           print("add(e) invoked!");
 590      *       } else {
 591      *           print("add(i, e) invoked!");
 592      *       }
 593      * }
 594      * </pre>
 595      * We can see several important concepts in the above example:
 596      * <ul>
 597      * <li>Every specified list of Java types will have one extender subclass in Nashorn per caller protection domain -
 598      * repeated invocations of {@code extend} for the same list of types for scripts same protection domain will yield
 599      * the same extender type. It's a generic adapter that delegates to whatever JavaScript functions its implementation
 600      * object has on a per-instance basis.</li>
 601      * <li>If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter
 602      * must be prepared to deal with all overloads.</li>
 603      * <li>To invoke super methods from adapters, call them on the adapter instance prefixing them with {@code super$},
 604      * or use the special {@link #_super(Object, Object) super-adapter}.</li>
 605      * <li>It is also possible to specify an ordinary JavaScript object as the last argument to {@code extend}. In that
 606      * case, it is treated as a class-level override. {@code extend} will return an extender class where all instances
 607      * will have the methods implemented by functions on that object, just as if that object were passed as the last
 608      * argument to their constructor. Example:
 609      * <pre>
 610      * var Runnable = Java.type("java.lang.Runnable")
 611      * var R1 = Java.extend(Runnable, {
 612      *     run: function() {
 613      *         print("R1.run() invoked!")
 614      *     }
 615      * })
 616      * var r1 = new R1
 617      * var t = new java.lang.Thread(r1)
 618      * t.start()
 619      * t.join()
 620      * </pre>
 621      * As you can see, you don't have to pass any object when you create a new instance of {@code R1} as its
 622      * {@code run()} function was defined already when extending the class. If you also want to add instance-level
 623      * overrides on these objects, you will have to repeatedly use {@code extend()} to subclass the class-level adapter.
 624      * For such adapters, the order of precedence is instance-level method, class-level method, superclass method, or
 625      * {@code UnsupportedOperationException} if the superclass method is abstract. If we continue our previous example:
 626      * <pre>
 627      * var R2 = Java.extend(R1);
 628      * var r2 = new R2(function() { print("r2.run() invoked!") })
 629      * r2.run()
 630      * </pre>
 631      * We'll see it'll print {@code "r2.run() invoked!"}, thus overriding on instance-level the class-level behavior.
 632      * Note that you must use {@code Java.extend} to explicitly create an instance-override adapter class from a
 633      * class-override adapter class, as the class-override adapter class is no longer abstract.
 634      * </li>
 635      * </ul>
 636      * @param self not used
 637      * @param types the original types. The caller must pass at least one Java type object of class {@link StaticClass}
 638      * representing either a public interface or a non-final public class with at least one public or protected
 639      * constructor. If more than one type is specified, at most one can be a class and the rest have to be interfaces.
 640      * Invoking the method twice with exactly the same types in the same order - in absence of class-level overrides -
 641      * will return the same adapter class, any reordering of types or even addition or removal of redundant types (i.e.
 642      * interfaces that other types in the list already implement/extend, or {@code java.lang.Object} in a list of types
 643      * consisting purely of interfaces) will result in a different adapter class, even though those adapter classes are
 644      * functionally identical; we deliberately don't want to incur the additional processing cost of canonicalizing type
 645      * lists. As a special case, the last argument can be a {@code ScriptObject} instead of a type. In this case, a
 646      * separate adapter class is generated - new one for each invocation - that will use the passed script object as its
 647      * implementation for all instances. Instances of such adapter classes can then be created without passing another
 648      * script object in the constructor, as the class has a class-level behavior defined by the script object. However,
 649      * you can still pass a script object (or if it's a SAM type, a function) to the constructor to provide further
 650      * instance-level overrides.
 651      *
 652      * @return a new {@link StaticClass} that represents the adapter for the original types.
 653      */
 654     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 655     public static Object extend(final Object self, final Object... types) {
 656         if(types == null || types.length == 0) {
 657             throw typeError("extend.expects.at.least.one.argument");
 658         }
 659         final int l = types.length;
 660         final int typesLen;
 661         final ScriptObject classOverrides;
 662         if(types[l - 1] instanceof ScriptObject) {
 663             classOverrides = (ScriptObject)types[l - 1];
 664             typesLen = l - 1;
 665             if(typesLen == 0) {
 666                 throw typeError("extend.expects.at.least.one.type.argument");
 667             }
 668         } else {
 669             classOverrides = null;
 670             typesLen = l;
 671         }
 672         final Class<?>[] stypes = new Class<?>[typesLen];
 673         try {
 674             for(int i = 0; i < typesLen; ++i) {
 675                 stypes[i] = ((StaticClass)types[i]).getRepresentedClass();
 676             }
 677         } catch(final ClassCastException e) {
 678             throw typeError("extend.expects.java.types");
 679         }
 680         // Note that while the public API documentation claims self is not used, we actually use it.
 681         // ScriptFunction.findCallMethod will bind the lookup object into it, and we can then use that lookup when
 682         // requesting the adapter class. Note that if Java.extend is invoked with no lookup object, it'll pass the
 683         // public lookup which'll result in generation of a no-permissions adapter. A typical situation this can happen
 684         // is when the extend function is bound.
 685         final MethodHandles.Lookup lookup;
 686         if(self instanceof MethodHandles.Lookup) {
 687             lookup = (MethodHandles.Lookup)self;
 688         } else {
 689             lookup = MethodHandles.publicLookup();
 690         }
 691         return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides, lookup);
 692     }
 693 
 694     /**
 695      * When given an object created using {@code Java.extend()} or equivalent mechanism (that is, any JavaScript-to-Java
 696      * adapter), returns an object that can be used to invoke superclass methods on that object. E.g.:
 697      * <pre>
 698      * var cw = new FilterWriterAdapter(sw) {
 699      *     write: function(s, off, len) {
 700      *         s = capitalize(s, off, len)
 701      *         cw_super.write(s, 0, s.length())
 702      *     }
 703      * }
 704      * var cw_super = Java.super(cw)
 705      * </pre>
 706      * @param self the {@code Java} object itself - not used.
 707      * @param adapter the original Java adapter instance for which the super adapter is created.
 708      * @return a super adapter for the original adapter
 709      */
 710     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR, name="super")
 711     public static Object _super(final Object self, final Object adapter) {
 712         return Bootstrap.createSuperAdapter(adapter);
 713     }
 714 
 715     /**
 716      * Returns an object that is compatible with Java JSON libraries expectations; namely, that if it itself, or any
 717      * object transitively reachable through it is a JavaScript array, then such objects will be exposed as
 718      * {@link JSObject} that also implements the {@link List} interface for exposing the array elements. An explicit
 719      * API is required as otherwise Nashorn exposes all objects externally as {@link JSObject}s that also implement the
 720      * {@link Map} interface instead. By using this method, arrays will be exposed as {@link List}s and all other
 721      * objects as {@link Map}s.
 722      * @param self not used
 723      * @param obj the object to be exposed in a Java JSON library compatible manner.
 724      * @return a wrapper around the object that will enforce Java JSON library compatible exposure.
 725      */
 726     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
 727     public static Object asJSONCompatible(final Object self, final Object obj) {
 728         return ScriptObjectMirror.wrapAsJSONCompatible(obj, Context.getGlobal());
 729     }
 730 }