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