nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
author sundar
Fri, 05 Jul 2013 14:38:04 +0530
changeset 18851 bdb92c95f886
parent 18846 4ef5f2321c67
child 19627 90d910ec15a3
permissions -rw-r--r--
8019947: inherited property invalidation does not work with two globals in same context Reviewed-by: jlaskey, lagergren, hannesw, attila
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     1
/*
16151
97c1e756ae1e 8005663: Update copyright year to 2013
jlaskey
parents: 16147
diff changeset
     2
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     4
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    10
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    15
 * accompanied this code).
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    16
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    20
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    23
 * questions.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    24
 */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    25
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    26
package jdk.nashorn.internal.objects;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    27
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    28
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    29
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    30
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    31
import java.lang.reflect.Array;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    32
import java.util.Collection;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
    33
import java.util.Deque;
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
    34
import java.util.List;
18842
3c3be808b593 8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
lagergren
parents: 18618
diff changeset
    35
16234
86cb162cec6c 8008085: Integrate Dynalink source code into Nashorn codebase
attila
parents: 16233
diff changeset
    36
import jdk.internal.dynalink.beans.StaticClass;
86cb162cec6c 8008085: Integrate Dynalink source code into Nashorn codebase
attila
parents: 16233
diff changeset
    37
import jdk.internal.dynalink.support.TypeUtilities;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    38
import jdk.nashorn.internal.objects.annotations.Attribute;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    39
import jdk.nashorn.internal.objects.annotations.Function;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    40
import jdk.nashorn.internal.objects.annotations.ScriptClass;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    41
import jdk.nashorn.internal.objects.annotations.Where;
18846
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
    42
import jdk.nashorn.internal.runtime.Context;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    43
import jdk.nashorn.internal.runtime.JSType;
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
    44
import jdk.nashorn.internal.runtime.ListAdapter;
18618
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17765
diff changeset
    45
import jdk.nashorn.internal.runtime.PropertyMap;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    46
import jdk.nashorn.internal.runtime.ScriptObject;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    47
import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    48
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    49
/**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    50
 * This class is the implementation for the {@code Java} global object exposed to programs running under Nashorn. This
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    51
 * object acts as the API entry point to Java platform specific functionality, dealing with creating new instances of
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    52
 * Java classes, subclassing Java classes, implementing Java interfaces, converting between Java arrays and ECMAScript
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    53
 * arrays, and so forth.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    54
 */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    55
@ScriptClass("Java")
16226
0e4f37e6cc40 8007915: Nashorn IR, codegen, parser packages and Context instance should be inaccessible to user code
sundar
parents: 16212
diff changeset
    56
