emul/mini/src/main/java/java/lang/Class.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 26 Jan 2013 08:47:05 +0100
changeset 592 5e13b1ac2886
parent 576 b679a7dad297
parent 586 b670af2aa0f7
child 604 3fcc279c921b
child 658 578cea5b4359
permissions -rw-r--r--
In order to support fields of the same name in subclasses we are now prefixing them with name of the class that defines them. To provide convenient way to access them from generated bytecode and also directly from JavaScript, there is a getter/setter function for each field. It starts with _ followed by the field name. If called with a parameter, it sets the field, with a parameter it just returns it.
jaroslav@56
     1
/*
jaroslav@56
     2
 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
jaroslav@56
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@56
     4
 *
jaroslav@56
     5
 * This code is free software; you can redistribute it and/or modify it
jaroslav@56
     6
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@56
     7
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@56
     8
 * particular file as subject to the "Classpath" exception as provided
jaroslav@56
     9
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@56
    10
 *
jaroslav@56
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@56
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@56
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@56
    14
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@56
    15
 * accompanied this code).
jaroslav@56
    16
 *
jaroslav@56
    17
 * You should have received a copy of the GNU General Public License version
jaroslav@56
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@56
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@56
    20
 *
jaroslav@56
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@56
    22
 * or visit www.oracle.com if you need additional information or have any
jaroslav@56
    23
 * questions.
jaroslav@56
    24
 */
jaroslav@56
    25
jaroslav@56
    26
package java.lang;
jaroslav@56
    27
jaroslav@424
    28
import java.io.ByteArrayInputStream;
jaroslav@555
    29
import org.apidesign.bck2brwsr.emul.reflect.AnnotationImpl;
jaroslav@122
    30
import java.io.InputStream;
jaroslav@56
    31
import java.lang.annotation.Annotation;
jaroslav@261
    32
import java.lang.reflect.Field;
jaroslav@261
    33
import java.lang.reflect.Method;
jaroslav@260
    34
import java.lang.reflect.TypeVariable;
jaroslav@576
    35
import java.net.URL;
jaroslav@225
    36
import org.apidesign.bck2brwsr.core.JavaScriptBody;
jaroslav@555
    37
import org.apidesign.bck2brwsr.emul.reflect.MethodImpl;
jaroslav@56
    38
jaroslav@56
    39
/**
jaroslav@56
    40
 * Instances of the class {@code Class} represent classes and
jaroslav@56
    41
 * interfaces in a running Java application.  An enum is a kind of
jaroslav@56
    42
 * class and an annotation is a kind of interface.  Every array also
jaroslav@56
    43
 * belongs to a class that is reflected as a {@code Class} object
jaroslav@56
    44
 * that is shared by all arrays with the same element type and number
jaroslav@56
    45
 * of dimensions.  The primitive Java types ({@code boolean},
jaroslav@56
    46
 * {@code byte}, {@code char}, {@code short},
jaroslav@56
    47
 * {@code int}, {@code long}, {@code float}, and
jaroslav@56
    48
 * {@code double}), and the keyword {@code void} are also
jaroslav@56
    49
 * represented as {@code Class} objects.
jaroslav@56
    50
 *
jaroslav@56
    51
 * <p> {@code Class} has no public constructor. Instead {@code Class}
jaroslav@56
    52
 * objects are constructed automatically by the Java Virtual Machine as classes
jaroslav@56
    53
 * are loaded and by calls to the {@code defineClass} method in the class
jaroslav@56
    54
 * loader.
jaroslav@56
    55
 *
jaroslav@56
    56
 * <p> The following example uses a {@code Class} object to print the
jaroslav@56
    57
 * class name of an object:
jaroslav@56
    58
 *
jaroslav@56
    59
 * <p> <blockquote><pre>
jaroslav@56
    60
 *     void printClassName(Object obj) {
jaroslav@56
    61
 *         System.out.println("The class of " + obj +
jaroslav@56
    62
 *                            " is " + obj.getClass().getName());
jaroslav@56
    63
 *     }
jaroslav@56
    64
 * </pre></blockquote>
jaroslav@56
    65
 *
jaroslav@56
    66
 * <p> It is also possible to get the {@code Class} object for a named
jaroslav@56
    67
 * type (or for void) using a class literal.  See Section 15.8.2 of
jaroslav@56
    68
 * <cite>The Java&trade; Language Specification</cite>.
jaroslav@56
    69
 * For example:
jaroslav@56
    70
 *
jaroslav@56
    71
 * <p> <blockquote>
jaroslav@56
    72
 *     {@code System.out.println("The name of class Foo is: "+Foo.class.getName());}
jaroslav@56
    73
 * </blockquote>
jaroslav@56
    74
 *
jaroslav@56
    75
 * @param <T> the type of the class modeled by this {@code Class}
jaroslav@56
    76
 * object.  For example, the type of {@code String.class} is {@code
jaroslav@56
    77
 * Class<String>}.  Use {@code Class<?>} if the class being modeled is
jaroslav@56
    78
 * unknown.
jaroslav@56
    79
 *
jaroslav@56
    80
 * @author  unascribed
jaroslav@56
    81
 * @see     java.lang.ClassLoader#defineClass(byte[], int, int)
jaroslav@56
    82
 * @since   JDK1.0
jaroslav@56
    83
 */
jaroslav@56
    84
public final
jaroslav@260
    85
    class Class<T> implements java.io.Serializable,
jaroslav@260
    86
                              java.lang.reflect.GenericDeclaration,
jaroslav@260
    87
                              java.lang.reflect.Type,
