NativeJava.java revision 1297:92f7bf49eb65
1169689Skan/*
2169689Skan * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3169689Skan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4169689Skan *
5169689Skan * This code is free software; you can redistribute it and/or modify it
6169689Skan * under the terms of the GNU General Public License version 2 only, as
7169689Skan * published by the Free Software Foundation.  Oracle designates this
8169689Skan * particular file as subject to the "Classpath" exception as provided
9169689Skan * by Oracle in the LICENSE file that accompanied this code.
10169689Skan *
11169689Skan * This code is distributed in the hope that it will be useful, but WITHOUT
12169689Skan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13169689Skan * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14169689Skan * version 2 for more details (a copy is included in the LICENSE file that
15169689Skan * accompanied this code).
16169689Skan *
17169689Skan * You should have received a copy of the GNU General Public License version
18169689Skan * 2 along with this work; if not, write to the Free Software Foundation,
19169689Skan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20169689Skan *
21169689Skan * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22169689Skan * or visit www.oracle.com if you need additional information or have any
23169689Skan * questions.
24169689Skan */
25169689Skan
26169689Skanpackage jdk.nashorn.internal.objects;
27169689Skan
28169689Skanimport static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
29169689Skanimport static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
30169689Skan
31169689Skanimport java.lang.invoke.MethodHandles;
32169689Skanimport java.lang.reflect.Array;
33169689Skanimport java.util.Collection;
34169689Skanimport java.util.Deque;
35169689Skanimport java.util.List;
36169689Skanimport java.util.Map;
37169689Skanimport java.util.Queue;
38169689Skanimport jdk.internal.dynalink.beans.StaticClass;
39169689Skanimport jdk.internal.dynalink.support.TypeUtilities;
40169689Skanimport jdk.nashorn.api.scripting.JSObject;
41169689Skanimport jdk.nashorn.api.scripting.ScriptObjectMirror;
42169689Skanimport jdk.nashorn.internal.objects.annotations.Attribute;
43169689Skanimport jdk.nashorn.internal.objects.annotations.Function;
44169689Skanimport jdk.nashorn.internal.objects.annotations.ScriptClass;
45169689Skanimport jdk.nashorn.internal.objects.annotations.Where;
46169689Skanimport jdk.nashorn.internal.runtime.Context;
47169689Skanimport jdk.nashorn.internal.runtime.JSType;
48169689Skanimport jdk.nashorn.internal.runtime.ListAdapter;
49169689Skanimport jdk.nashorn.internal.runtime.PropertyMap;
50169689Skanimport jdk.nashorn.internal.runtime.ScriptFunction;
51169689Skanimport jdk.nashorn.internal.runtime.ScriptObject;
52169689Skanimport jdk.nashorn.internal.runtime.ScriptRuntime;
53169689Skanimport jdk.nashorn.internal.runtime.linker.Bootstrap;
54169689Skanimport jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
55169689Skan
56169689Skan/**
57169689Skan * This class is the implementation for the {@code Java} global object exposed to programs running under Nashorn. This
58169689Skan * object acts as the API entry point to Java platform specific functionality, dealing with creating new instances of
59169689Skan * Java classes, subclassing Java classes, implementing Java interfaces, converting between Java arrays and ECMAScript
60169689Skan * arrays, and so forth.
61169689Skan */
62169689Skan@ScriptClass("Java")
63169689Skanpublic final class NativeJava {
64169689Skan
65169689Skan    // initialized by nasgen
66169689Skan    @SuppressWarnings("unused")
67169689Skan    private static PropertyMap $nasgenmap$;
68169689Skan
69169689Skan    private NativeJava() {
70169689Skan        // don't create me
71169689Skan        throw new UnsupportedOperationException();
72169689Skan    }
73169689Skan
74169689Skan    /**
75169689Skan     * Returns true if the specified object is a Java type object, that is an instance of {@link StaticClass}.
76169689Skan     * @param self not used
77169689Skan     * @param type the object that is checked if it is a type object or not
78169689Skan     * @return tells whether given object is a Java type object or not.
79169689Skan     * @see #type(Object, Object)
80169689Skan     */
81169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
82169689Skan    public static boolean isType(final Object self, final Object type) {
83169689Skan        return type instanceof StaticClass;
84169689Skan    }
85169689Skan
86169689Skan    /**
87169689Skan     * Returns synchronized wrapper version of the given ECMAScript function.
88169689Skan     * @param self not used
89169689Skan     * @param func the ECMAScript function whose synchronized version is returned.
90169689Skan     * @param obj the object (i.e, lock) on which the function synchronizes.
91169689Skan     * @return synchronized wrapper version of the given ECMAScript function.
92169689Skan     */
93169689Skan    @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
94169689Skan    public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
95169689Skan        if (func instanceof ScriptFunction) {
96169689Skan            return ((ScriptFunction)func).makeSynchronizedFunction(obj);
97169689Skan        }
98169689Skan
99169689Skan        throw typeError("not.a.function", ScriptRuntime.safeToString(func));
100169689Skan    }
101169689Skan
102169689Skan    /**
103169689Skan     * Returns true if the specified object is a Java method.
104169689Skan     * @param self not used
105169689Skan     * @param obj the object that is checked if it is a Java method object or not
106169689Skan     * @return tells whether given object is a Java method object or not.
107169689Skan     */
108169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
109169689Skan    public static boolean isJavaMethod(final Object self, final Object obj) {
110169689Skan        return Bootstrap.isDynamicMethod(obj);
111169689Skan    }
112169689Skan
113169689Skan    /**
114169689Skan     * Returns true if the specified object is a java function (but not script function)
115169689Skan     * @param self not used
116169689Skan     * @param obj the object that is checked if it is a Java function or not
117169689Skan     * @return tells whether given object is a Java function or not
118169689Skan     */
119169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
120169689Skan    public static boolean isJavaFunction(final Object self, final Object obj) {
121169689Skan        return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
122169689Skan    }
123169689Skan
124169689Skan    /**
125169689Skan     * Returns true if the specified object is a Java object but not a script object
126169689Skan     * @param self not used
127169689Skan     * @param obj the object that is checked
128169689Skan     * @return tells whether given object is a Java object but not a script object
129169689Skan     */
130169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
131169689Skan    public static boolean isJavaObject(final Object self, final Object obj) {
132169689Skan        return obj != null && !(obj instanceof ScriptObject);
133169689Skan    }
134169689Skan
135169689Skan    /**
136169689Skan     * Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
137169689Skan     * @param self not used
138169689Skan     * @param obj the object that is checked if it is a ECMAScript object or not
139169689Skan     * @return tells whether given object is a ECMAScript object or not.
140169689Skan     */
141169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
142169689Skan    public static boolean isScriptObject(final Object self, final Object obj) {
143169689Skan        return obj instanceof ScriptObject;
144169689Skan    }
145169689Skan
146169689Skan    /**
147169689Skan     * Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
148169689Skan     * @param self not used
149169689Skan     * @param obj the object that is checked if it is a ECMAScript function or not
150169689Skan     * @return tells whether given object is a ECMAScript function or not.
151169689Skan     */
152169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
153169689Skan    public static boolean isScriptFunction(final Object self, final Object obj) {
154169689Skan        return obj instanceof ScriptFunction;
155169689Skan    }
156169689Skan
157169689Skan    /**
158169689Skan     * <p>
159169689Skan     * Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
160169689Skan     * used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
161169689Skan     * the objects that you can use with the {@code new} operator to create new instances of the class as well as to
162169689Skan     * access static members of the class. In Nashorn, {@code Class} objects are just regular Java objects that aren't
163169689Skan     * treated specially. Instead of them, {@link StaticClass} instances - which we sometimes refer to as "Java type
164169689Skan     * objects" are used as constructors with the {@code new} operator, and they expose static fields, properties, and
165169689Skan     * methods. While this might seem confusing at first, it actually closely matches the Java language: you use a
166169689Skan     * different expression (e.g. {@code java.io.File}) as an argument in "new" and to address statics, and it is
167169689Skan     * distinct from the {@code Class} object (e.g. {@code java.io.File.class}). Below we cover in details the
168169689Skan     * properties of the type objects.
169169689Skan     * </p>
170169689Skan     * <p><b>Constructing Java objects</b></p>
171169689Skan     * Examples:
172169689Skan     * <pre>
173169689Skan     * var arrayListType = Java.type("java.util.ArrayList")
174169689Skan     * var intType = Java.type("int")
175169689Skan     * var stringArrayType = Java.type("java.lang.String[]")
176169689Skan     * var int2DArrayType = Java.type("int[][]")
177169689Skan     * </pre>
178169689Skan     * Note that the name of the type is always a string for a fully qualified name. You can use any of these types to
179169689Skan     * create new instances, e.g.:
180169689Skan     * <pre>
181169689Skan     * var anArrayList = new Java.type("java.util.ArrayList")
182169689Skan     * </pre>
183169689Skan     * or
184169689Skan     * <pre>
185169689Skan     * var ArrayList = Java.type("java.util.ArrayList")
186169689Skan     * var anArrayList = new ArrayList
187169689Skan     * var anArrayListWithSize = new ArrayList(16)
188169689Skan     * </pre>
189169689Skan     * In the special case of inner classes, you can either use the JVM fully qualified name, meaning using {@code $}
190169689Skan     * sign in the class name, or you can use the dot:
191169689Skan     * <pre>
192169689Skan     * var ftype = Java.type("java.awt.geom.Arc2D$Float")
193169689Skan     * </pre>
194169689Skan     * and
195169689Skan     * <pre>
196169689Skan     * var ftype = Java.type("java.awt.geom.Arc2D.Float")
197169689Skan     * </pre>
198169689Skan     * both work. Note however that using the dollar sign is faster, as Java.type first tries to resolve the class name
199169689Skan     * as it is originally specified, and the internal JVM names for inner classes use the dollar sign. If you use the
200169689Skan     * dot, Java.type will internally get a ClassNotFoundException and subsequently retry by changing the last dot to
201169689Skan     * dollar sign. As a matter of fact, it'll keep replacing dots with dollar signs until it either successfully loads
202169689Skan     * the class or runs out of all dots in the name. This way it can correctly resolve and load even multiply nested
203169689Skan     * inner classes with the dot notation. Again, this will be slower than using the dollar signs in the name. An
204169689Skan     * alternative way to access the inner class is as a property of the outer class:
205169689Skan     * <pre>
206169689Skan     * var arctype = Java.type("java.awt.geom.Arc2D")
207169689Skan     * var ftype = arctype.Float
208169689Skan     * </pre>
209169689Skan     * <p>
210169689Skan     * You can access both static and non-static inner classes. If you want to create an instance of a non-static
211169689Skan     * inner class, remember to pass an instance of its outer class as the first argument to the constructor.
212169689Skan     * </p>
213169689Skan     * <p>
214169689Skan     * If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is
215169689Skan     * applicable to any of its public or protected constructors, but inserting a JavaScript object with functions
216169689Skan     * properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the
217169689Skan     * JavaScript function will provide implementation for all overloads. E.g.:
218169689Skan     * </p>
219169689Skan     * <pre>
220169689Skan     * var TimerTask =  Java.type("java.util.TimerTask")
221169689Skan     * var task = new TimerTask({ run: function() { print("Hello World!") } })
222169689Skan     * </pre>
223169689Skan     * <p>
224169689Skan     * Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to
225169689Skan     * invoking the constructor and passing the argument to it, so you can write the above example also as:
226169689Skan     * </p>
227169689Skan     * <pre>
228169689Skan     * var task = new TimerTask {
229169689Skan     *     run: function() {
230169689Skan     *       print("Hello World!")
231169689Skan     *     }
232169689Skan     * }
233169689Skan     * </pre>
234169689Skan     * <p>
235169689Skan     * which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract
236169689Skan     * type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share
237169689Skan     * the same overloaded name), then instead of an object, you can just pass a function, so the above example can
238169689Skan     * become even more simplified to:
239169689Skan     * </p>
240169689Skan     * <pre>
241169689Skan     * var task = new TimerTask(function() { print("Hello World!") })
242169689Skan     * </pre>
243169689Skan     * <p>
244169689Skan     * Note that in every one of these cases if you are trying to instantiate an abstract class that has constructors
245169689Skan     * that take some arguments, you can invoke those simply by specifying the arguments after the initial
246169689Skan     * implementation object or function.
247169689Skan     * </p>
248169689Skan     * <p>The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type,
249169689Skan     * you can just pass in a function object, and Nashorn will know what you meant:
250169689Skan     * </p>
251169689Skan     * <pre>
252169689Skan     * var timer = new Java.type("java.util.Timer")
253169689Skan     * timer.schedule(function() { print("Hello World!") })
254169689Skan     * </pre>
255169689Skan     * <p>
256169689Skan     * Here, {@code Timer.schedule()} expects a {@code TimerTask} as its argument, so Nashorn creates an instance of a
257169689Skan     * {@code TimerTask} subclass and uses the passed function to implement its only abstract method, {@code run()}. In
258169689Skan     * this usage though, you can't use non-default constructors; the type must be either an interface, or must have a
259169689Skan     * protected or public no-arg constructor.
260169689Skan     * </p>
261169689Skan     * <p>
262169689Skan     * You can also subclass non-abstract classes; for that you will need to use the {@link #extend(Object, Object...)}
263169689Skan     * method.
264169689Skan     * </p>
265169689Skan     * <p><b>Accessing static members</b></p>
266169689Skan     * Examples:
267169689Skan     * <pre>
268169689Skan     * var File = Java.type("java.io.File")
269169689Skan     * var pathSep = File.pathSeparator
270169689Skan     * var tmpFile1 = File.createTempFile("abcdefg", ".tmp")
271169689Skan     * var tmpFile2 = File.createTempFile("abcdefg", ".tmp", new File("/tmp"))
272169689Skan     * </pre>
273169689Skan     * Actually, you can even assign static methods to variables, so the above example can be rewritten as:
274169689Skan     * <pre>
275169689Skan     * var File = Java.type("java.io.File")
276169689Skan     * var createTempFile = File.createTempFile
277169689Skan     * var tmpFile1 = createTempFile("abcdefg", ".tmp")
278169689Skan     * var tmpFile2 = createTempFile("abcdefg", ".tmp", new File("/tmp"))
279169689Skan     * </pre>
280169689Skan     * If you need to access the actual {@code java.lang.Class} object for the type, you can use the {@code class}
281169689Skan     * property on the object representing the type:
282169689Skan     * <pre>
283169689Skan     * var File = Java.type("java.io.File")
284169689Skan     * var someFile = new File("blah")
285169689Skan     * print(File.class === someFile.getClass()) // prints true
286169689Skan     * </pre>
287169689Skan     * Of course, you can also use the {@code getClass()} method or its equivalent {@code class} property on any
288169689Skan     * instance of the class. Other way round, you can use the synthetic {@code static} property on any
289169689Skan     * {@code java.lang.Class} object to retrieve its type-representing object:
290169689Skan     * <pre>
291169689Skan     * var File = Java.type("java.io.File")
292169689Skan     * print(File.class.static === File) // prints true
293169689Skan     * </pre>
294169689Skan     * <p><b>{@code instanceof} operator</b></p>
295169689Skan     * The standard ECMAScript {@code instanceof} operator is extended to recognize Java objects and their type objects:
296169689Skan     * <pre>
297169689Skan     * var File = Java.type("java.io.File")
298169689Skan     * var aFile = new File("foo")
299169689Skan     * print(aFile instanceof File) // prints true
300169689Skan     * print(aFile instanceof File.class) // prints false - Class objects aren't type objects.
301169689Skan     * </pre>
302169689Skan     * @param self not used
303169689Skan     * @param objTypeName the object whose JS string value represents the type name. You can use names of primitive Java
304169689Skan     * types to obtain representations of them, and you can use trailing square brackets to represent Java array types.
305169689Skan     * @return the object representing the named type
306169689Skan     * @throws ClassNotFoundException if the class is not found
307169689Skan     */
308169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
309169689Skan    public static Object type(final Object self, final Object objTypeName) throws ClassNotFoundException {
310169689Skan        return type(objTypeName);
311169689Skan    }
312169689Skan
313169689Skan    private static StaticClass type(final Object objTypeName) throws ClassNotFoundException {
314169689Skan        return StaticClass.forClass(type(JSType.toString(objTypeName)));
315169689Skan    }
316169689Skan
317169689Skan    private static Class<?> type(final String typeName) throws ClassNotFoundException {
318169689Skan        if (typeName.endsWith("[]")) {
319169689Skan            return arrayType(typeName);
320169689Skan        }
321169689Skan
322169689Skan        return simpleType(typeName);
323169689Skan    }
324169689Skan
325169689Skan    /**
326169689Skan     * Returns name of a java type {@link StaticClass}.
327169689Skan     * @param self not used
328169689Skan     * @param type the type whose name is returned
329169689Skan     * @return name of the given type
330169689Skan     */
331169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
332169689Skan    public static Object typeName(final Object self, final Object type) {
333169689Skan        if (type instanceof StaticClass) {
334169689Skan            return ((StaticClass)type).getRepresentedClass().getName();
335169689Skan        } else if (type instanceof Class) {
336169689Skan            return ((Class<?>)type).getName();
337169689Skan        } else {
338169689Skan            return UNDEFINED;
339169689Skan        }
340169689Skan    }
341169689Skan
342169689Skan    /**
343169689Skan     * Given a script object and a Java type, converts the script object into the desired Java type. Currently it
344169689Skan     * performs shallow creation of Java arrays, as well as wrapping of objects in Lists, Dequeues, Queues,
345169689Skan     * and Collections. Example:
346169689Skan     * <pre>
347169689Skan     * var anArray = [1, "13", false]
348169689Skan     * var javaIntArray = Java.to(anArray, "int[]")
349169689Skan     * print(javaIntArray[0]) // prints 1
350169689Skan     * print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
351169689Skan     * print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
352169689Skan     * </pre>
353169689Skan     * @param self not used
354169689Skan     * @param obj the script object. Can be null.
355169689Skan     * @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java
356169689Skan     * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
357169689Skan     * omitted).
358169689Skan     * @return a Java object whose value corresponds to the original script object's value. Specifically, for array
359169689Skan     * target types, returns a Java array of the same type with contents converted to the array's component type.
360169689Skan     * Converts recursively when the target type is multidimensional array. For {@link List}, {@link Deque},
361169689Skan     * {@link Queue}, or {@link Collection}, returns a live wrapper around the object, see {@link ListAdapter} for
362169689Skan     * details. Returns null if obj is null.
363169689Skan     * @throws ClassNotFoundException if the class described by objType is not found
364169689Skan     */
365169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
366169689Skan    public static Object to(final Object self, final Object obj, final Object objType) throws ClassNotFoundException {
367169689Skan        if (obj == null) {
368169689Skan            return null;
369169689Skan        }
370169689Skan
371169689Skan        if (!(obj instanceof ScriptObject) && !(obj instanceof JSObject)) {
372169689Skan            throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
373169689Skan        }
374169689Skan
375169689Skan        final Class<?> targetClass;
376169689Skan        if(objType == UNDEFINED) {
377169689Skan            targetClass = Object[].class;
378169689Skan        } else {
379169689Skan            final StaticClass targetType;
380169689Skan            if(objType instanceof StaticClass) {
381169689Skan                targetType = (StaticClass)objType;
382169689Skan            } else {
383169689Skan                targetType = type(objType);
384169689Skan            }
385169689Skan            targetClass = targetType.getRepresentedClass();
386169689Skan        }
387169689Skan
388169689Skan        if(targetClass.isArray()) {
389169689Skan            return JSType.toJavaArray(obj, targetClass.getComponentType());
390169689Skan        }
391169689Skan
392169689Skan        if (targetClass == List.class || targetClass == Deque.class || targetClass == Queue.class || targetClass == Collection.class) {
393169689Skan            return ListAdapter.create(obj);
394169689Skan        }
395169689Skan
396169689Skan        throw typeError("unsupported.java.to.type", targetClass.getName());
397169689Skan    }
398169689Skan
399169689Skan    /**
400169689Skan     * Given a Java array or {@link Collection}, returns a JavaScript array with a shallow copy of its contents. Note
401169689Skan     * that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you
402169689Skan     * need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will
403169689Skan     * want to use this method. Example:
404169689Skan     * <pre>
405169689Skan     * var File = Java.type("java.io.File")
406169689Skan     * var listHomeDir = new File("~").listFiles()
407169689Skan     * var jsListHome = Java.from(listHomeDir)
408169689Skan     * var jpegModifiedDates = jsListHome
409169689Skan     *     .filter(function(val) { return val.getName().endsWith(".jpg") })
410169689Skan     *     .map(function(val) { return val.lastModified() })
411169689Skan     * </pre>
412169689Skan     * @param self not used
413169689Skan     * @param objArray the java array or collection. Can be null.
414169689Skan     * @return a JavaScript array with the copy of Java array's or collection's contents. Returns null if objArray is
415169689Skan     * null.
416169689Skan     */
417169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
418169689Skan    public static NativeArray from(final Object self, final Object objArray) {
419169689Skan        if (objArray == null) {
420169689Skan            return null;
421169689Skan        } else if (objArray instanceof Collection) {
422169689Skan            return new NativeArray(((Collection<?>)objArray).toArray());
423169689Skan        } else if (objArray instanceof Object[]) {
424169689Skan            return new NativeArray(((Object[])objArray).clone());
425169689Skan        } else if (objArray instanceof int[]) {
426169689Skan            return new NativeArray(((int[])objArray).clone());
427169689Skan        } else if (objArray instanceof double[]) {
428169689Skan            return new NativeArray(((double[])objArray).clone());
429169689Skan        } else if (objArray instanceof long[]) {
430169689Skan            return new NativeArray(((long[])objArray).clone());
431169689Skan        } else if (objArray instanceof byte[]) {
432169689Skan            return new NativeArray(copyArray((byte[])objArray));
433169689Skan        } else if (objArray instanceof short[]) {
434169689Skan            return new NativeArray(copyArray((short[])objArray));
435169689Skan        } else if (objArray instanceof char[]) {
436169689Skan            return new NativeArray(copyArray((char[])objArray));
437169689Skan        } else if (objArray instanceof float[]) {
438169689Skan            return new NativeArray(copyArray((float[])objArray));
439169689Skan        } else if (objArray instanceof boolean[]) {
440169689Skan            return new NativeArray(copyArray((boolean[])objArray));
441169689Skan        }
442169689Skan
443169689Skan        throw typeError("cant.convert.to.javascript.array", objArray.getClass().getName());
444169689Skan    }
445169689Skan
446169689Skan    private static int[] copyArray(final byte[] in) {
447169689Skan        final int[] out = new int[in.length];
448169689Skan        for(int i = 0; i < in.length; ++i) {
449169689Skan            out[i] = in[i];
450169689Skan        }
451169689Skan        return out;
452169689Skan    }
453169689Skan
454169689Skan    private static int[] copyArray(final short[] in) {
455169689Skan        final int[] out = new int[in.length];
456169689Skan        for(int i = 0; i < in.length; ++i) {
457169689Skan            out[i] = in[i];
458169689Skan        }
459169689Skan        return out;
460169689Skan    }
461169689Skan
462169689Skan    private static int[] copyArray(final char[] in) {
463169689Skan        final int[] out = new int[in.length];
464169689Skan        for(int i = 0; i < in.length; ++i) {
465169689Skan            out[i] = in[i];
466169689Skan        }
467169689Skan        return out;
468169689Skan    }
469169689Skan
470169689Skan    private static double[] copyArray(final float[] in) {
471169689Skan        final double[] out = new double[in.length];
472169689Skan        for(int i = 0; i < in.length; ++i) {
473169689Skan            out[i] = in[i];
474169689Skan        }
475169689Skan        return out;
476169689Skan    }
477169689Skan
478169689Skan    private static Object[] copyArray(final boolean[] in) {
479169689Skan        final Object[] out = new Object[in.length];
480169689Skan        for(int i = 0; i < in.length; ++i) {
481169689Skan            out[i] = in[i];
482169689Skan        }
483169689Skan        return out;
484169689Skan    }
485169689Skan
486169689Skan    private static Class<?> simpleType(final String typeName) throws ClassNotFoundException {
487169689Skan        final Class<?> primClass = TypeUtilities.getPrimitiveTypeByName(typeName);
488169689Skan        if(primClass != null) {
489169689Skan            return primClass;
490169689Skan        }
491169689Skan        final Context ctx = Global.getThisContext();
492169689Skan        try {
493169689Skan            return ctx.findClass(typeName);
494169689Skan        } catch(final ClassNotFoundException e) {
495169689Skan            // The logic below compensates for a frequent user error - when people use dot notation to separate inner
496169689Skan            // class names, i.e. "java.lang.Character.UnicodeBlock" vs."java.lang.Character$UnicodeBlock". The logic
497169689Skan            // below will try alternative class names, replacing dots at the end of the name with dollar signs.
498169689Skan            final StringBuilder nextName = new StringBuilder(typeName);
499169689Skan            int lastDot = nextName.length();
500169689Skan            for(;;) {
501169689Skan                lastDot = nextName.lastIndexOf(".", lastDot - 1);
502169689Skan                if(lastDot == -1) {
503169689Skan                    // Exhausted the search space, class not found - rethrow the original exception.
504169689Skan                    throw e;
505169689Skan                }
506169689Skan                nextName.setCharAt(lastDot, '$');
507169689Skan                try {
508169689Skan                    return ctx.findClass(nextName.toString());
509169689Skan                } catch(final ClassNotFoundException cnfe) {
510169689Skan                    // Intentionally ignored, so the loop retries with the next name
511169689Skan                }
512169689Skan            }
513169689Skan        }
514169689Skan
515169689Skan    }
516169689Skan
517169689Skan    private static Class<?> arrayType(final String typeName) throws ClassNotFoundException {
518169689Skan        return Array.newInstance(type(typeName.substring(0, typeName.length() - 2)), 0).getClass();
519169689Skan    }
520169689Skan
521169689Skan    /**
522169689Skan     * Returns a type object for a subclass of the specified Java class (or implementation of the specified interface)
523169689Skan     * that acts as a script-to-Java adapter for it. See {@link #type(Object, Object)} for a discussion of type objects,
524169689Skan     * and see {@link JavaAdapterFactory} for details on script-to-Java adapters. Note that you can also implement
525169689Skan     * interfaces and subclass abstract classes using {@code new} operator on a type object for an interface or abstract
526169689Skan     * class. However, to extend a non-abstract class, you will have to use this method. Example:
527169689Skan     * <pre>
528169689Skan     * var ArrayList = Java.type("java.util.ArrayList")
529169689Skan     * var ArrayListExtender = Java.extend(ArrayList)
530169689Skan     * var printSizeInvokedArrayList = new ArrayListExtender() {
531169689Skan     *     size: function() { print("size invoked!"); }
532169689Skan     * }
533169689Skan     * var printAddInvokedArrayList = new ArrayListExtender() {
534169689Skan     *     add: function(x, y) {
535169689Skan     *       if(typeof(y) === "undefined") {
536169689Skan     *           print("add(e) invoked!");
537169689Skan     *       } else {
538169689Skan     *           print("add(i, e) invoked!");
539169689Skan     *       }
540169689Skan     * }
541169689Skan     * </pre>
542169689Skan     * We can see several important concepts in the above example:
543169689Skan     * <ul>
544169689Skan     * <li>Every specified list of Java types will have one extender subclass in Nashorn per caller protection domain -
545169689Skan     * repeated invocations of {@code extend} for the same list of types for scripts same protection domain will yield
546169689Skan     * the same extender type. It's a generic adapter that delegates to whatever JavaScript functions its implementation
547169689Skan     * object has on a per-instance basis.</li>
548169689Skan     * <li>If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter
549169689Skan     * must be prepared to deal with all overloads.</li>
550169689Skan     * <li>To invoke super methods from adapters, call them on the adapter instance prefixing them with {@code super$},
551169689Skan     * or use the special {@link #_super(Object, Object) super-adapter}.</li>
552169689Skan     * <li>It is also possible to specify an ordinary JavaScript object as the last argument to {@code extend}. In that
553169689Skan     * case, it is treated as a class-level override. {@code extend} will return an extender class where all instances
554169689Skan     * will have the methods implemented by functions on that object, just as if that object were passed as the last
555169689Skan     * argument to their constructor. Example:
556169689Skan     * <pre>
557169689Skan     * var Runnable = Java.type("java.lang.Runnable")
558169689Skan     * var R1 = Java.extend(Runnable, {
559169689Skan     *     run: function() {
560169689Skan     *         print("R1.run() invoked!")
561169689Skan     *     }
562169689Skan     * })
563169689Skan     * var r1 = new R1
564169689Skan     * var t = new java.lang.Thread(r1)
565169689Skan     * t.start()
566169689Skan     * t.join()
567169689Skan     * </pre>
568169689Skan     * As you can see, you don't have to pass any object when you create a new instance of {@code R1} as its
569169689Skan     * {@code run()} function was defined already when extending the class. If you also want to add instance-level
570169689Skan     * overrides on these objects, you will have to repeatedly use {@code extend()} to subclass the class-level adapter.
571169689Skan     * For such adapters, the order of precedence is instance-level method, class-level method, superclass method, or
572169689Skan     * {@code UnsupportedOperationException} if the superclass method is abstract. If we continue our previous example:
573169689Skan     * <pre>
574169689Skan     * var R2 = Java.extend(R1);
575169689Skan     * var r2 = new R2(function() { print("r2.run() invoked!") })
576169689Skan     * r2.run()
577169689Skan     * </pre>
578169689Skan     * We'll see it'll print {@code "r2.run() invoked!"}, thus overriding on instance-level the class-level behavior.
579169689Skan     * Note that you must use {@code Java.extend} to explicitly create an instance-override adapter class from a
580169689Skan     * class-override adapter class, as the class-override adapter class is no longer abstract.
581169689Skan     * </li>
582169689Skan     * </ul>
583169689Skan     * @param self not used
584169689Skan     * @param types the original types. The caller must pass at least one Java type object of class {@link StaticClass}
585169689Skan     * representing either a public interface or a non-final public class with at least one public or protected
586169689Skan     * constructor. If more than one type is specified, at most one can be a class and the rest have to be interfaces.
587169689Skan     * Invoking the method twice with exactly the same types in the same order - in absence of class-level overrides -
588169689Skan     * will return the same adapter class, any reordering of types or even addition or removal of redundant types (i.e.
589169689Skan     * interfaces that other types in the list already implement/extend, or {@code java.lang.Object} in a list of types
590169689Skan     * consisting purely of interfaces) will result in a different adapter class, even though those adapter classes are
591169689Skan     * functionally identical; we deliberately don't want to incur the additional processing cost of canonicalizing type
592169689Skan     * lists. As a special case, the last argument can be a {@code ScriptObject} instead of a type. In this case, a
593169689Skan     * separate adapter class is generated - new one for each invocation - that will use the passed script object as its
594169689Skan     * implementation for all instances. Instances of such adapter classes can then be created without passing another
595169689Skan     * script object in the constructor, as the class has a class-level behavior defined by the script object. However,
596169689Skan     * you can still pass a script object (or if it's a SAM type, a function) to the constructor to provide further
597169689Skan     * instance-level overrides.
598169689Skan     *
599169689Skan     * @return a new {@link StaticClass} that represents the adapter for the original types.
600169689Skan     */
601169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
602169689Skan    public static Object extend(final Object self, final Object... types) {
603169689Skan        if(types == null || types.length == 0) {
604169689Skan            throw typeError("extend.expects.at.least.one.argument");
605169689Skan        }
606169689Skan        final int l = types.length;
607169689Skan        final int typesLen;
608169689Skan        final ScriptObject classOverrides;
609169689Skan        if(types[l - 1] instanceof ScriptObject) {
610169689Skan            classOverrides = (ScriptObject)types[l - 1];
611169689Skan            typesLen = l - 1;
612169689Skan            if(typesLen == 0) {
613169689Skan                throw typeError("extend.expects.at.least.one.type.argument");
614169689Skan            }
615169689Skan        } else {
616169689Skan            classOverrides = null;
617169689Skan            typesLen = l;
618169689Skan        }
619169689Skan        final Class<?>[] stypes = new Class<?>[typesLen];
620169689Skan        try {
621169689Skan            for(int i = 0; i < typesLen; ++i) {
622169689Skan                stypes[i] = ((StaticClass)types[i]).getRepresentedClass();
623169689Skan            }
624169689Skan        } catch(final ClassCastException e) {
625169689Skan            throw typeError("extend.expects.java.types");
626169689Skan        }
627169689Skan        // Note that while the public API documentation claims self is not used, we actually use it.
628169689Skan        // ScriptFunction.findCallMethod will bind the lookup object into it, and we can then use that lookup when
629169689Skan        // requesting the adapter class. Note that if Java.extend is invoked with no lookup object, it'll pass the
630169689Skan        // public lookup which'll result in generation of a no-permissions adapter. A typical situation this can happen
631169689Skan        // is when the extend function is bound.
632169689Skan        final MethodHandles.Lookup lookup;
633169689Skan        if(self instanceof MethodHandles.Lookup) {
634169689Skan            lookup = (MethodHandles.Lookup)self;
635169689Skan        } else {
636169689Skan            lookup = MethodHandles.publicLookup();
637169689Skan        }
638169689Skan        return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides, lookup);
639169689Skan    }
640169689Skan
641169689Skan    /**
642169689Skan     * When given an object created using {@code Java.extend()} or equivalent mechanism (that is, any JavaScript-to-Java
643169689Skan     * adapter), returns an object that can be used to invoke superclass methods on that object. E.g.:
644169689Skan     * <pre>
645169689Skan     * var cw = new FilterWriterAdapter(sw) {
646169689Skan     *     write: function(s, off, len) {
647169689Skan     *         s = capitalize(s, off, len)
648169689Skan     *         cw_super.write(s, 0, s.length())
649169689Skan     *     }
650169689Skan     * }
651169689Skan     * var cw_super = Java.super(cw)
652169689Skan     * </pre>
653169689Skan     * @param self the {@code Java} object itself - not used.
654169689Skan     * @param adapter the original Java adapter instance for which the super adapter is created.
655169689Skan     * @return a super adapter for the original adapter
656169689Skan     */
657169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR, name="super")
658169689Skan    public static Object _super(final Object self, final Object adapter) {
659169689Skan        return Bootstrap.createSuperAdapter(adapter);
660169689Skan    }
661169689Skan
662169689Skan    /**
663169689Skan     * Returns an object that is compatible with Java JSON libraries expectations; namely, that if it itself, or any
664169689Skan     * object transitively reachable through it is a JavaScript array, then such objects will be exposed as
665169689Skan     * {@link JSObject} that also implements the {@link List} interface for exposing the array elements. An explicit
666169689Skan     * API is required as otherwise Nashorn exposes all objects externally as {@link JSObject}s that also implement the
667169689Skan     * {@link Map} interface instead. By using this method, arrays will be exposed as {@link List}s and all other
668169689Skan     * objects as {@link Map}s.
669169689Skan     * @param self not used
670169689Skan     * @param obj the object to be exposed in a Java JSON library compatible manner.
671169689Skan     * @return a wrapper around the object that will enforce Java JSON library compatible exposure.
672169689Skan     */
673169689Skan    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
674169689Skan    public static Object asJSONCompatible(final Object self, final Object obj) {
675169689Skan        return ScriptObjectMirror.wrapAsJSONCompatible(obj, Context.getGlobal());
676169689Skan    }
677169689Skan}
678169689Skan