public final class NativeJava {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    57
18618
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17765
diff changeset
    58
    // initialized by nasgen
18842
3c3be808b593 8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
lagergren
parents: 18618
diff changeset
    59
    @SuppressWarnings("unused")
18618
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17765
diff changeset
    60
    private static PropertyMap $nasgenmap$;
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17765
diff changeset
    61
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    62
    private NativeJava() {
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18846
diff changeset
    63
        // don't create me
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18846
diff changeset
    64
        throw new UnsupportedOperationException();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    65
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    66
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    67
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    68
     * Returns true if the specified object is a Java type object, that is an instance of {@link StaticClass}.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    69
     * @param self not used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    70
     * @param type the object that is checked if it is a type object or not
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    71
     * @return tells whether given object is a Java type object or not.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    72
     * @see #type(Object, Object)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    73
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    74
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    75
    public static Object isType(final Object self, final Object type) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    76
        return type instanceof StaticClass;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    77
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    78
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    79
    /**
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
    80
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    81
     * Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    82
     * used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    83
     * the objects that you can use with the {@code new} operator to create new instances of the class as well as to
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    84
     * access static members of the class. In Nashorn, {@code Class} objects are just regular Java objects that aren't
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    85
     * treated specially. Instead of them, {@link StaticClass} instances - which we sometimes refer to as "Java type
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    86
     * objects" are used as constructors with the {@code new} operator, and they expose static fields, properties, and
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    87
     * methods. While this might seem confusing at first, it actually closely matches the Java language: you use a
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    88
     * different expression (e.g. {@code java.io.File}) as an argument in "new" and to address statics, and it is
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    89
     * distinct from the {@code Class} object (e.g. {@code java.io.File.class}). Below we cover in details the
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    90
     * properties of the type objects.
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
    91
     * </p>
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
    92
     * <p><b>Constructing Java objects</b></p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    93
     * Examples:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    94
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    95
     * var arrayListType = Java.type("java.util.ArrayList")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    96
     * var intType = Java.type("int")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    97
     * var stringArrayType = Java.type("java.lang.String[]")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    98
     * var int2DArrayType = Java.type("int[][]")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    99
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   100
     * Note that the name of the type is always a string for a fully qualified name. You can use any of these types to
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   101
     * create new instances, e.g.:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   102
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   103
     * var anArrayList = new Java.type("java.util.ArrayList")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   104
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   105
     * or
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   106
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   107
     * var ArrayList = Java.type("java.util.ArrayList")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   108
     * var anArrayList = new ArrayList
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   109
     * var anArrayListWithSize = new ArrayList(16)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   110
     * </pre>
18846
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   111
     * In the special case of inner classes, you can either use the JVM fully qualified name, meaning using {@code $}
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   112
     * sign in the class name, or you can use the dot:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   113
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   114
     * var ftype = Java.type("java.awt.geom.Arc2D$Float")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   115
     * </pre>
18846
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   116
     * and
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   117
     * <pre>
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   118
     * var ftype = Java.type("java.awt.geom.Arc2D.Float")
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   119
     * </pre>
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   120
     * both work. Note however that using the dollar sign is faster, as Java.type first tries to resolve the class name
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   121
     * as it is originally specified, and the internal JVM names for inner classes use the dollar sign. If you use the
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   122
     * dot, Java.type will internally get a ClassNotFoundException and subsequently retry by changing the last dot to
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   123
     * dollar sign. As a matter of fact, it'll keep replacing dots with dollar signs until it either successfully loads
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   124
     * the class or runs out of all dots in the name. This way it can correctly resolve and load even multiply nested
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   125
     * inner classes with the dot notation. Again, this will be slower than using the dollar signs in the name. An
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   126
     * alternative way to access the inner class is as a property of the outer class:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   127
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   128
     * var arctype = Java.type("java.awt.geom.Arc2D")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   129
     * var ftype = arctype.Float
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   130
     * </pre>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   131
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   132
     * You can access both static and non-static inner classes. If you want to create an instance of a non-static
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   133
     * inner class, remember to pass an instance of its outer class as the first argument to the constructor.
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   134
     * </p>
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   135
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   136
     * If the type is abstract, you can instantiate an anonymous subclass of it using an argument list that is
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   137
     * applicable to any of its public or protected constructors, but inserting a JavaScript object with functions
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   138
     * properties that provide JavaScript implementations of the abstract methods. If method names are overloaded, the
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   139
     * JavaScript function will provide implementation for all overloads. E.g.:
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   140
     * </p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   141
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   142
     * var TimerTask =  Java.type("java.util.TimerTask")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   143
     * var task = new TimerTask({ run: function() { print("Hello World!") } })
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   144
     * </pre>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   145
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   146
     * Nashorn supports a syntactic extension where a "new" expression followed by an argument is identical to
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   147
     * invoking the constructor and passing the argument to it, so you can write the above example also as:
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   148
     * </p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   149
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   150
     * var task = new TimerTask {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   151
     *     run: function() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   152
     *       print("Hello World!")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   153
     *     }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   154
     * }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   155
     * </pre>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   156
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   157
     * which is very similar to Java anonymous inner class definition. On the other hand, if the type is an abstract
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   158
     * type with a single abstract method (commonly referred to as a "SAM type") or all abstract methods it has share
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   159
     * the same overloaded name), then instead of an object, you can just pass a function, so the above example can
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   160
     * become even more simplified to:
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   161
     * </p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   162
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   163
     * var task = new TimerTask(function() { print("Hello World!") })
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   164
     * </pre>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   165
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   166
     * Note that in every one of these cases if you are trying to instantiate an abstract class that has constructors
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   167
     * that take some arguments, you can invoke those simply by specifying the arguments after the initial
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   168
     * implementation object or function.
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   169
     * </p>
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   170
     * <p>The use of functions can be taken even further; if you are invoking a Java method that takes a SAM type,
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   171
     * you can just pass in a function object, and Nashorn will know what you meant:
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   172
     * </p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   173
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   174
     * var timer = new Java.type("java.util.Timer")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   175
     * timer.schedule(function() { print("Hello World!") })
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   176
     * </pre>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   177
     * <p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   178
     * Here, {@code Timer.schedule()} expects a {@code TimerTask} as its argument, so Nashorn creates an instance of a
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   179
     * {@code TimerTask} subclass and uses the passed function to implement its only abstract method, {@code run()}. In
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   180
     * this usage though, you can't use non-default constructors; the type must be either an interface, or must have a
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   181
     * protected or public no-arg constructor.
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   182
     * </p>
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   183
     * <p>
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   184
     * You can also subclass non-abstract classes; for that you will need to use the {@link #extend(Object, Object...)}
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   185
     * method.
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   186
     * </p>
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   187
     * <p><b>Accessing static members</b></p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   188
     * Examples:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   189
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   190
     * var File = Java.type("java.io.File")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   191
     * var pathSep = File.pathSeparator
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   192
     * var tmpFile1 = File.createTempFile("abcdefg", ".tmp")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   193
     * var tmpFile2 = File.createTempFile("abcdefg", ".tmp", new File("/tmp"))
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   194
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   195
     * Actually, you can even assign static methods to variables, so the above example can be rewritten as:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   196
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   197
     * var File = Java.type("java.io.File")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   198
     * var createTempFile = File.createTempFile
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   199
     * var tmpFile1 = createTempFile("abcdefg", ".tmp")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   200
     * var tmpFile2 = createTempFile("abcdefg", ".tmp", new File("/tmp"))
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   201
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   202
     * If you need to access the actual {@code java.lang.Class} object for the type, you can use the {@code class}
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   203
     * property on the object representing the type:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   204
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   205
     * var File = Java.type("java.io.File")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   206
     * var someFile = new File("blah")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   207
     * print(File.class === someFile.getClass()) // prints true
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   208
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   209
     * Of course, you can also use the {@code getClass()} method or its equivalent {@code class} property on any
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   210
     * instance of the class. Other way round, you can use the synthetic {@code static} property on any
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   211
     * {@code java.lang.Class} object to retrieve its type-representing object:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   212
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   213
     * var File = Java.type("java.io.File")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   214
     * print(File.class.static === File) // prints true
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   215
     * </pre>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   216
     * <p><b>{@code instanceof} operator</b></p>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   217
     * The standard ECMAScript {@code instanceof} operator is extended to recognize Java objects and their type objects:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   218
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   219
     * var File = Java.type("java.io.File")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   220
     * var aFile = new File("foo")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   221
     * print(aFile instanceof File) // prints true
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   222
     * print(aFile instanceof File.class) // prints false - Class objects aren't type objects.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   223
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   224
     * @param self not used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   225
     * @param objTypeName the object whose JS string value represents the type name. You can use names of primitive Java
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   226
     * types to obtain representations of them, and you can use trailing square brackets to represent Java array types.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   227
     * @return the object representing the named type
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   228
     * @throws ClassNotFoundException if the class is not found
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   229
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   230
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   231
    public static Object type(final Object self, final Object objTypeName) throws ClassNotFoundException {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   232
        return type(objTypeName);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   233
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   234
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   235
    private static StaticClass type(final Object objTypeName) throws ClassNotFoundException {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   236
        return StaticClass.forClass(type(JSType.toString(objTypeName)));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   237
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   238
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   239
    private static Class<?> type(final String typeName) throws ClassNotFoundException {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   240
        if (typeName.endsWith("[]")) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   241
            return arrayType(typeName);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   242
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   243
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   244
        return simpleType(typeName);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   245
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   246
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   247
    /**
16522
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   248
     * Returns name of a java type {@link StaticClass}.
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   249
     * @param self not used
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   250
     * @param type the type whose name is returned
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   251
     * @return name of the given type
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   252
     */
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   253
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   254
    public static Object typeName(final Object self, final Object type) {
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   255
        if (type instanceof StaticClass) {
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   256
            return ((StaticClass)type).getRepresentedClass().getName();
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   257
        } else if (type instanceof Class) {
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   258
            return ((Class<?>)type).getName();
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   259
        } else {
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   260
            return UNDEFINED;
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   261
        }
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   262
    }
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   263
d643e3ee819c 8009757: Package access clean up and refactoring
sundar
parents: 16272
diff changeset
   264
    /**
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   265
     * Given a script object and a Java type, converts the script object into the desired Java type. Currently it
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   266
     * performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   267
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   268
     * var anArray = [1, "13", false]
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   269
     * var javaIntArray = Java.to(anArray, "int[]")
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   270
     * print(javaIntArray[0]) // prints 1
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   271
     * print(javaIntArray[1]) // prints 13, as string "13" was converted to number 13 as per ECMAScript ToNumber conversion
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   272
     * print(javaIntArray[2]) // prints 0, as boolean false was converted to number 0 as per ECMAScript ToNumber conversion
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   273
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   274
     * @param self not used
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   275
     * @param obj the script object. Can be null.
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   276
     * @param objType either a {@link #type(Object, Object) type object} or a String describing the type of the Java
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   277
     * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   278
     * omitted).
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   279
     * @return a Java object whose value corresponds to the original script object's value. Specifically, for array
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   280
     * target types, returns a Java array of the same type with contents converted to the array's component type. Does
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   281
     * not recursively convert for multidimensional arrays. For {@link List} or {@link Deque}, returns a live wrapper
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   282
     * around the object, see {@link ListAdapter} for details. Returns null if obj is null.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   283
     * @throws ClassNotFoundException if the class described by objType is not found
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   284
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   285
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   286
    public static Object to(final Object self, final Object obj, final Object objType) throws ClassNotFoundException {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   287
        if (obj == null) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   288
            return null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   289
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   290
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   291
        Global.checkObject(obj);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   292
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   293
        final Class<?> targetClass;
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   294
        if(objType == UNDEFINED) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   295
            targetClass = Object[].class;
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   296
        } else {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   297
            final StaticClass targetType;
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   298
            if(objType instanceof StaticClass) {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   299
                targetType = (StaticClass)objType;
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   300
            } else {
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   301
                targetType = type(objType);
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   302
            }
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   303
            targetClass = targetType.getRepresentedClass();
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   304
        }
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   305
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   306
        if(targetClass.isArray()) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   307
            return ((ScriptObject)obj).getArray().asArrayOfType(targetClass.getComponentType());
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   308
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   309
17765
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   310
        if(targetClass == List.class || targetClass == Deque.class) {
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   311
            return new ListAdapter((ScriptObject)obj);
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   312
        }
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   313
6b45f57bebc4 8015267: Allow conversion of JS arrays to Java List/Deque
attila
parents: 17758
diff changeset
   314
        throw typeError("unsupported.java.to.type", targetClass.getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   315
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   316
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   317
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   318
     * Given a Java array or {@link Collection}, returns a JavaScript array with a shallow copy of its contents. Note
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   319
     * that in most cases, you can use Java arrays and lists natively in Nashorn; in cases where for some reason you
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   320
     * need to have an actual JavaScript native array (e.g. to work with the array comprehensions functions), you will
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   321
     * want to use this method. Example:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   322
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   323
     * var File = Java.type("java.io.File")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   324
     * var listHomeDir = new File("~").listFiles()
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   325
     * var jsListHome = Java.from(listHomeDir)
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   326
     * var jpegModifiedDates = jsListHome
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   327
     *     .filter(function(val) { return val.getName().endsWith(".jpg") })
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   328
     *     .map(function(val) { return val.lastModified() })
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   329
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   330
     * @param self not used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   331
     * @param objArray the java array or collection. Can be null.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   332
     * @return a JavaScript array with the copy of Java array's or collection's contents. Returns null if objArray is
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   333
     * null.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   334
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   335
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
17758
2b056941e4dd 8014797: rename Java.toJavaArray/toJavaScriptArray to Java.to/from, respectively.
attila
parents: 16777
diff changeset
   336
    public static Object from(final Object self, final Object objArray) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   337
        if (objArray == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   338
            return null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   339
        } else if (objArray instanceof Collection) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   340
            return new NativeArray(((Collection<?>)objArray).toArray());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   341
        } else if (objArray instanceof Object[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   342
            return new NativeArray(((Object[])objArray).clone());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   343
        } else if (objArray instanceof int[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   344
            return new NativeArray(((int[])objArray).clone());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   345
        } else if (objArray instanceof double[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   346
            return new NativeArray(((double[])objArray).clone());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   347
        } else if (objArray instanceof long[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   348
            return new NativeArray(((long[])objArray).clone());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   349
        } else if (objArray instanceof byte[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   350
            return new NativeArray(copyArray((byte[])objArray));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   351
        } else if (objArray instanceof short[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   352
            return new NativeArray(copyArray((short[])objArray));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   353
        } else if (objArray instanceof char[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   354
            return new NativeArray(copyArray((char[])objArray));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   355
        } else if (objArray instanceof float[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   356
            return new NativeArray(copyArray((float[])objArray));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   357
        } else if (objArray instanceof boolean[]) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   358
            return new NativeArray(copyArray((boolean[])objArray));
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   359
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   360
16256
f2d9a0c49914 8007002: Replace implicit exception throwing methods with explicit throws - simplify control flow and remove useless code
lagergren
parents: 16234
diff changeset
   361
        throw typeError("cant.convert.to.javascript.array", objArray.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   362
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   363
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   364
    private static int[] copyArray(final byte[] in) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   365
        final int[] out = new int[in.length];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   366
        for(int i = 0; i < in.length; ++i) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   367
            out[i] = in[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   368
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   369
        return out;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   370
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   371
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   372
    private static int[] copyArray(final short[] in) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   373
        final int[] out = new int[in.length];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   374
        for(int i = 0; i < in.length; ++i) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   375
            out[i] = in[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   376
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   377
        return out;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   378
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   379
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   380
    private static int[] copyArray(final char[] in) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   381
        final int[] out = new int[in.length];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   382
        for(int i = 0; i < in.length; ++i) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   383
            out[i] = in[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   384
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   385
        return out;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   386
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   387
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   388
    private static double[] copyArray(final float[] in) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   389
        final double[] out = new double[in.length];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   390
        for(int i = 0; i < in.length; ++i) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   391
            out[i] = in[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   392
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   393
        return out;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   394
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   395
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   396
    private static Object[] copyArray(final boolean[] in) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   397
        final Object[] out = new Object[in.length];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   398
        for(int i = 0; i < in.length; ++i) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   399
            out[i] = in[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   400
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   401
        return out;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   402
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   403
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   404
    private static Class<?> simpleType(final String typeName) throws ClassNotFoundException {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   405
        final Class<?> primClass = TypeUtilities.getPrimitiveTypeByName(typeName);
18846
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   406
        if(primClass != null) {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   407
            return primClass;
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   408
        }
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   409
        final Context ctx = Global.getThisContext();
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   410
        try {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   411
            return ctx.findClass(typeName);
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   412
        } catch(ClassNotFoundException e) {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   413
            // The logic below compensates for a frequent user error - when people use dot notation to separate inner
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   414
            // class names, i.e. "java.lang.Character.UnicodeBlock" vs."java.lang.Character$UnicodeBlock". The logic
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   415
            // below will try alternative class names, replacing dots at the end of the name with dollar signs.
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   416
            final StringBuilder nextName = new StringBuilder(typeName);
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   417
            int lastDot = nextName.length();
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   418
            for(;;) {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   419
                lastDot = nextName.lastIndexOf(".", lastDot - 1);
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   420
                if(lastDot == -1) {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   421
                    // Exhausted the search space, class not found - rethrow the original exception.
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   422
                    throw e;
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   423
                }
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   424
                nextName.setCharAt(lastDot, '$');
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   425
                try {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   426
                    return ctx.findClass(nextName.toString());
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   427
                } catch(ClassNotFoundException cnfe) {
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   428
                    // Intentionally ignored, so the loop retries with the next name
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   429
                }
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   430
            }
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   431
        }
4ef5f2321c67 8017768: allow dot as inner class name separator for Java.type
attila
parents: 18842
diff changeset
   432
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   433
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   434
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   435
    private static Class<?> arrayType(final String typeName) throws ClassNotFoundException {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   436
        return Array.newInstance(type(typeName.substring(0, typeName.length() - 2)), 0).getClass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   437
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   438
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   439
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   440
     * Returns a type object for a subclass of the specified Java class (or implementation of the specified interface)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   441
     * that acts as a script-to-Java adapter for it. See {@link #type(Object, Object)} for a discussion of type objects,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   442
     * and see {@link JavaAdapterFactory} for details on script-to-Java adapters. Note that you can also implement
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   443
     * interfaces and subclass abstract classes using {@code new} operator on a type object for an interface or abstract
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   444
     * class. However, to extend a non-abstract class, you will have to use this method. Example:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   445
     * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   446
     * var ArrayList = Java.type("java.util.ArrayList")
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   447
     * var ArrayListExtender = Java.extend(ArrayList)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   448
     * var printSizeInvokedArrayList = new ArrayListExtender() {
16212
363737d0d757 8007452: add scripting programmers doc changes for nashorn
sundar
parents: 16188
diff changeset
   449
     *     size: function() { print("size invoked!"); }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   450
     * }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   451
     * var printAddInvokedArrayList = new ArrayListExtender() {
16212
363737d0d757 8007452: add scripting programmers doc changes for nashorn
sundar
parents: 16188
diff changeset
   452
     *     add: function(x, y) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   453
     *       if(typeof(y) === "undefined") {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   454
     *           print("add(e) invoked!");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   455
     *       } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   456
     *           print("add(i, e) invoked!");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   457
     *       }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   458
     * }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   459
     * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   460
     * We can see several important concepts in the above example:
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   461
     * <ul>
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   462
     * <li>Every specified list of Java types will have exactly one extender subclass in Nashorn - repeated invocations
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   463
     * of {@code extend} for the same list of types will yield the same extender type. It's a generic adapter that
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   464
     * delegates to whatever JavaScript functions its implementation object has on a per-instance basis.</li>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   465
     * <li>If the Java method is overloaded (as in the above example {@code List.add()}), then your JavaScript adapter
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   466
     * must be prepared to deal with all overloads.</li>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   467
     * <li>You can't invoke {@code super.*()} from adapters for now.</li>
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   468
     * <li>It is also possible to specify an ordinary JavaScript object as the last argument to {@code extend}. In that
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   469
     * case, it is treated as a class-level override. {@code extend} will return an extender class where all instances
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   470
     * will have the methods implemented by functions on that object, just as if that object were passed as the last
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   471
     * argument to their constructor. Example:
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   472
     * <pre>
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   473
     * var Runnable = Java.type("java.lang.Runnable")
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   474
     * var R1 = Java.extend(Runnable, {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   475
     *     run: function() {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   476
     *         print("R1.run() invoked!")
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   477
     *     }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   478
     * })
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   479
     * var r1 = new R1
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   480
     * var t = new java.lang.Thread(r1)
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   481
     * t.start()
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   482
     * t.join()
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   483
     * </pre>
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   484
     * As you can see, you don't have to pass any object when you create a new instance of {@code R1} as its
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   485
     * {@code run()} function was defined already when extending the class. Of course, you can still provide
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   486
     * instance-level overrides on these objects. The order of precedence is instance-level method, class-level method,
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   487
     * superclass method, or {@code UnsupportedOperationException} if the superclass method is abstract. If we continue
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   488
     * our previous example:
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   489
     * <pre>
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   490
     * var r2 = new R1(function() { print("r2.run() invoked!") })
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   491
     * r2.run()
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   492
     * </pre>
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   493
     * We'll see it'll print {@code "r2.run() invoked!"}, thus overriding on instance-level the class-level behavior.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   494
     * </li>
16272
675a0caf75bc 8009263: Fix all javadoc errors in nashorn code
sundar
parents: 16256
diff changeset
   495
     * </ul>
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   496
     * @param self not used
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   497
     * @param types the original types. The caller must pass at least one Java type object of class {@link StaticClass}
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   498
     * representing either a public interface or a non-final public class with at least one public or protected
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   499
     * constructor. If more than one type is specified, at most one can be a class and the rest have to be interfaces.
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   500
     * Invoking the method twice with exactly the same types in the same order - in absence of class-level overrides -
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   501
     * will return the same adapter class, any reordering of types or even addition or removal of redundant types (i.e.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   502
     * interfaces that other types in the list already implement/extend, or {@code java.lang.Object} in a list of types
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   503
     * consisting purely of interfaces) will result in a different adapter class, even though those adapter classes are
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   504
     * functionally identical; we deliberately don't want to incur the additional processing cost of canonicalizing type
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   505
     * lists. As a special case, the last argument can be a {@code ScriptObject} instead of a type. In this case, a
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   506
     * separate adapter class is generated - new one for each invocation - that will use the passed script object as its
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   507
     * implementation for all instances. Instances of such adapter classes can then be created without passing another
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   508
     * script object in the constructor, as the class has a class-level behavior defined by the script object. However,
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   509
     * you can still pass a script object (or if it's a SAM type, a function) to the constructor to provide further
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   510
     * instance-level overrides.
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   511
     *
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   512
     * @return a new {@link StaticClass} that represents the adapter for the original types.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   513
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   514
    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   515
    public static Object extend(final Object self, final Object... types) {
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   516
        if(types == null || types.length == 0) {
16256
f2d9a0c49914 8007002: Replace implicit exception throwing methods with explicit throws - simplify control flow and remove useless code
lagergren
parents: 16234
diff changeset
   517
            throw typeError("extend.expects.at.least.one.argument");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   518
        }
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   519
        final int l = types.length;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   520
        final int typesLen;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   521
        final ScriptObject classOverrides;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   522
        if(types[l - 1] instanceof ScriptObject) {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   523
            classOverrides = (ScriptObject)types[l - 1];
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   524
            typesLen = l - 1;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   525
            if(typesLen == 0) {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   526
                throw typeError("extend.expects.at.least.one.type.argument");
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   527
            }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   528
        } else {
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   529
            classOverrides = null;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   530
            typesLen = l;
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   531
        }
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   532
        final Class<?>[] stypes = new Class<?>[typesLen];
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   533
        try {
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   534
            for(int i = 0; i < typesLen; ++i) {
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   535
                stypes[i] = ((StaticClass)types[i]).getRepresentedClass();
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   536
            }
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   537
        } catch(final ClassCastException e) {
16256
f2d9a0c49914 8007002: Replace implicit exception throwing methods with explicit throws - simplify control flow and remove useless code
lagergren
parents: 16234
diff changeset
   538
            throw typeError("extend.expects.java.types");
16171
90dcd4fc42f0 8006168: ability to generate multi-type Java adapters
attila
parents: 16151
diff changeset
   539
        }
16777
207a993adb9a 8011544: Allow subclassing Java classes from script without creating instances
attila
parents: 16522
diff changeset
   540
        return JavaAdapterFactory.getAdapterClassFor(stypes, classOverrides);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   541
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   542
}