jaroslav@260
    88
                              java.lang.reflect.AnnotatedElement {
jaroslav@56
    89
    private static final int ANNOTATION= 0x00002000;
jaroslav@56
    90
    private static final int ENUM      = 0x00004000;
jaroslav@56
    91
    private static final int SYNTHETIC = 0x00001000;
jaroslav@56
    92
jaroslav@56
    93
    /*
jaroslav@56
    94
     * Constructor. Only the Java Virtual Machine creates Class
jaroslav@56
    95
     * objects.
jaroslav@56
    96
     */
jaroslav@56
    97
    private Class() {}
jaroslav@56
    98
jaroslav@56
    99
jaroslav@56
   100
    /**
jaroslav@56
   101
     * Converts the object to a string. The string representation is the
jaroslav@56
   102
     * string "class" or "interface", followed by a space, and then by the
jaroslav@56
   103
     * fully qualified name of the class in the format returned by
jaroslav@56
   104
     * {@code getName}.  If this {@code Class} object represents a
jaroslav@56
   105
     * primitive type, this method returns the name of the primitive type.  If
jaroslav@56
   106
     * this {@code Class} object represents void this method returns
jaroslav@56
   107
     * "void".
jaroslav@56
   108
     *
jaroslav@56
   109
     * @return a string representation of this class object.
jaroslav@56
   110
     */
jaroslav@56
   111
    public String toString() {
jaroslav@56
   112
        return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
jaroslav@56
   113
            + getName();
jaroslav@56
   114
    }
jaroslav@56
   115
jaroslav@56
   116
jaroslav@56
   117
    /**
jaroslav@56
   118
     * Returns the {@code Class} object associated with the class or
jaroslav@56
   119
     * interface with the given string name.  Invoking this method is
jaroslav@56
   120
     * equivalent to:
jaroslav@56
   121
     *
jaroslav@56
   122
     * <blockquote>
jaroslav@56
   123
     *  {@code Class.forName(className, true, currentLoader)}
jaroslav@56
   124
     * </blockquote>
jaroslav@56
   125
     *
jaroslav@56
   126
     * where {@code currentLoader} denotes the defining class loader of
jaroslav@56
   127
     * the current class.
jaroslav@56
   128
     *
jaroslav@56
   129
     * <p> For example, the following code fragment returns the
jaroslav@56
   130
     * runtime {@code Class} descriptor for the class named
jaroslav@56
   131
     * {@code java.lang.Thread}:
jaroslav@56
   132
     *
jaroslav@56
   133
     * <blockquote>
jaroslav@56
   134
     *   {@code Class t = Class.forName("java.lang.Thread")}
jaroslav@56
   135
     * </blockquote>
jaroslav@56
   136
     * <p>
jaroslav@56
   137
     * A call to {@code forName("X")} causes the class named
jaroslav@56
   138
     * {@code X} to be initialized.
jaroslav@56
   139
     *
jaroslav@56
   140
     * @param      className   the fully qualified name of the desired class.
jaroslav@56
   141
     * @return     the {@code Class} object for the class with the
jaroslav@56
   142
     *             specified name.
jaroslav@56
   143
     * @exception LinkageError if the linkage fails
jaroslav@56
   144
     * @exception ExceptionInInitializerError if the initialization provoked
jaroslav@56
   145
     *            by this method fails
jaroslav@56
   146
     * @exception ClassNotFoundException if the class cannot be located
jaroslav@56
   147
     */
jaroslav@56
   148
    public static Class<?> forName(String className)
jaroslav@450
   149
    throws ClassNotFoundException {
jaroslav@450
   150
        if (className.startsWith("[")) {
jaroslav@452
   151
            Class<?> arrType = defineArray(className);
jaroslav@452
   152
            Class<?> c = arrType;
jaroslav@452
   153
            while (c != null && c.isArray()) {
jaroslav@452
   154
                c = c.getComponentType0(); // verify component type is sane
jaroslav@452
   155
            }
jaroslav@452
   156
            return arrType;
jaroslav@450
   157
        }
jaroslav@322
   158
        Class<?> c = loadCls(className, className.replace('.', '_'));
jaroslav@321
   159
        if (c == null) {
jaroslav@400
   160
            throw new ClassNotFoundException(className);
jaroslav@321
   161
        }
jaroslav@321
   162
        return c;
jaroslav@56
   163
    }
jaroslav@562
   164
jaroslav@562
   165
jaroslav@562
   166
    /**
jaroslav@562
   167
     * Returns the {@code Class} object associated with the class or
jaroslav@562
   168
     * interface with the given string name, using the given class loader.
jaroslav@562
   169
     * Given the fully qualified name for a class or interface (in the same
jaroslav@562
   170
     * format returned by {@code getName}) this method attempts to
jaroslav@562
   171
     * locate, load, and link the class or interface.  The specified class
jaroslav@562
   172
     * loader is used to load the class or interface.  If the parameter
jaroslav@562
   173
     * {@code loader} is null, the class is loaded through the bootstrap
jaroslav@562
   174
     * class loader.  The class is initialized only if the
jaroslav@562
   175
     * {@code initialize} parameter is {@code true} and if it has
jaroslav@562
   176
     * not been initialized earlier.
jaroslav@562
   177
     *
jaroslav@562
   178
     * <p> If {@code name} denotes a primitive type or void, an attempt
jaroslav@562
   179
     * will be made to locate a user-defined class in the unnamed package whose
jaroslav@562
   180
     * name is {@code name}. Therefore, this method cannot be used to
jaroslav@562
   181
     * obtain any of the {@code Class} objects representing primitive
jaroslav@562
   182
     * types or void.
jaroslav@562
   183
     *
jaroslav@562
   184
     * <p> If {@code name} denotes an array class, the component type of
jaroslav@562
   185
     * the array class is loaded but not initialized.
jaroslav@562
   186
     *
jaroslav@562
   187
     * <p> For example, in an instance method the expression:
jaroslav@562
   188
     *
jaroslav@562
   189
     * <blockquote>
jaroslav@562
   190
     *  {@code Class.forName("Foo")}
jaroslav@562
   191
     * </blockquote>
jaroslav@562
   192
     *
jaroslav@562
   193
     * is equivalent to:
jaroslav@562
   194
     *
jaroslav@562
   195
     * <blockquote>
jaroslav@562
   196
     *  {@code Class.forName("Foo", true, this.getClass().getClassLoader())}
jaroslav@562
   197
     * </blockquote>
jaroslav@562
   198
     *
jaroslav@562
   199
     * Note that this method throws errors related to loading, linking or
jaroslav@562
   200
     * initializing as specified in Sections 12.2, 12.3 and 12.4 of <em>The
jaroslav@562
   201
     * Java Language Specification</em>.
jaroslav@562
   202
     * Note that this method does not check whether the requested class
jaroslav@562
   203
     * is accessible to its caller.
jaroslav@562
   204
     *
jaroslav@562
   205
     * <p> If the {@code loader} is {@code null}, and a security
jaroslav@562
   206
     * manager is present, and the caller's class loader is not null, then this
jaroslav@562
   207
     * method calls the security manager's {@code checkPermission} method
jaroslav@562
   208
     * with a {@code RuntimePermission("getClassLoader")} permission to
jaroslav@562
   209
     * ensure it's ok to access the bootstrap class loader.
jaroslav@562
   210
     *
jaroslav@562
   211
     * @param name       fully qualified name of the desired class
jaroslav@562
   212
     * @param initialize whether the class must be initialized
jaroslav@562
   213
     * @param loader     class loader from which the class must be loaded
jaroslav@562
   214
     * @return           class object representing the desired class
jaroslav@562
   215
     *
jaroslav@562
   216
     * @exception LinkageError if the linkage fails
jaroslav@562
   217
     * @exception ExceptionInInitializerError if the initialization provoked
jaroslav@562
   218
     *            by this method fails
jaroslav@562
   219
     * @exception ClassNotFoundException if the class cannot be located by
jaroslav@562
   220
     *            the specified class loader
jaroslav@562
   221
     *
jaroslav@562
   222
     * @see       java.lang.Class#forName(String)
jaroslav@562
   223
     * @see       java.lang.ClassLoader
jaroslav@562
   224
     * @since     1.2
jaroslav@562
   225
     */
jaroslav@562
   226
    public static Class<?> forName(String name, boolean initialize,
jaroslav@562
   227
                                   ClassLoader loader)
jaroslav@562
   228
        throws ClassNotFoundException
jaroslav@562
   229
    {
jaroslav@562
   230
        return forName(name);
jaroslav@562
   231
    }
jaroslav@321
   232
    
jaroslav@322
   233
    @JavaScriptBody(args = {"n", "c" }, body =
jaroslav@322
   234
        "if (vm[c]) return vm[c].$class;\n"
jaroslav@322
   235
      + "if (vm.loadClass) {\n"
jaroslav@322
   236
      + "  vm.loadClass(n);\n"
jaroslav@322
   237
      + "  if (vm[c]) return vm[c].$class;\n"
jaroslav@322
   238
      + "}\n"
jaroslav@322
   239
      + "return null;"
jaroslav@321
   240
    )
jaroslav@322
   241
    private static native Class<?> loadCls(String n, String c);
jaroslav@56
   242
jaroslav@56
   243
jaroslav@56
   244
    /**
jaroslav@56
   245
     * Creates a new instance of the class represented by this {@code Class}
jaroslav@56
   246
     * object.  The class is instantiated as if by a {@code new}
jaroslav@56
   247
     * expression with an empty argument list.  The class is initialized if it
jaroslav@56
   248
     * has not already been initialized.
jaroslav@56
   249
     *
jaroslav@56
   250
     * <p>Note that this method propagates any exception thrown by the
jaroslav@56
   251
     * nullary constructor, including a checked exception.  Use of
jaroslav@56
   252
     * this method effectively bypasses the compile-time exception
jaroslav@56
   253
     * checking that would otherwise be performed by the compiler.
jaroslav@56
   254
     * The {@link
jaroslav@56
   255
     * java.lang.reflect.Constructor#newInstance(java.lang.Object...)
jaroslav@56
   256
     * Constructor.newInstance} method avoids this problem by wrapping
jaroslav@56
   257
     * any exception thrown by the constructor in a (checked) {@link
jaroslav@56
   258
     * java.lang.reflect.InvocationTargetException}.
jaroslav@56
   259
     *
jaroslav@56
   260
     * @return     a newly allocated instance of the class represented by this
jaroslav@56
   261
     *             object.
jaroslav@56
   262
     * @exception  IllegalAccessException  if the class or its nullary
jaroslav@56
   263
     *               constructor is not accessible.
jaroslav@56
   264
     * @exception  InstantiationException
jaroslav@56
   265
     *               if this {@code Class} represents an abstract class,
jaroslav@56
   266
     *               an interface, an array class, a primitive type, or void;
jaroslav@56
   267
     *               or if the class has no nullary constructor;
jaroslav@56
   268
     *               or if the instantiation fails for some other reason.
jaroslav@56
   269
     * @exception  ExceptionInInitializerError if the initialization
jaroslav@56
   270
     *               provoked by this method fails.
jaroslav@56
   271
     * @exception  SecurityException
jaroslav@56
   272
     *             If a security manager, <i>s</i>, is present and any of the
jaroslav@56
   273
     *             following conditions is met:
jaroslav@56
   274
     *
jaroslav@56
   275
     *             <ul>
jaroslav@56
   276
     *
jaroslav@56
   277
     *             <li> invocation of
jaroslav@56
   278
     *             {@link SecurityManager#checkMemberAccess
jaroslav@56
   279
     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
jaroslav@56
   280
     *             creation of new instances of this class
jaroslav@56
   281
     *
jaroslav@56
   282
     *             <li> the caller's class loader is not the same as or an
jaroslav@56
   283
     *             ancestor of the class loader for the current class and
jaroslav@56
   284
     *             invocation of {@link SecurityManager#checkPackageAccess
jaroslav@56
   285
     *             s.checkPackageAccess()} denies access to the package
jaroslav@56
   286
     *             of this class
jaroslav@56
   287
     *
jaroslav@56
   288
     *             </ul>
jaroslav@56
   289
     *
jaroslav@56
   290
     */
jaroslav@397
   291
    @JavaScriptBody(args = { "self", "illegal" }, body =
jaroslav@397
   292
          "\nvar c = self.cnstr;"
jaroslav@397
   293
        + "\nif (c['cons__V']) {"
jaroslav@397
   294
        + "\n  if ((c.cons__V.access & 0x1) != 0) {"
jaroslav@397
   295
        + "\n    var inst = c();"
jaroslav@442
   296
        + "\n    c.cons__V.call(inst);"
jaroslav@397
   297
        + "\n    return inst;"
jaroslav@397
   298
        + "\n  }"
jaroslav@397
   299
        + "\n  return illegal;"
jaroslav@397
   300
        + "\n}"
jaroslav@397
   301
        + "\nreturn null;"
jaroslav@231
   302
    )
jaroslav@397
   303
    private static native Object newInstance0(Class<?> self, Object illegal);
jaroslav@397
   304
    
jaroslav@56
   305
    public T newInstance()
jaroslav@56
   306
        throws InstantiationException, IllegalAccessException
jaroslav@56
   307
    {
jaroslav@397
   308
        Object illegal = new Object();
jaroslav@397
   309
        Object inst = newInstance0(this, illegal);
jaroslav@397
   310
        if (inst == null) {
jaroslav@397
   311
            throw new InstantiationException(getName());
jaroslav@397
   312
        }
jaroslav@397
   313
        if (inst == illegal) {
jaroslav@397
   314
            throw new IllegalAccessException();
jaroslav@397
   315
        }
jaroslav@397
   316
        return (T)inst;
jaroslav@56
   317
    }
jaroslav@56
   318
jaroslav@56
   319
    /**
jaroslav@56
   320
     * Determines if the specified {@code Object} is assignment-compatible
jaroslav@56
   321
     * with the object represented by this {@code Class}.  This method is
jaroslav@56
   322
     * the dynamic equivalent of the Java language {@code instanceof}
jaroslav@56
   323
     * operator. The method returns {@code true} if the specified
jaroslav@56
   324
     * {@code Object} argument is non-null and can be cast to the
jaroslav@56
   325
     * reference type represented by this {@code Class} object without
jaroslav@56
   326
     * raising a {@code ClassCastException.} It returns {@code false}
jaroslav@56
   327
     * otherwise.
jaroslav@56
   328
     *
jaroslav@56
   329
     * <p> Specifically, if this {@code Class} object represents a
jaroslav@56
   330
     * declared class, this method returns {@code true} if the specified
jaroslav@56
   331
     * {@code Object} argument is an instance of the represented class (or
jaroslav@56
   332
     * of any of its subclasses); it returns {@code false} otherwise. If
jaroslav@56
   333
     * this {@code Class} object represents an array class, this method
jaroslav@56
   334
     * returns {@code true} if the specified {@code Object} argument
jaroslav@56
   335
     * can be converted to an object of the array class by an identity
jaroslav@56
   336
     * conversion or by a widening reference conversion; it returns
jaroslav@56
   337
     * {@code false} otherwise. If this {@code Class} object
jaroslav@56
   338
     * represents an interface, this method returns {@code true} if the
jaroslav@56
   339
     * class or any superclass of the specified {@code Object} argument
jaroslav@56
   340
     * implements this interface; it returns {@code false} otherwise. If
jaroslav@56
   341
     * this {@code Class} object represents a primitive type, this method
jaroslav@56
   342
     * returns {@code false}.
jaroslav@56
   343
     *
jaroslav@56
   344
     * @param   obj the object to check
jaroslav@56
   345
     * @return  true if {@code obj} is an instance of this class
jaroslav@56
   346
     *
jaroslav@56
   347
     * @since JDK1.1
jaroslav@56
   348
     */
jaroslav@434
   349
    public boolean isInstance(Object obj) {
jaroslav@571
   350
        if (isArray()) {
jaroslav@571
   351
            return isAssignableFrom(obj.getClass());
jaroslav@571
   352
        }
jaroslav@571
   353
        
jaroslav@434
   354
        String prop = "$instOf_" + getName().replace('.', '_');
jaroslav@434
   355
        return hasProperty(obj, prop);
jaroslav@434
   356
    }
jaroslav@434
   357
    
jaroslav@434
   358
    @JavaScriptBody(args = { "who", "prop" }, body = 
jaroslav@434
   359
        "if (who[prop]) return true; else return false;"
jaroslav@434
   360
    )
jaroslav@434
   361
    private static native boolean hasProperty(Object who, String prop);
jaroslav@56
   362
jaroslav@56
   363
jaroslav@56
   364
    /**
jaroslav@56
   365
     * Determines if the class or interface represented by this
jaroslav@56
   366
     * {@code Class} object is either the same as, or is a superclass or
jaroslav@56
   367
     * superinterface of, the class or interface represented by the specified
jaroslav@56
   368
     * {@code Class} parameter. It returns {@code true} if so;
jaroslav@56
   369
     * otherwise it returns {@code false}. If this {@code Class}
jaroslav@56
   370
     * object represents a primitive type, this method returns
jaroslav@56
   371
     * {@code true} if the specified {@code Class} parameter is
jaroslav@56
   372
     * exactly this {@code Class} object; otherwise it returns
jaroslav@56
   373
     * {@code false}.
jaroslav@56
   374
     *
jaroslav@56
   375
     * <p> Specifically, this method tests whether the type represented by the
jaroslav@56
   376
     * specified {@code Class} parameter can be converted to the type
jaroslav@56
   377
     * represented by this {@code Class} object via an identity conversion
jaroslav@56
   378
     * or via a widening reference conversion. See <em>The Java Language
jaroslav@56
   379
     * Specification</em>, sections 5.1.1 and 5.1.4 , for details.
jaroslav@56
   380
     *
jaroslav@56
   381
     * @param cls the {@code Class} object to be checked
jaroslav@56
   382
     * @return the {@code boolean} value indicating whether objects of the
jaroslav@56
   383
     * type {@code cls} can be assigned to objects of this class
jaroslav@56
   384
     * @exception NullPointerException if the specified Class parameter is
jaroslav@56
   385
     *            null.
jaroslav@56
   386
     * @since JDK1.1
jaroslav@56
   387
     */
jaroslav@571
   388
    public boolean isAssignableFrom(Class<?> cls) {
jaroslav@571
   389
        if (this == cls) {
jaroslav@571
   390
            return true;
jaroslav@571
   391
        }
jaroslav@571
   392
        
jaroslav@571
   393
        if (isArray()) {
jaroslav@571
   394
            final Class<?> cmpType = cls.getComponentType();
jaroslav@571
   395
            if (isPrimitive()) {
jaroslav@571
   396
                return this == cmpType;
jaroslav@571
   397
            }
jaroslav@571
   398
            return cmpType != null && getComponentType().isAssignableFrom(cmpType);
jaroslav@571
   399
        }
jaroslav@571
   400
        String prop = "$instOf_" + getName().replace('.', '_');
jaroslav@571
   401
        return hasProperty(cls, prop);
jaroslav@571
   402
    }
jaroslav@56
   403
jaroslav@56
   404
jaroslav@56
   405
    /**
jaroslav@56
   406
     * Determines if the specified {@code Class} object represents an
jaroslav@56
   407
     * interface type.
jaroslav@56
   408
     *
jaroslav@56
   409
     * @return  {@code true} if this object represents an interface;
jaroslav@56
   410
     *          {@code false} otherwise.
jaroslav@56
   411
     */
jaroslav@355
   412
    public boolean isInterface() {
jaroslav@355
   413
        return (getAccess() & 0x200) != 0;
jaroslav@355
   414
    }
jaroslav@355
   415
    
jaroslav@443
   416
    @JavaScriptBody(args = {}, body = "return this.access;")
jaroslav@355
   417
    private native int getAccess();
jaroslav@56
   418
jaroslav@56
   419
jaroslav@56
   420
    /**
jaroslav@56
   421
     * Determines if this {@code Class} object represents an array class.
jaroslav@56
   422
     *
jaroslav@56
   423
     * @return  {@code true} if this object represents an array class;
jaroslav@56
   424
     *          {@code false} otherwise.
jaroslav@56
   425
     * @since   JDK1.1
jaroslav@56
   426
     */
jaroslav@228
   427
    public boolean isArray() {
jaroslav@448
   428
        return hasProperty(this, "array"); // NOI18N
jaroslav@228
   429
    }
jaroslav@56
   430
jaroslav@56
   431
jaroslav@56
   432
    /**
jaroslav@56
   433
     * Determines if the specified {@code Class} object represents a
jaroslav@56
   434
     * primitive type.
jaroslav@56
   435
     *
jaroslav@56
   436
     * <p> There are nine predefined {@code Class} objects to represent
jaroslav@56
   437
     * the eight primitive types and void.  These are created by the Java
jaroslav@56
   438
     * Virtual Machine, and have the same names as the primitive types that
jaroslav@56
   439
     * they represent, namely {@code boolean}, {@code byte},
jaroslav@56
   440
     * {@code char}, {@code short}, {@code int},
jaroslav@56
   441
     * {@code long}, {@code float}, and {@code double}.
jaroslav@56
   442
     *
jaroslav@56
   443
     * <p> These objects may only be accessed via the following public static
jaroslav@56
   444
     * final variables, and are the only {@code Class} objects for which
jaroslav@56
   445
     * this method returns {@code true}.
jaroslav@56
   446
     *
jaroslav@56
   447
     * @return true if and only if this class represents a primitive type
jaroslav@56
   448
     *
jaroslav@56
   449
     * @see     java.lang.Boolean#TYPE
jaroslav@56
   450
     * @see     java.lang.Character#TYPE
jaroslav@56
   451
     * @see     java.lang.Byte#TYPE
jaroslav@56
   452
     * @see     java.lang.Short#TYPE
jaroslav@56
   453
     * @see     java.lang.Integer#TYPE
jaroslav@56
   454
     * @see     java.lang.Long#TYPE
jaroslav@56
   455
     * @see     java.lang.Float#TYPE
jaroslav@56
   456
     * @see     java.lang.Double#TYPE
jaroslav@56
   457
     * @see     java.lang.Void#TYPE
jaroslav@56
   458
     * @since JDK1.1
jaroslav@56
   459
     */
jaroslav@443
   460
    @JavaScriptBody(args = {}, body = 
jaroslav@443
   461
           "if (this.primitive) return true;"
jaroslav@354
   462
        + "else return false;"
jaroslav@354
   463
    )
jaroslav@56
   464
    public native boolean isPrimitive();
jaroslav@56
   465
jaroslav@56
   466
    /**
jaroslav@56
   467
     * Returns true if this {@code Class} object represents an annotation
jaroslav@56
   468
     * type.  Note that if this method returns true, {@link #isInterface()}
jaroslav@56
   469
     * would also return true, as all annotation types are also interfaces.
jaroslav@56
   470
     *
jaroslav@56
   471
     * @return {@code true} if this class object represents an annotation
jaroslav@56
   472
     *      type; {@code false} otherwise
jaroslav@56
   473
     * @since 1.5
jaroslav@56
   474
     */
jaroslav@56
   475
    public boolean isAnnotation() {
jaroslav@56
   476
        return (getModifiers() & ANNOTATION) != 0;
jaroslav@56
   477
    }
jaroslav@56
   478
jaroslav@56
   479
    /**
jaroslav@56
   480
     * Returns {@code true} if this class is a synthetic class;
jaroslav@56
   481
     * returns {@code false} otherwise.
jaroslav@56
   482
     * @return {@code true} if and only if this class is a synthetic class as
jaroslav@56
   483
     *         defined by the Java Language Specification.
jaroslav@56
   484
     * @since 1.5
jaroslav@56
   485
     */
jaroslav@56
   486
    public boolean isSynthetic() {
jaroslav@56
   487
        return (getModifiers() & SYNTHETIC) != 0;
jaroslav@56
   488
    }
jaroslav@56
   489
jaroslav@56
   490
    /**
jaroslav@56
   491
     * Returns the  name of the entity (class, interface, array class,
jaroslav@56
   492
     * primitive type, or void) represented by this {@code Class} object,
jaroslav@56
   493
     * as a {@code String}.
jaroslav@56
   494
     *
jaroslav@56
   495
     * <p> If this class object represents a reference type that is not an
jaroslav@56
   496
     * array type then the binary name of the class is returned, as specified
jaroslav@56
   497
     * by
jaroslav@56
   498
     * <cite>The Java&trade; Language Specification</cite>.
jaroslav@56
   499
     *
jaroslav@56
   500
     * <p> If this class object represents a primitive type or void, then the
jaroslav@56
   501
     * name returned is a {@code String} equal to the Java language
jaroslav@56
   502
     * keyword corresponding to the primitive type or void.
jaroslav@56
   503
     *
jaroslav@56
   504
     * <p> If this class object represents a class of arrays, then the internal
jaroslav@56
   505
     * form of the name consists of the name of the element type preceded by
jaroslav@56
   506
     * one or more '{@code [}' characters representing the depth of the array
jaroslav@56
   507
     * nesting.  The encoding of element type names is as follows:
jaroslav@56
   508
     *
jaroslav@56
   509
     * <blockquote><table summary="Element types and encodings">
jaroslav@56
   510
     * <tr><th> Element Type <th> &nbsp;&nbsp;&nbsp; <th> Encoding
jaroslav@56
   511
     * <tr><td> boolean      <td> &nbsp;&nbsp;&nbsp; <td align=center> Z
jaroslav@56
   512
     * <tr><td> byte         <td> &nbsp;&nbsp;&nbsp; <td align=center> B
jaroslav@56
   513
     * <tr><td> char         <td> &nbsp;&nbsp;&nbsp; <td align=center> C
jaroslav@56
   514
     * <tr><td> class or interface
jaroslav@56
   515
     *                       <td> &nbsp;&nbsp;&nbsp; <td align=center> L<i>classname</i>;
jaroslav@56
   516
     * <tr><td> double       <td> &nbsp;&nbsp;&nbsp; <td align=center> D
jaroslav@56
   517
     * <tr><td> float        <td> &nbsp;&nbsp;&nbsp; <td align=center> F
jaroslav@56
   518
     * <tr><td> int          <td> &nbsp;&nbsp;&nbsp; <td align=center> I
jaroslav@56
   519
     * <tr><td> long         <td> &nbsp;&nbsp;&nbsp; <td align=center> J
jaroslav@56
   520
     * <tr><td> short        <td> &nbsp;&nbsp;&nbsp; <td align=center> S
jaroslav@56
   521
     * </table></blockquote>
jaroslav@56
   522
     *
jaroslav@56
   523
     * <p> The class or interface name <i>classname</i> is the binary name of
jaroslav@56
   524
     * the class specified above.
jaroslav@56
   525
     *
jaroslav@56
   526
     * <p> Examples:
jaroslav@56
   527
     * <blockquote><pre>
jaroslav@56
   528
     * String.class.getName()
jaroslav@56
   529
     *     returns "java.lang.String"
jaroslav@56
   530
     * byte.class.getName()
jaroslav@56
   531
     *     returns "byte"
jaroslav@56
   532
     * (new Object[3]).getClass().getName()
jaroslav@56
   533
     *     returns "[Ljava.lang.Object;"
jaroslav@56
   534
     * (new int[3][4][5][6][7][8][9]).getClass().getName()
jaroslav@56
   535
     *     returns "[[[[[[[I"
jaroslav@56
   536
     * </pre></blockquote>
jaroslav@56
   537
     *
jaroslav@56
   538
     * @return  the name of the class or interface
jaroslav@56
   539
     *          represented by this object.
jaroslav@56
   540
     */
jaroslav@56
   541
    public String getName() {
jaroslav@225
   542
        return jvmName().replace('/', '.');
jaroslav@56
   543
    }
jaroslav@56
   544
jaroslav@443
   545
    @JavaScriptBody(args = {}, body = "return this.jvmName;")
jaroslav@225
   546
    private native String jvmName();
jaroslav@225
   547
jaroslav@260
   548
    
jaroslav@260
   549
    /**
jaroslav@260
   550
     * Returns an array of {@code TypeVariable} objects that represent the
jaroslav@260
   551
     * type variables declared by the generic declaration represented by this
jaroslav@260
   552
     * {@code GenericDeclaration} object, in declaration order.  Returns an
jaroslav@260
   553
     * array of length 0 if the underlying generic declaration declares no type
jaroslav@260
   554
     * variables.
jaroslav@260
   555
     *
jaroslav@260
   556
     * @return an array of {@code TypeVariable} objects that represent
jaroslav@260
   557
     *     the type variables declared by this generic declaration
jaroslav@260
   558
     * @throws java.lang.reflect.GenericSignatureFormatError if the generic
jaroslav@260
   559
     *     signature of this generic declaration does not conform to
jaroslav@260
   560
     *     the format specified in
jaroslav@260
   561
     *     <cite>The Java&trade; Virtual Machine Specification</cite>
jaroslav@260
   562
     * @since 1.5
jaroslav@260
   563
     */
jaroslav@260
   564
    public TypeVariable<Class<T>>[] getTypeParameters() {
jaroslav@260
   565
        throw new UnsupportedOperationException();
jaroslav@260
   566
    }
jaroslav@260
   567
 
jaroslav@56
   568
    /**
jaroslav@56
   569
     * Returns the {@code Class} representing the superclass of the entity
jaroslav@56
   570
     * (class, interface, primitive type or void) represented by this
jaroslav@56
   571
     * {@code Class}.  If this {@code Class} represents either the
jaroslav@56
   572
     * {@code Object} class, an interface, a primitive type, or void, then
jaroslav@56
   573
     * null is returned.  If this object represents an array class then the
jaroslav@56
   574
     * {@code Class} object representing the {@code Object} class is
jaroslav@56
   575
     * returned.
jaroslav@56
   576
     *
jaroslav@56
   577
     * @return the superclass of the class represented by this object.
jaroslav@56
   578
     */
jaroslav@443
   579
    @JavaScriptBody(args = {}, body = "return this.superclass;")
jaroslav@56
   580
    public native Class<? super T> getSuperclass();
jaroslav@56
   581
jaroslav@56
   582
    /**
jaroslav@56
   583
     * Returns the Java language modifiers for this class or interface, encoded
jaroslav@56
   584
     * in an integer. The modifiers consist of the Java Virtual Machine's
jaroslav@56
   585
     * constants for {@code public}, {@code protected},
jaroslav@56
   586
     * {@code private}, {@code final}, {@code static},
jaroslav@56
   587
     * {@code abstract} and {@code interface}; they should be decoded
jaroslav@56
   588
     * using the methods of class {@code Modifier}.
jaroslav@56
   589
     *
jaroslav@56
   590
     * <p> If the underlying class is an array class, then its
jaroslav@56
   591
     * {@code public}, {@code private} and {@code protected}
jaroslav@56
   592
     * modifiers are the same as those of its component type.  If this
jaroslav@56
   593
     * {@code Class} represents a primitive type or void, its
jaroslav@56
   594
     * {@code public} modifier is always {@code true}, and its
jaroslav@56
   595
     * {@code protected} and {@code private} modifiers are always
jaroslav@56
   596
     * {@code false}. If this object represents an array class, a
jaroslav@56
   597
     * primitive type or void, then its {@code final} modifier is always
jaroslav@56
   598
     * {@code true} and its interface modifier is always
jaroslav@56
   599
     * {@code false}. The values of its other modifiers are not determined
jaroslav@56
   600
     * by this specification.
jaroslav@56
   601
     *
jaroslav@56
   602
     * <p> The modifier encodings are defined in <em>The Java Virtual Machine
jaroslav@56
   603
     * Specification</em>, table 4.1.
jaroslav@56
   604
     *
jaroslav@56
   605
     * @return the {@code int} representing the modifiers for this class
jaroslav@56
   606
     * @see     java.lang.reflect.Modifier
jaroslav@56
   607
     * @since JDK1.1
jaroslav@56
   608
     */
jaroslav@586
   609
    public int getModifiers() {
jaroslav@586
   610
        return getAccess();
jaroslav@586
   611
    }
jaroslav@56
   612
jaroslav@56
   613
jaroslav@56
   614
    /**
jaroslav@56
   615
     * Returns the simple name of the underlying class as given in the
jaroslav@56
   616
     * source code. Returns an empty string if the underlying class is
jaroslav@56
   617
     * anonymous.
jaroslav@56
   618
     *
jaroslav@56
   619
     * <p>The simple name of an array is the simple name of the
jaroslav@56
   620
     * component type with "[]" appended.  In particular the simple
jaroslav@56
   621
     * name of an array whose component type is anonymous is "[]".
jaroslav@56
   622
     *
jaroslav@56
   623
     * @return the simple name of the underlying class
jaroslav@56
   624
     * @since 1.5
jaroslav@56
   625
     */
jaroslav@56
   626
    public String getSimpleName() {
jaroslav@229
   627
        if (isArray())
jaroslav@229
   628
            return getComponentType().getSimpleName()+"[]";
jaroslav@229
   629
jaroslav@229
   630
        String simpleName = getSimpleBinaryName();
jaroslav@229
   631
        if (simpleName == null) { // top level class
jaroslav@229
   632
            simpleName = getName();
jaroslav@229
   633
            return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
jaroslav@229
   634
        }
jaroslav@229
   635
        // According to JLS3 "Binary Compatibility" (13.1) the binary
jaroslav@229
   636
        // name of non-package classes (not top level) is the binary
jaroslav@229
   637
        // name of the immediately enclosing class followed by a '$' followed by:
jaroslav@229
   638
        // (for nested and inner classes): the simple name.
jaroslav@229
   639
        // (for local classes): 1 or more digits followed by the simple name.
jaroslav@229
   640
        // (for anonymous classes): 1 or more digits.
jaroslav@229
   641
jaroslav@229
   642
        // Since getSimpleBinaryName() will strip the binary name of
jaroslav@229
   643
        // the immediatly enclosing class, we are now looking at a
jaroslav@229
   644
        // string that matches the regular expression "\$[0-9]*"
jaroslav@229
   645
        // followed by a simple name (considering the simple of an
jaroslav@229
   646
        // anonymous class to be the empty string).
jaroslav@229
   647
jaroslav@229
   648
        // Remove leading "\$[0-9]*" from the name
jaroslav@229
   649
        int length = simpleName.length();
jaroslav@229
   650
        if (length < 1 || simpleName.charAt(0) != '$')
jaroslav@229
   651
            throw new IllegalStateException("Malformed class name");
jaroslav@229
   652
        int index = 1;
jaroslav@229
   653
        while (index < length && isAsciiDigit(simpleName.charAt(index)))
jaroslav@229
   654
            index++;
jaroslav@229
   655
        // Eventually, this is the empty string iff this is an anonymous class
jaroslav@229
   656
        return simpleName.substring(index);
jaroslav@56
   657
    }
jaroslav@56
   658
jaroslav@56
   659
    /**
jaroslav@229
   660
     * Returns the "simple binary name" of the underlying class, i.e.,
jaroslav@229
   661
     * the binary name without the leading enclosing class name.
jaroslav@229
   662
     * Returns {@code null} if the underlying class is a top level
jaroslav@229
   663
     * class.
jaroslav@229
   664
     */
jaroslav@229
   665
    private String getSimpleBinaryName() {
jaroslav@229
   666
        Class<?> enclosingClass = null; // XXX getEnclosingClass();
jaroslav@229
   667
        if (enclosingClass == null) // top level class
jaroslav@229
   668
            return null;
jaroslav@229
   669
        // Otherwise, strip the enclosing class' name
jaroslav@229
   670
        try {
jaroslav@229
   671
            return getName().substring(enclosingClass.getName().length());
jaroslav@229
   672
        } catch (IndexOutOfBoundsException ex) {
jaroslav@229
   673
            throw new IllegalStateException("Malformed class name");
jaroslav@229
   674
        }
jaroslav@229
   675
    }
jaroslav@261
   676
jaroslav@261
   677
    /**
jaroslav@261
   678
     * Returns an array containing {@code Field} objects reflecting all
jaroslav@261
   679
     * the accessible public fields of the class or interface represented by
jaroslav@261
   680
     * this {@code Class} object.  The elements in the array returned are
jaroslav@261
   681
     * not sorted and are not in any particular order.  This method returns an
jaroslav@261
   682
     * array of length 0 if the class or interface has no accessible public
jaroslav@261
   683
     * fields, or if it represents an array class, a primitive type, or void.
jaroslav@261
   684
     *
jaroslav@261
   685
     * <p> Specifically, if this {@code Class} object represents a class,
jaroslav@261
   686
     * this method returns the public fields of this class and of all its
jaroslav@261
   687
     * superclasses.  If this {@code Class} object represents an
jaroslav@261
   688
     * interface, this method returns the fields of this interface and of all
jaroslav@261
   689
     * its superinterfaces.
jaroslav@261
   690
     *
jaroslav@261
   691
     * <p> The implicit length field for array class is not reflected by this
jaroslav@261
   692
     * method. User code should use the methods of class {@code Array} to
jaroslav@261
   693
     * manipulate arrays.
jaroslav@261
   694
     *
jaroslav@261
   695
     * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.3.
jaroslav@261
   696
     *
jaroslav@261
   697
     * @return the array of {@code Field} objects representing the
jaroslav@261
   698
     * public fields
jaroslav@261
   699
     * @exception  SecurityException
jaroslav@261
   700
     *             If a security manager, <i>s</i>, is present and any of the
jaroslav@261
   701
     *             following conditions is met:
jaroslav@261
   702
     *
jaroslav@261
   703
     *             <ul>
jaroslav@261
   704
     *
jaroslav@261
   705
     *             <li> invocation of
jaroslav@261
   706
     *             {@link SecurityManager#checkMemberAccess
jaroslav@261
   707
     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
jaroslav@261
   708
     *             access to the fields within this class
jaroslav@261
   709
     *
jaroslav@261
   710
     *             <li> the caller's class loader is not the same as or an
jaroslav@261
   711
     *             ancestor of the class loader for the current class and
jaroslav@261
   712
     *             invocation of {@link SecurityManager#checkPackageAccess
jaroslav@261
   713
     *             s.checkPackageAccess()} denies access to the package
jaroslav@261
   714
     *             of this class
jaroslav@261
   715
     *
jaroslav@261
   716
     *             </ul>
jaroslav@261
   717
     *
jaroslav@261
   718
     * @since JDK1.1
jaroslav@261
   719
     */
jaroslav@261
   720
    public Field[] getFields() throws SecurityException {
jaroslav@261
   721
        throw new SecurityException();
jaroslav@261
   722
    }
jaroslav@261
   723
jaroslav@261
   724
    /**
jaroslav@261
   725
     * Returns an array containing {@code Method} objects reflecting all
jaroslav@261
   726
     * the public <em>member</em> methods of the class or interface represented
jaroslav@261
   727
     * by this {@code Class} object, including those declared by the class
jaroslav@261
   728
     * or interface and those inherited from superclasses and
jaroslav@261
   729
     * superinterfaces.  Array classes return all the (public) member methods
jaroslav@261
   730
     * inherited from the {@code Object} class.  The elements in the array
jaroslav@261
   731
     * returned are not sorted and are not in any particular order.  This
jaroslav@261
   732
     * method returns an array of length 0 if this {@code Class} object
jaroslav@261
   733
     * represents a class or interface that has no public member methods, or if
jaroslav@261
   734
     * this {@code Class} object represents a primitive type or void.
jaroslav@261
   735
     *
jaroslav@261
   736
     * <p> The class initialization method {@code <clinit>} is not
jaroslav@261
   737
     * included in the returned array. If the class declares multiple public
jaroslav@261
   738
     * member methods with the same parameter types, they are all included in
jaroslav@261
   739
     * the returned array.
jaroslav@261
   740
     *
jaroslav@261
   741
     * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.4.
jaroslav@261
   742
     *
jaroslav@261
   743
     * @return the array of {@code Method} objects representing the
jaroslav@261
   744
     * public methods of this class
jaroslav@261
   745
     * @exception  SecurityException
jaroslav@261
   746
     *             If a security manager, <i>s</i>, is present and any of the
jaroslav@261
   747
     *             following conditions is met:
jaroslav@261
   748
     *
jaroslav@261
   749
     *             <ul>
jaroslav@261
   750
     *
jaroslav@261
   751
     *             <li> invocation of
jaroslav@261
   752
     *             {@link SecurityManager#checkMemberAccess
jaroslav@261
   753
     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
jaroslav@261
   754
     *             access to the methods within this class
jaroslav@261
   755
     *
jaroslav@261
   756
     *             <li> the caller's class loader is not the same as or an
jaroslav@261
   757
     *             ancestor of the class loader for the current class and
jaroslav@261
   758
     *             invocation of {@link SecurityManager#checkPackageAccess
jaroslav@261
   759
     *             s.checkPackageAccess()} denies access to the package
jaroslav@261
   760
     *             of this class
jaroslav@261
   761
     *
jaroslav@261
   762
     *             </ul>
jaroslav@261
   763
     *
jaroslav@261
   764
     * @since JDK1.1
jaroslav@261
   765
     */
jaroslav@261
   766
    public Method[] getMethods() throws SecurityException {
jaroslav@392
   767
        return MethodImpl.findMethods(this, 0x01);
jaroslav@261
   768
    }
jaroslav@261
   769
jaroslav@261
   770
    /**
jaroslav@261
   771
     * Returns a {@code Field} object that reflects the specified public
jaroslav@261
   772
     * member field of the class or interface represented by this
jaroslav@261
   773
     * {@code Class} object. The {@code name} parameter is a
jaroslav@261
   774
     * {@code String} specifying the simple name of the desired field.
jaroslav@261
   775
     *
jaroslav@261
   776
     * <p> The field to be reflected is determined by the algorithm that
jaroslav@261
   777
     * follows.  Let C be the class represented by this object:
jaroslav@261
   778
     * <OL>
jaroslav@261
   779
     * <LI> If C declares a public field with the name specified, that is the
jaroslav@261
   780
     *      field to be reflected.</LI>
jaroslav@261
   781
     * <LI> If no field was found in step 1 above, this algorithm is applied
jaroslav@261
   782
     *      recursively to each direct superinterface of C. The direct
jaroslav@261
   783
     *      superinterfaces are searched in the order they were declared.</LI>
jaroslav@261
   784
     * <LI> If no field was found in steps 1 and 2 above, and C has a
jaroslav@261
   785
     *      superclass S, then this algorithm is invoked recursively upon S.
jaroslav@261
   786
     *      If C has no superclass, then a {@code NoSuchFieldException}
jaroslav@261
   787
     *      is thrown.</LI>
jaroslav@261
   788
     * </OL>
jaroslav@261
   789
     *
jaroslav@261
   790
     * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.3.
jaroslav@261
   791
     *
jaroslav@261
   792
     * @param name the field name
jaroslav@261
   793
     * @return  the {@code Field} object of this class specified by
jaroslav@261
   794
     * {@code name}
jaroslav@261
   795
     * @exception NoSuchFieldException if a field with the specified name is
jaroslav@261
   796
     *              not found.
jaroslav@261
   797
     * @exception NullPointerException if {@code name} is {@code null}
jaroslav@261
   798
     * @exception  SecurityException
jaroslav@261
   799
     *             If a security manager, <i>s</i>, is present and any of the
jaroslav@261
   800
     *             following conditions is met:
jaroslav@261
   801
     *
jaroslav@261
   802
     *             <ul>
jaroslav@261
   803
     *
jaroslav@261
   804
     *             <li> invocation of
jaroslav@261
   805
     *             {@link SecurityManager#checkMemberAccess
jaroslav@261
   806
     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
jaroslav@261
   807
     *             access to the field
jaroslav@261
   808
     *
jaroslav@261
   809
     *             <li> the caller's class loader is not the same as or an
jaroslav@261
   810
     *             ancestor of the class loader for the current class and
jaroslav@261
   811
     *             invocation of {@link SecurityManager#checkPackageAccess
jaroslav@261
   812
     *             s.checkPackageAccess()} denies access to the package
jaroslav@261
   813
     *             of this class
jaroslav@261
   814
     *
jaroslav@261
   815
     *             </ul>
jaroslav@261
   816
     *
jaroslav@261
   817
     * @since JDK1.1
jaroslav@261
   818
     */
jaroslav@261
   819
    public Field getField(String name)
jaroslav@261
   820
        throws SecurityException {
jaroslav@261
   821
        throw new SecurityException();
jaroslav@261
   822
    }
jaroslav@229
   823
    
jaroslav@261
   824
    
jaroslav@261
   825
    /**
jaroslav@261
   826
     * Returns a {@code Method} object that reflects the specified public
jaroslav@261
   827
     * member method of the class or interface represented by this
jaroslav@261
   828
     * {@code Class} object. The {@code name} parameter is a
jaroslav@261
   829
     * {@code String} specifying the simple name of the desired method. The
jaroslav@261
   830
     * {@code parameterTypes} parameter is an array of {@code Class}
jaroslav@261
   831
     * objects that identify the method's formal parameter types, in declared
jaroslav@261
   832
     * order. If {@code parameterTypes} is {@code null}, it is
jaroslav@261
   833
     * treated as if it were an empty array.
jaroslav@261
   834
     *
jaroslav@261
   835
     * <p> If the {@code name} is "{@code <init>};"or "{@code <clinit>}" a
jaroslav@261
   836
     * {@code NoSuchMethodException} is raised. Otherwise, the method to
jaroslav@261
   837
     * be reflected is determined by the algorithm that follows.  Let C be the
jaroslav@261
   838
     * class represented by this object:
jaroslav@261
   839
     * <OL>
jaroslav@261
   840
     * <LI> C is searched for any <I>matching methods</I>. If no matching
jaroslav@261
   841
     *      method is found, the algorithm of step 1 is invoked recursively on
jaroslav@261
   842
     *      the superclass of C.</LI>
jaroslav@261
   843
     * <LI> If no method was found in step 1 above, the superinterfaces of C
jaroslav@261
   844
     *      are searched for a matching method. If any such method is found, it
jaroslav@261
   845
     *      is reflected.</LI>
jaroslav@261
   846
     * </OL>
jaroslav@261
   847
     *
jaroslav@261
   848
     * To find a matching method in a class C:&nbsp; If C declares exactly one
jaroslav@261
   849
     * public method with the specified name and exactly the same formal
jaroslav@261
   850
     * parameter types, that is the method reflected. If more than one such
jaroslav@261
   851
     * method is found in C, and one of these methods has a return type that is
jaroslav@261
   852
     * more specific than any of the others, that method is reflected;
jaroslav@261
   853
     * otherwise one of the methods is chosen arbitrarily.
jaroslav@261
   854
     *
jaroslav@261
   855
     * <p>Note that there may be more than one matching method in a
jaroslav@261
   856
     * class because while the Java language forbids a class to
jaroslav@261
   857
     * declare multiple methods with the same signature but different
jaroslav@261
   858
     * return types, the Java virtual machine does not.  This
jaroslav@261
   859
     * increased flexibility in the virtual machine can be used to
jaroslav@261
   860
     * implement various language features.  For example, covariant
jaroslav@261
   861
     * returns can be implemented with {@linkplain
jaroslav@261
   862
     * java.lang.reflect.Method#isBridge bridge methods}; the bridge
jaroslav@261
   863
     * method and the method being overridden would have the same
jaroslav@261
   864
     * signature but different return types.
jaroslav@261
   865
     *
jaroslav@261
   866
     * <p> See <em>The Java Language Specification</em>, sections 8.2 and 8.4.
jaroslav@261
   867
     *
jaroslav@261
   868
     * @param name the name of the method
jaroslav@261
   869
     * @param parameterTypes the list of parameters
jaroslav@261
   870
     * @return the {@code Method} object that matches the specified
jaroslav@261
   871
     * {@code name} and {@code parameterTypes}
jaroslav@261
   872
     * @exception NoSuchMethodException if a matching method is not found
jaroslav@261
   873
     *            or if the name is "&lt;init&gt;"or "&lt;clinit&gt;".
jaroslav@261
   874
     * @exception NullPointerException if {@code name} is {@code null}
jaroslav@261
   875
     * @exception  SecurityException
jaroslav@261
   876
     *             If a security manager, <i>s</i>, is present and any of the
jaroslav@261
   877
     *             following conditions is met:
jaroslav@261
   878
     *
jaroslav@261
   879
     *             <ul>
jaroslav@261
   880
     *
jaroslav@261
   881
     *             <li> invocation of
jaroslav@261
   882
     *             {@link SecurityManager#checkMemberAccess
jaroslav@261
   883
     *             s.checkMemberAccess(this, Member.PUBLIC)} denies
jaroslav@261
   884
     *             access to the method
jaroslav@261
   885
     *
jaroslav@261
   886
     *             <li> the caller's class loader is not the same as or an
jaroslav@261
   887
     *             ancestor of the class loader for the current class and
jaroslav@261
   888
     *             invocation of {@link SecurityManager#checkPackageAccess
jaroslav@261
   889
     *             s.checkPackageAccess()} denies access to the package
jaroslav@261
   890
     *             of this class
jaroslav@261
   891
     *
jaroslav@261
   892
     *             </ul>
jaroslav@261
   893
     *
jaroslav@261
   894
     * @since JDK1.1
jaroslav@261
   895
     */
jaroslav@261
   896
    public Method getMethod(String name, Class<?>... parameterTypes)
jaroslav@420
   897
        throws SecurityException, NoSuchMethodException {
jaroslav@391
   898
        Method m = MethodImpl.findMethod(this, name, parameterTypes);
jaroslav@262
   899
        if (m == null) {
jaroslav@420
   900
            StringBuilder sb = new StringBuilder();
jaroslav@420
   901
            sb.append(getName()).append('.').append(name).append('(');
jaroslav@420
   902
            String sep = "";
jaroslav@420
   903
            for (int i = 0; i < parameterTypes.length; i++) {
jaroslav@420
   904
                sb.append(sep).append(parameterTypes[i].getName());
jaroslav@420
   905
                sep = ", ";
jaroslav@420
   906
            }
jaroslav@420
   907
            sb.append(')');
jaroslav@420
   908
            throw new NoSuchMethodException(sb.toString());
jaroslav@262
   909
        }
jaroslav@262
   910
        return m;
jaroslav@261
   911
    }
jaroslav@261
   912
jaroslav@229
   913
    /**
jaroslav@56
   914
     * Character.isDigit answers {@code true} to some non-ascii
jaroslav@56
   915
     * digits.  This one does not.
jaroslav@56
   916
     */
jaroslav@56
   917
    private static boolean isAsciiDigit(char c) {
jaroslav@56
   918
        return '0' <= c && c <= '9';
jaroslav@56
   919
    }
jaroslav@56
   920
jaroslav@56
   921
    /**
jaroslav@56
   922
     * Returns the canonical name of the underlying class as
jaroslav@56
   923
     * defined by the Java Language Specification.  Returns null if
jaroslav@56
   924
     * the underlying class does not have a canonical name (i.e., if
jaroslav@56
   925
     * it is a local or anonymous class or an array whose component
jaroslav@56
   926
     * type does not have a canonical name).
jaroslav@56
   927
     * @return the canonical name of the underlying class if it exists, and
jaroslav@56
   928
     * {@code null} otherwise.
jaroslav@56
   929
     * @since 1.5
jaroslav@56
   930
     */
jaroslav@56
   931
    public String getCanonicalName() {
jaroslav@228
   932
        if (isArray()) {
jaroslav@228
   933
            String canonicalName = getComponentType().getCanonicalName();
jaroslav@228
   934
            if (canonicalName != null)
jaroslav@228
   935
                return canonicalName + "[]";
jaroslav@228
   936
            else
jaroslav@228
   937
                return null;
jaroslav@228
   938
        }
jaroslav@65
   939
//        if (isLocalOrAnonymousClass())
jaroslav@65
   940
//            return null;
jaroslav@65
   941
//        Class<?> enclosingClass = getEnclosingClass();
jaroslav@228
   942
        Class<?> enclosingClass = null;
jaroslav@228
   943
        if (enclosingClass == null) { // top level class
jaroslav@228
   944
            return getName();
jaroslav@228
   945
        } else {
jaroslav@228
   946
            String enclosingName = enclosingClass.getCanonicalName();
jaroslav@228
   947
            if (enclosingName == null)
jaroslav@228
   948
                return null;
jaroslav@228
   949
            return enclosingName + "." + getSimpleName();
jaroslav@228
   950
        }
jaroslav@56
   951
    }
jaroslav@56
   952
jaroslav@56
   953
    /**
jaroslav@56
   954
     * Finds a resource with a given name.  The rules for searching resources
jaroslav@56
   955
     * associated with a given class are implemented by the defining
jaroslav@56
   956
     * {@linkplain ClassLoader class loader} of the class.  This method
jaroslav@56
   957
     * delegates to this object's class loader.  If this object was loaded by
jaroslav@56
   958
     * the bootstrap class loader, the method delegates to {@link
jaroslav@56
   959
     * ClassLoader#getSystemResourceAsStream}.
jaroslav@56
   960
     *
jaroslav@56
   961
     * <p> Before delegation, an absolute resource name is constructed from the
jaroslav@56
   962
     * given resource name using this algorithm:
jaroslav@56
   963
     *
jaroslav@56
   964
     * <ul>
jaroslav@56
   965
     *
jaroslav@56
   966
     * <li> If the {@code name} begins with a {@code '/'}
jaroslav@56
   967
     * (<tt>'&#92;u002f'</tt>), then the absolute name of the resource is the
jaroslav@56
   968
     * portion of the {@code name} following the {@code '/'}.
jaroslav@56
   969
     *
jaroslav@56
   970
     * <li> Otherwise, the absolute name is of the following form:
jaroslav@56
   971
     *
jaroslav@56
   972
     * <blockquote>
jaroslav@56
   973
     *   {@code modified_package_name/name}
jaroslav@56
   974
     * </blockquote>
jaroslav@56
   975
     *
jaroslav@56
   976
     * <p> Where the {@code modified_package_name} is the package name of this
jaroslav@56
   977
     * object with {@code '/'} substituted for {@code '.'}
jaroslav@56
   978
     * (<tt>'&#92;u002e'</tt>).
jaroslav@56
   979
     *
jaroslav@56
   980
     * </ul>
jaroslav@56
   981
     *
jaroslav@56
   982
     * @param  name name of the desired resource
jaroslav@56
   983
     * @return      A {@link java.io.InputStream} object or {@code null} if
jaroslav@56
   984
     *              no resource with this name is found
jaroslav@56
   985
     * @throws  NullPointerException If {@code name} is {@code null}
jaroslav@56
   986
     * @since  JDK1.1
jaroslav@56
   987
     */
jaroslav@122
   988
     public InputStream getResourceAsStream(String name) {
jaroslav@122
   989
        name = resolveName(name);
jaroslav@424
   990
        byte[] arr = getResourceAsStream0(name);
jaroslav@424
   991
        return arr == null ? null : new ByteArrayInputStream(arr);
jaroslav@424
   992
     }
jaroslav@424
   993
     
jaroslav@424
   994
     @JavaScriptBody(args = "name", body = 
jaroslav@424
   995
         "return (vm.loadBytes) ? vm.loadBytes(name) : null;"
jaroslav@424
   996
     )
jaroslav@424
   997
     private static native byte[] getResourceAsStream0(String name);
jaroslav@56
   998
jaroslav@56
   999
    /**
jaroslav@56
  1000
     * Finds a resource with a given name.  The rules for searching resources
jaroslav@56
  1001
     * associated with a given class are implemented by the defining
jaroslav@56
  1002
     * {@linkplain ClassLoader class loader} of the class.  This method
jaroslav@56
  1003
     * delegates to this object's class loader.  If this object was loaded by
jaroslav@56
  1004
     * the bootstrap class loader, the method delegates to {@link
jaroslav@56
  1005
     * ClassLoader#getSystemResource}.
jaroslav@56
  1006
     *
jaroslav@56
  1007
     * <p> Before delegation, an absolute resource name is constructed from the
jaroslav@56
  1008
     * given resource name using this algorithm:
jaroslav@56
  1009
     *
jaroslav@56
  1010
     * <ul>
jaroslav@56
  1011
     *
jaroslav@56
  1012
     * <li> If the {@code name} begins with a {@code '/'}
jaroslav@56
  1013
     * (<tt>'&#92;u002f'</tt>), then the absolute name of the resource is the
jaroslav@56
  1014
     * portion of the {@code name} following the {@code '/'}.
jaroslav@56
  1015
     *
jaroslav@56
  1016
     * <li> Otherwise, the absolute name is of the following form:
jaroslav@56
  1017
     *
jaroslav@56
  1018
     * <blockquote>
jaroslav@56
  1019
     *   {@code modified_package_name/name}
jaroslav@56
  1020
     * </blockquote>
jaroslav@56
  1021
     *
jaroslav@56
  1022
     * <p> Where the {@code modified_package_name} is the package name of this
jaroslav@56
  1023
     * object with {@code '/'} substituted for {@code '.'}
jaroslav@56
  1024
     * (<tt>'&#92;u002e'</tt>).
jaroslav@56
  1025
     *
jaroslav@56
  1026
     * </ul>
jaroslav@56
  1027
     *
jaroslav@56
  1028
     * @param  name name of the desired resource
jaroslav@56
  1029
     * @return      A  {@link java.net.URL} object or {@code null} if no
jaroslav@56
  1030
     *              resource with this name is found
jaroslav@56
  1031
     * @since  JDK1.1
jaroslav@56
  1032
     */
jaroslav@122
  1033
    public java.net.URL getResource(String name) {
jaroslav@576
  1034
        InputStream is = getResourceAsStream(name);
jaroslav@576
  1035
        return is == null ? null : newResourceURL(URL.class, "res:/" + name, is);
jaroslav@122
  1036
    }
jaroslav@576
  1037
    
jaroslav@576
  1038
    @JavaScriptBody(args = { "url", "spec", "is" }, body = 
jaroslav@576
  1039
        "var u = url.cnstr(true);\n"
jaroslav@576
  1040
      + "u.constructor.cons__VLjava_lang_String_2Ljava_io_InputStream_2.call(u, spec, is);\n"
jaroslav@576
  1041
      + "return u;"
jaroslav@576
  1042
    )
jaroslav@576
  1043
    private static native URL newResourceURL(Class<URL> url, String spec, InputStream is);
jaroslav@56
  1044
jaroslav@122
  1045
   /**
jaroslav@122
  1046
     * Add a package name prefix if the name is not absolute Remove leading "/"
jaroslav@122
  1047
     * if name is absolute
jaroslav@122
  1048
     */
jaroslav@122
  1049
    private String resolveName(String name) {
jaroslav@122
  1050
        if (name == null) {
jaroslav@122
  1051
            return name;
jaroslav@122
  1052
        }
jaroslav@122
  1053
        if (!name.startsWith("/")) {
jaroslav@122
  1054
            Class<?> c = this;
jaroslav@122
  1055
            while (c.isArray()) {
jaroslav@122
  1056
                c = c.getComponentType();
jaroslav@122
  1057
            }
jaroslav@122
  1058
            String baseName = c.getName();
jaroslav@122
  1059
            int index = baseName.lastIndexOf('.');
jaroslav@122
  1060
            if (index != -1) {
jaroslav@122
  1061
                name = baseName.substring(0, index).replace('.', '/')
jaroslav@122
  1062
                    +"/"+name;
jaroslav@122
  1063
            }
jaroslav@122
  1064
        } else {
jaroslav@122
  1065
            name = name.substring(1);
jaroslav@122
  1066
        }
jaroslav@122
  1067
        return name;
jaroslav@122
  1068
    }
jaroslav@122
  1069
    
jaroslav@122
  1070
    /**
jaroslav@122
  1071
     * Returns the class loader for the class.  Some implementations may use
jaroslav@122
  1072
     * null to represent the bootstrap class loader. This method will return
jaroslav@122
  1073
     * null in such implementations if this class was loaded by the bootstrap
jaroslav@122
  1074
     * class loader.
jaroslav@122
  1075
     *
jaroslav@122
  1076
     * <p> If a security manager is present, and the caller's class loader is
jaroslav@122
  1077
     * not null and the caller's class loader is not the same as or an ancestor of
jaroslav@122
  1078
     * the class loader for the class whose class loader is requested, then
jaroslav@122
  1079
     * this method calls the security manager's {@code checkPermission}
jaroslav@122
  1080
     * method with a {@code RuntimePermission("getClassLoader")}
jaroslav@122
  1081
     * permission to ensure it's ok to access the class loader for the class.
jaroslav@122
  1082
     *
jaroslav@122
  1083
     * <p>If this object
jaroslav@122
  1084
     * represents a primitive type or void, null is returned.
jaroslav@122
  1085
     *
jaroslav@122
  1086
     * @return  the class loader that loaded the class or interface
jaroslav@122
  1087
     *          represented by this object.
jaroslav@122
  1088
     * @throws SecurityException
jaroslav@122
  1089
     *    if a security manager exists and its
jaroslav@122
  1090
     *    {@code checkPermission} method denies
jaroslav@122
  1091
     *    access to the class loader for the class.
jaroslav@122
  1092
     * @see java.lang.ClassLoader
jaroslav@122
  1093
     * @see SecurityManager#checkPermission
jaroslav@122
  1094
     * @see java.lang.RuntimePermission
jaroslav@122
  1095
     */
jaroslav@122
  1096
    public ClassLoader getClassLoader() {
jaroslav@122
  1097
        throw new SecurityException();
jaroslav@122
  1098
    }
jaroslav@122
  1099
    
jaroslav@122
  1100
    /**
jaroslav@122
  1101
     * Returns the {@code Class} representing the component type of an
jaroslav@122
  1102
     * array.  If this class does not represent an array class this method
jaroslav@122
  1103
     * returns null.
jaroslav@122
  1104
     *
jaroslav@122
  1105
     * @return the {@code Class} representing the component type of this
jaroslav@122
  1106
     * class if this class is an array
jaroslav@122
  1107
     * @see     java.lang.reflect.Array
jaroslav@122
  1108
     * @since JDK1.1
jaroslav@122
  1109
     */
jaroslav@228
  1110
    public Class<?> getComponentType() {
jaroslav@451
  1111
        if (isArray()) {
jaroslav@451
  1112
            try {
jaroslav@451
  1113
                return getComponentType0();
jaroslav@451
  1114
            } catch (ClassNotFoundException cnfe) {
jaroslav@451
  1115
                throw new IllegalStateException(cnfe);
jaroslav@451
  1116
            }
jaroslav@451
  1117
        }
jaroslav@228
  1118
        return null;
jaroslav@228
  1119
    }
jaroslav@56
  1120
jaroslav@451
  1121
    private Class<?> getComponentType0() throws ClassNotFoundException {
jaroslav@451
  1122
        String n = getName().substring(1);
jaroslav@451
  1123
        switch (n.charAt(0)) {
jaroslav@451
  1124
            case 'L': 
jaroslav@451
  1125
                n = n.substring(1, n.length() - 1);
jaroslav@451
  1126
                return Class.forName(n);
jaroslav@451
  1127
            case 'I':
jaroslav@451
  1128
                return Integer.TYPE;
jaroslav@451
  1129
            case 'J':
jaroslav@451
  1130
                return Long.TYPE;
jaroslav@451
  1131
            case 'D':
jaroslav@451
  1132
                return Double.TYPE;
jaroslav@451
  1133
            case 'F':
jaroslav@451
  1134
                return Float.TYPE;
jaroslav@451
  1135
            case 'B':
jaroslav@451
  1136
                return Byte.TYPE;
jaroslav@451
  1137
            case 'Z':
jaroslav@451
  1138
                return Boolean.TYPE;
jaroslav@451
  1139
            case 'S':
jaroslav@451
  1140
                return Short.TYPE;
jaroslav@451
  1141
            case 'V':
jaroslav@451
  1142
                return Void.TYPE;
jaroslav@451
  1143
            case 'C':
jaroslav@451
  1144
                return Character.TYPE;
jaroslav@451
  1145
            case '[':
jaroslav@451
  1146
                return defineArray(n);
jaroslav@451
  1147
            default:
jaroslav@451
  1148
                throw new ClassNotFoundException("Unknown component type of " + getName());
jaroslav@451
  1149
        }
jaroslav@451
  1150
    }
jaroslav@451
  1151
    
jaroslav@450
  1152
    @JavaScriptBody(args = { "sig" }, body = 
jaroslav@450
  1153
        "var c = Array[sig];\n" +
jaroslav@450
  1154
        "if (c) return c;\n" +
jaroslav@450
  1155
        "c = vm.java_lang_Class(true);\n" +
jaroslav@450
  1156
        "c.jvmName = sig;\n" +
jaroslav@450
  1157
        "c.superclass = vm.java_lang_Object(false).$class;\n" +
jaroslav@450
  1158
        "c.array = true;\n" +
jaroslav@450
  1159
        "Array[sig] = c;\n" +
jaroslav@450
  1160
        "return c;"
jaroslav@450
  1161
    )
jaroslav@450
  1162
    private static native Class<?> defineArray(String sig);
jaroslav@450
  1163
    
jaroslav@56
  1164
    /**
jaroslav@56
  1165
     * Returns true if and only if this class was declared as an enum in the
jaroslav@56
  1166
     * source code.
jaroslav@56
  1167
     *
jaroslav@56
  1168
     * @return true if and only if this class was declared as an enum in the
jaroslav@56
  1169
     *     source code
jaroslav@56
  1170
     * @since 1.5
jaroslav@56
  1171
     */
jaroslav@56
  1172
    public boolean isEnum() {
jaroslav@56
  1173
        // An enum must both directly extend java.lang.Enum and have
jaroslav@56
  1174
        // the ENUM bit set; classes for specialized enum constants
jaroslav@56
  1175
        // don't do the former.
jaroslav@56
  1176
        return (this.getModifiers() & ENUM) != 0 &&
jaroslav@56
  1177
        this.getSuperclass() == java.lang.Enum.class;
jaroslav@56
  1178
    }
jaroslav@56
  1179
jaroslav@56
  1180
    /**
jaroslav@56
  1181
     * Casts an object to the class or interface represented
jaroslav@56
  1182
     * by this {@code Class} object.
jaroslav@56
  1183
     *
jaroslav@56
  1184
     * @param obj the object to be cast
jaroslav@56
  1185
     * @return the object after casting, or null if obj is null
jaroslav@56
  1186
     *
jaroslav@56
  1187
     * @throws ClassCastException if the object is not
jaroslav@56
  1188
     * null and is not assignable to the type T.
jaroslav@56
  1189
     *
jaroslav@56
  1190
     * @since 1.5
jaroslav@56
  1191
     */
jaroslav@56
  1192
    public T cast(Object obj) {
jaroslav@56
  1193
        if (obj != null && !isInstance(obj))
jaroslav@56
  1194
            throw new ClassCastException(cannotCastMsg(obj));
jaroslav@56
  1195
        return (T) obj;
jaroslav@56
  1196
    }
jaroslav@56
  1197
jaroslav@56
  1198
    private String cannotCastMsg(Object obj) {
jaroslav@56
  1199
        return "Cannot cast " + obj.getClass().getName() + " to " + getName();
jaroslav@56
  1200
    }
jaroslav@56
  1201
jaroslav@56
  1202
    /**
jaroslav@56
  1203
     * Casts this {@code Class} object to represent a subclass of the class
jaroslav@56
  1204
     * represented by the specified class object.  Checks that that the cast
jaroslav@56
  1205
     * is valid, and throws a {@code ClassCastException} if it is not.  If
jaroslav@56
  1206
     * this method succeeds, it always returns a reference to this class object.
jaroslav@56
  1207
     *
jaroslav@56
  1208
     * <p>This method is useful when a client needs to "narrow" the type of
jaroslav@56
  1209
     * a {@code Class} object to pass it to an API that restricts the
jaroslav@56
  1210
     * {@code Class} objects that it is willing to accept.  A cast would
jaroslav@56
  1211
     * generate a compile-time warning, as the correctness of the cast
jaroslav@56
  1212
     * could not be checked at runtime (because generic types are implemented
jaroslav@56
  1213
     * by erasure).
jaroslav@56
  1214
     *
jaroslav@56
  1215
     * @return this {@code Class} object, cast to represent a subclass of
jaroslav@56
  1216
     *    the specified class object.
jaroslav@56
  1217
     * @throws ClassCastException if this {@code Class} object does not
jaroslav@56
  1218
     *    represent a subclass of the specified class (here "subclass" includes
jaroslav@56
  1219
     *    the class itself).
jaroslav@56
  1220
     * @since 1.5
jaroslav@56
  1221
     */
jaroslav@56
  1222
    public <U> Class<? extends U> asSubclass(Class<U> clazz) {
jaroslav@56
  1223
        if (clazz.isAssignableFrom(this))
jaroslav@56
  1224
            return (Class<? extends U>) this;
jaroslav@56
  1225
        else
jaroslav@56
  1226
            throw new ClassCastException(this.toString());
jaroslav@56
  1227
    }
jaroslav@56
  1228
jaroslav@443
  1229
    @JavaScriptBody(args = { "ac" }, 
jaroslav@235
  1230
        body = 
jaroslav@443
  1231
          "if (this.anno) {"
jaroslav@443
  1232
        + "  return this.anno['L' + ac.jvmName + ';'];"
jaroslav@266
  1233
        + "} else return null;"
jaroslav@235
  1234
    )
jaroslav@235
  1235
    private Object getAnnotationData(Class<?> annotationClass) {
jaroslav@235
  1236
        throw new UnsupportedOperationException();
jaroslav@235
  1237
    }
jaroslav@237
  1238
    /**
jaroslav@237
  1239
     * @throws NullPointerException {@inheritDoc}
jaroslav@237
  1240
     * @since 1.5
jaroslav@237
  1241
     */
jaroslav@56
  1242
    public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
jaroslav@235
  1243
        Object data = getAnnotationData(annotationClass);
jaroslav@235
  1244
        return data == null ? null : AnnotationImpl.create(annotationClass, data);
jaroslav@56
  1245
    }
jaroslav@56
  1246
jaroslav@56
  1247
    /**
jaroslav@56
  1248
     * @throws NullPointerException {@inheritDoc}
jaroslav@56
  1249
     * @since 1.5
jaroslav@56
  1250
     */
jaroslav@443
  1251
    @JavaScriptBody(args = { "ac" }, 
jaroslav@443
  1252
        body = "if (this.anno && this.anno['L' + ac.jvmName + ';']) { return true; }"
jaroslav@235
  1253
        + "else return false;"
jaroslav@235
  1254
    )
jaroslav@56
  1255
    public boolean isAnnotationPresent(
jaroslav@56
  1256
        Class<? extends Annotation> annotationClass) {
jaroslav@56
  1257
        if (annotationClass == null)
jaroslav@56
  1258
            throw new NullPointerException();
jaroslav@56
  1259
jaroslav@56
  1260
        return getAnnotation(annotationClass) != null;
jaroslav@56
  1261
    }
jaroslav@56
  1262
jaroslav@443
  1263
    @JavaScriptBody(args = {}, body = "return this.anno;")
jaroslav@238
  1264
    private Object getAnnotationData() {
jaroslav@238
  1265
        throw new UnsupportedOperationException();
jaroslav@238
  1266
    }
jaroslav@56
  1267
jaroslav@56
  1268
    /**
jaroslav@56
  1269
     * @since 1.5
jaroslav@56
  1270
     */
jaroslav@56
  1271
    public Annotation[] getAnnotations() {
jaroslav@238
  1272
        Object data = getAnnotationData();
jaroslav@238
  1273
        return data == null ? new Annotation[0] : AnnotationImpl.create(data);
jaroslav@56
  1274
    }
jaroslav@56
  1275
jaroslav@56
  1276
    /**
jaroslav@56
  1277
     * @since 1.5
jaroslav@56
  1278
     */
jaroslav@56
  1279
    public Annotation[] getDeclaredAnnotations()  {
jaroslav@65
  1280
        throw new UnsupportedOperationException();
jaroslav@56
  1281
    }
jaroslav@56
  1282
jaroslav@353
  1283
    @JavaScriptBody(args = "type", body = ""
jaroslav@353
  1284
        + "var c = vm.java_lang_Class(true);"
jaroslav@353
  1285
        + "c.jvmName = type;"
jaroslav@354
  1286
        + "c.primitive = true;"
jaroslav@353
  1287
        + "return c;"
jaroslav@353
  1288
    )
jaroslav@353
  1289
    native static Class getPrimitiveClass(String type);
jaroslav@88
  1290
jaroslav@517
  1291
    @JavaScriptBody(args = {}, body = 
jaroslav@517
  1292
        "return vm.desiredAssertionStatus ? vm.desiredAssertionStatus : false;"
jaroslav@517
  1293
    )
jaroslav@517
  1294
    public native boolean desiredAssertionStatus();
jaroslav@56
  1295
}