示例#1
0
文件: Main.java 项目: NCIP/calims
 public void quit(Context cx, int exitCode) {
   if (type == SYSTEM_EXIT) {
     System.exit(exitCode);
     return;
   }
   throw Kit.codeBug();
 }
示例#2
0
  private static MemberBox extractSetMethod(Class<?> type, MemberBox[] methods, boolean isStatic) {
    //
    // Note: it may be preferable to allow NativeJavaMethod.findFunction()
    //       to find the appropriate setter; unfortunately, it requires an
    //       instance of the target arg to determine that.
    //

    // Make two passes: one to find a method with direct type assignment,
    // and one to find a widening conversion.
    for (int pass = 1; pass <= 2; ++pass) {
      for (int i = 0; i < methods.length; ++i) {
        MemberBox method = methods[i];
        if (!isStatic || method.isStatic()) {
          Class<?>[] params = method.argTypes;
          if (params.length == 1) {
            if (pass == 1) {
              if (params[0] == type) {
                return method;
              }
            } else {
              if (pass != 2) Kit.codeBug();
              if (params[0].isAssignableFrom(type)) {
                return method;
              }
            }
          }
        }
      }
    }
    return null;
  }
示例#3
0
 /**
  * Generates code to push typed parameters onto the operand stack prior to a direct Java method
  * call.
  */
 private static int generatePushParam(ClassFileWriter cfw, int paramOffset, Class<?> paramType) {
   if (!paramType.isPrimitive()) {
     cfw.addALoad(paramOffset);
     return 1;
   }
   String typeName = paramType.getName();
   switch (typeName.charAt(0)) {
     case 'z':
     case 'b':
     case 'c':
     case 's':
     case 'i':
       // load an int value, convert to double.
       cfw.addILoad(paramOffset);
       return 1;
     case 'l':
       // load a long, convert to double.
       cfw.addLLoad(paramOffset);
       return 2;
     case 'f':
       // load a float, convert to double.
       cfw.addFLoad(paramOffset);
       return 1;
     case 'd':
       cfw.addDLoad(paramOffset);
       return 2;
   }
   throw Kit.codeBug();
 }
示例#4
0
 protected void onContextReleased(Context cx) {
   Object listeners = this.listeners;
   for (int i = 0; ; ++i) {
     Listener l = (Listener) Kit.getListener(listeners, i);
     if (l == null) break;
     l.contextReleased(cx);
   }
 }
示例#5
0
 @Override
 public Ref nameRef(Context cx, Object name, Scriptable scope, int memberTypeFlags) {
   if ((memberTypeFlags & Node.ATTRIBUTE_FLAG) == 0) {
     // should only be called for cases like @name or @[expr]
     throw Kit.codeBug();
   }
   XMLName xmlName = toAttributeName(cx, name);
   return xmlPrimaryReference(cx, xmlName, scope);
 }
示例#6
0
 public final void removeListener(Listener listener) {
   checkNotSealed();
   synchronized (listenersLock) {
     if (disabledListening) {
       throw new IllegalStateException();
     }
     listeners = Kit.removeListener(listeners, listener);
   }
 }
  synchronized Object getPkgProperty(String name, Scriptable start, boolean createPkg) {
    Object cached = super.get(name, start);
    if (cached != NOT_FOUND) return cached;
    if (negativeCache != null && negativeCache.contains(name)) {
      // Performance optimization: see bug 421071
      return null;
    }

    String className = (packageName.length() == 0) ? name : packageName + '.' + name;
    Context cx = Context.getContext();
    ClassShutter shutter = cx.getClassShutter();
    Scriptable newValue = null;
    if (shutter == null || shutter.visibleToScripts(className)) {
      Class<?> cl = null;
      if (classLoader != null) {
        cl = Kit.classOrNull(classLoader, className);
      } else {
        cl = Kit.classOrNull(className);
      }
      if (cl != null) {
        WrapFactory wrapFactory = cx.getWrapFactory();
        newValue = wrapFactory.wrapJavaClass(cx, getTopLevelScope(this), cl);
        newValue.setPrototype(getPrototype());
      }
    }
    if (newValue == null) {
      if (createPkg) {
        NativeJavaPackage pkg;
        pkg = new NativeJavaPackage(true, className, classLoader);
        ScriptRuntime.setObjectProtoAndParent(pkg, getParentScope());
        newValue = pkg;
      } else {
        // add to negative cache
        if (negativeCache == null) negativeCache = new HashSet<String>();
        negativeCache.add(name);
      }
    }
    if (newValue != null) {
      // Make it available for fast lookup and sharing of
      // lazily-reflected constructors and static members.
      super.put(name, start, newValue);
    }
    return newValue;
  }
示例#8
0
 static {
   // Are we running on a JDK 1.4 or later system?
   try {
     Class<?> ThrowableClass = Kit.classOrNull("java.lang.Throwable");
     Class<?>[] signature = {ThrowableClass};
     Throwable_initCause = ThrowableClass.getMethod("initCause", signature);
   } catch (Exception ex) {
     // Assume any exceptions means the method does not exist.
   }
 }
示例#9
0
  /**
   * Set explicit class loader to use when searching for Java classes.
   *
   * @see #getApplicationClassLoader()
   */
  public final void initApplicationClassLoader(ClassLoader loader) {
    if (loader == null) throw new IllegalArgumentException("loader is null");
    if (!Kit.testIfCanLoadRhinoClasses(loader))
      throw new IllegalArgumentException("Loader can not resolve Rhino classes");

    if (this.applicationClassLoader != null)
      throw new IllegalStateException("applicationClassLoader can only be set once");
    checkNotSealed();

    this.applicationClassLoader = loader;
  }
示例#10
0
  public Object action(
      Context cx, Scriptable scope, Scriptable thisObj, Object[] args, int actionType) {
    GlobData data = new GlobData();
    data.mode = actionType;

    switch (actionType) {
      case RA_MATCH:
        {
          Object rval;
          data.optarg = 1;
          rval = matchOrReplace(cx, scope, thisObj, args, this, data, false);
          return data.arrayobj == null ? rval : data.arrayobj;
        }

      case RA_SEARCH:
        data.optarg = 1;
        return matchOrReplace(cx, scope, thisObj, args, this, data, false);

      case RA_REPLACE:
        {
          Object arg1 = args.length < 2 ? Undefined.instance : args[1];
          String repstr = null;
          Function lambda = null;
          if (arg1 instanceof Function) {
            lambda = (Function) arg1;
          } else {
            repstr = ScriptRuntime.toString(arg1);
          }

          data.optarg = 2;
          data.lambda = lambda;
          data.repstr = repstr;
          data.dollar = repstr == null ? -1 : repstr.indexOf('$');
          data.charBuf = null;
          data.leftIndex = 0;
          Object val = matchOrReplace(cx, scope, thisObj, args, this, data, true);
          SubString rc = this.rightContext;

          if (data.charBuf == null) {
            if (data.global || val == null || !val.equals(Boolean.TRUE)) {
              /* Didn't match even once. */
              return data.str;
            }
            SubString lc = this.leftContext;
            replace_glob(data, cx, scope, this, lc.index, lc.length);
          }
          data.charBuf.append(rc.charArray, rc.index, rc.length);
          return data.charBuf.toString();
        }

      default:
        throw Kit.codeBug();
    }
  }
  static {
    // Reflection in java is verbose
    Class<?>[] sig2 = new Class[2];
    Class<?> cl = Kit.classOrNull("org.mozilla.javascript.JavaAdapter");
    if (cl != null) {
      try {
        sig2[0] = ScriptRuntime.ObjectClass;
        sig2[1] = Kit.classOrNull("java.io.ObjectOutputStream");
        adapter_writeAdapterObject = cl.getMethod("writeAdapterObject", sig2);

        sig2[0] = ScriptRuntime.ScriptableClass;
        sig2[1] = Kit.classOrNull("java.io.ObjectInputStream");
        adapter_readAdapterObject = cl.getMethod("readAdapterObject", sig2);

      } catch (Exception ex) {
        adapter_writeAdapterObject = null;
        adapter_readAdapterObject = null;
      }
    }
  }
示例#12
0
 /** Check that testClass is accessible from the given loader. */
 static boolean testIfCanLoadRhinoClasses(ClassLoader loader) {
   Class<?> testClass = ScriptRuntime.ContextFactoryClass;
   Class<?> x = Kit.classOrNull(loader, testClass.getName());
   if (x != testClass) {
     // The check covers the case when x == null =>
     // loader does not know about testClass or the case
     // when x != null && x != testClass =>
     // loader loads a class unrelated to testClass
     return false;
   }
   return true;
 }
示例#13
0
 private boolean isDom3Present() {
   Class<?> nodeClass = Kit.classOrNull("org.w3c.dom.Node");
   if (nodeClass == null) return false;
   // Check to see whether DOM3 is present; use a new method defined in
   // DOM3 that is vital to our implementation
   try {
     nodeClass.getMethod("getUserData", new Class<?>[] {String.class});
     return true;
   } catch (NoSuchMethodException e) {
     return false;
   }
 }
示例#14
0
文件: Main.java 项目: NCIP/calims
 public Object run(Context cx) {
   if (type == PROCESS_FILES) {
     try {
       processFiles(cx, args);
     } catch (IOException ioe) {
       Context.reportError(ioe.toString());
     }
   } else {
     throw Kit.codeBug();
   }
   return null;
 }
示例#15
0
  /**
   * Provides a default {@link org.mozilla.javascript.xml.XMLLib.Factory XMLLib.Factory} to be used
   * by the <code>Context</code> instances produced by this factory. See {@link
   * Context#getE4xImplementationFactory} for details.
   *
   * <p>May return null, in which case E4X functionality is not supported in Rhino.
   *
   * <p>The default implementation now prefers the DOM3 E4X implementation.
   */
  protected org.mozilla.javascript.xml.XMLLib.Factory getE4xImplementationFactory() {
    // Must provide default implementation, rather than abstract method,
    // so that past implementors of ContextFactory do not fail at runtime
    // upon invocation of this method.
    // Note that the default implementation returns null if we
    // neither have XMLBeans nor a DOM3 implementation present.

    if (isDom3Present()) {
      return org.mozilla.javascript.xml.XMLLib.Factory.create(
          "org.mozilla.javascript.xmlimpl.XMLLibImpl");
    } else if (Kit.classOrNull("org.apache.xmlbeans.XmlCursor") != null) {
      return org.mozilla.javascript.xml.XMLLib.Factory.create(
          "org.mozilla.javascript.xml.impl.xmlbeans.XMLLibImpl");
    } else {
      return null;
    }
  }
示例#16
0
文件: Main.java 项目: NCIP/calims
  static void processFiles(Context cx, String[] files) throws IOException {
    StringBuffer cout = new StringBuffer();
    if (files.length > 0) {
      for (int i = 0; i < files.length; i++) {
        try {
          String source = (String) readFileOrUrl(files[i], true);
          cout.append(Compressor.compressScript(source, 0, 1, escapeUnicode, stripConsole));
        } catch (IOException ex) {
          // continue processing files
        }
      }
    } else {
      byte[] data = Kit.readStream(global.getIn(), 4096);
      // Convert to String using the default encoding
      String source = new String(data);
      if (source != null) {
        cout.append(Compressor.compressScript(source, 0, 1, escapeUnicode, stripConsole));
      }
    }

    global.getOut().println(cout);
  }
示例#17
0
文件: Main.java 项目: NCIP/calims
  private static Object readFileOrUrl(String path, boolean convertToString) throws IOException {
    URL url = null;
    // Assume path is URL if it contains a colon and there are at least
    // 2 characters in the protocol part. The later allows under Windows
    // to interpret paths with driver letter as file, not URL.
    if (path.indexOf(':') >= 2) {
      try {
        url = new URL(path);
      } catch (MalformedURLException ex) {
      }
    }

    InputStream is = null;
    int capacityHint = 0;
    if (url == null) {
      File file = new File(path);
      capacityHint = (int) file.length();
      try {
        is = new FileInputStream(file);
      } catch (IOException ex) {
        Context.reportError(getMessage("msg.couldnt.open", path));
        throw ex;
      }
    } else {
      try {
        URLConnection uc = url.openConnection();
        is = uc.getInputStream();
        capacityHint = uc.getContentLength();
        // Ignore insane values for Content-Length
        if (capacityHint > (1 << 20)) {
          capacityHint = -1;
        }
      } catch (IOException ex) {
        Context.reportError(getMessage("msg.couldnt.open.url", url.toString(), ex.toString()));
        throw ex;
      }
    }
    if (capacityHint <= 0) {
      capacityHint = 4096;
    }

    byte[] data;
    try {
      try {
        is = new BufferedInputStream(is);
        data = Kit.readStream(is, capacityHint);
      } finally {
        is.close();
      }
    } catch (IOException ex) {
      Context.reportError(ex.toString());
      throw ex;
    }

    Object result;
    if (convertToString) {
      // Convert to String using the default encoding
      // TODO: Use 'charset=' argument of Content-Type if URL?
      result = new String(data);
    } else {
      result = data;
    }
    return result;
  }
示例#18
0
  /** Analog of C match_or_replace. */
  private static Object matchOrReplace(
      Context cx,
      Scriptable scope,
      Scriptable thisObj,
      Object[] args,
      RegExpImpl reImpl,
      GlobData data,
      boolean forceFlat) {
    NativeRegExp re;

    String str = ScriptRuntime.toString(thisObj);
    data.str = str;
    Scriptable topScope = ScriptableObject.getTopLevelScope(scope);

    if (args.length == 0) {
      Object compiled = NativeRegExp.compileRE(cx, "", "", false);
      re = new NativeRegExp(topScope, compiled);
    } else if (args[0] instanceof NativeRegExp) {
      re = (NativeRegExp) args[0];
    } else {
      String src = ScriptRuntime.toString(args[0]);
      String opt;
      if (data.optarg < args.length) {
        args[0] = src;
        opt = ScriptRuntime.toString(args[data.optarg]);
      } else {
        opt = null;
      }
      Object compiled = NativeRegExp.compileRE(cx, src, opt, forceFlat);
      re = new NativeRegExp(topScope, compiled);
    }
    data.regexp = re;

    data.global = (re.getFlags() & NativeRegExp.JSREG_GLOB) != 0;
    int[] indexp = {0};
    Object result = null;
    if (data.mode == RA_SEARCH) {
      result = re.executeRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
      if (result != null && result.equals(Boolean.TRUE))
        result = new Integer(reImpl.leftContext.length);
      else result = new Integer(-1);
    } else if (data.global) {
      re.lastIndex = 0;
      for (int count = 0; indexp[0] <= str.length(); count++) {
        result = re.executeRegExp(cx, scope, reImpl, str, indexp, NativeRegExp.TEST);
        if (result == null || !result.equals(Boolean.TRUE)) break;
        if (data.mode == RA_MATCH) {
          match_glob(data, cx, scope, count, reImpl);
        } else {
          if (data.mode != RA_REPLACE) Kit.codeBug();
          SubString lastMatch = reImpl.lastMatch;
          int leftIndex = data.leftIndex;
          int leftlen = lastMatch.index - leftIndex;
          data.leftIndex = lastMatch.index + lastMatch.length;
          replace_glob(data, cx, scope, reImpl, leftIndex, leftlen);
        }
        if (reImpl.lastMatch.length == 0) {
          if (indexp[0] == str.length()) break;
          indexp[0]++;
        }
      }
    } else {
      result =
          re.executeRegExp(
              cx,
              scope,
              reImpl,
              str,
              indexp,
              ((data.mode == RA_REPLACE) ? NativeRegExp.TEST : NativeRegExp.MATCH));
    }

    return result;
  }
示例#19
0
 /** @see Kit#codeBug */
 public static RuntimeException codeBug() throws RuntimeException {
   throw Kit.codeBug();
 }
示例#20
0
  /*
   * Analog of replace_glob() in jsstr.c
   */
  private static void replace_glob(
      GlobData rdata, Context cx, Scriptable scope, RegExpImpl reImpl, int leftIndex, int leftlen) {
    int replen;
    String lambdaStr;
    if (rdata.lambda != null) {
      // invoke lambda function with args lastMatch, $1, $2, ... $n,
      // leftContext.length, whole string.
      SubString[] parens = reImpl.parens;
      int parenCount = (parens == null) ? 0 : parens.length;
      Object[] args = new Object[parenCount + 3];
      args[0] = reImpl.lastMatch.toString();
      for (int i = 0; i < parenCount; i++) {
        SubString sub = parens[i];
        if (sub != null) {
          args[i + 1] = sub.toString();
        } else {
          args[i + 1] = Undefined.instance;
        }
      }
      args[parenCount + 1] = new Integer(reImpl.leftContext.length);
      args[parenCount + 2] = rdata.str;
      // This is a hack to prevent expose of reImpl data to
      // JS function which can run new regexps modifing
      // regexp that are used later by the engine.
      // TODO: redesign is necessary
      if (reImpl != ScriptRuntime.getRegExpProxy(cx)) Kit.codeBug();
      RegExpImpl re2 = new RegExpImpl();
      re2.multiline = reImpl.multiline;
      re2.input = reImpl.input;
      ScriptRuntime.setRegExpProxy(cx, re2);
      try {
        Scriptable parent = ScriptableObject.getTopLevelScope(scope);
        Object result = rdata.lambda.call(cx, parent, parent, args);
        lambdaStr = ScriptRuntime.toString(result);
      } finally {
        ScriptRuntime.setRegExpProxy(cx, reImpl);
      }
      replen = lambdaStr.length();
    } else {
      lambdaStr = null;
      replen = rdata.repstr.length();
      if (rdata.dollar >= 0) {
        int[] skip = new int[1];
        int dp = rdata.dollar;
        do {
          SubString sub = interpretDollar(cx, reImpl, rdata.repstr, dp, skip);
          if (sub != null) {
            replen += sub.length - skip[0];
            dp += skip[0];
          } else {
            ++dp;
          }
          dp = rdata.repstr.indexOf('$', dp);
        } while (dp >= 0);
      }
    }

    int growth = leftlen + replen + reImpl.rightContext.length;
    StringBuffer charBuf = rdata.charBuf;
    if (charBuf == null) {
      charBuf = new StringBuffer(growth);
      rdata.charBuf = charBuf;
    } else {
      charBuf.ensureCapacity(rdata.charBuf.length() + growth);
    }

    charBuf.append(reImpl.leftContext.charArray, leftIndex, leftlen);
    if (rdata.lambda != null) {
      charBuf.append(lambdaStr);
    } else {
      do_replace(rdata, cx, reImpl);
    }
  }
示例#21
0
  private static SubString interpretDollar(
      Context cx, RegExpImpl res, String da, int dp, int[] skip) {
    char dc;
    int num, tmp;

    if (da.charAt(dp) != '$') Kit.codeBug();

    /* Allow a real backslash (literal "\\") to escape "$1" etc. */
    int version = cx.getLanguageVersion();
    if (version != Context.VERSION_DEFAULT && version <= Context.VERSION_1_4) {
      if (dp > 0 && da.charAt(dp - 1) == '\\') return null;
    }
    int daL = da.length();
    if (dp + 1 >= daL) return null;
    /* Interpret all Perl match-induced dollar variables. */
    dc = da.charAt(dp + 1);
    if (NativeRegExp.isDigit(dc)) {
      int cp;
      if (version != Context.VERSION_DEFAULT && version <= Context.VERSION_1_4) {
        if (dc == '0') return null;
        /* Check for overflow to avoid gobbling arbitrary decimal digits. */
        num = 0;
        cp = dp;
        while (++cp < daL && NativeRegExp.isDigit(dc = da.charAt(cp))) {
          tmp = 10 * num + (dc - '0');
          if (tmp < num) break;
          num = tmp;
        }
      } else {
          /* ECMA 3, 1-9 or 01-99 */
        int parenCount = (res.parens == null) ? 0 : res.parens.length;
        num = dc - '0';
        if (num > parenCount) return null;
        cp = dp + 2;
        if ((dp + 2) < daL) {
          dc = da.charAt(dp + 2);
          if (NativeRegExp.isDigit(dc)) {
            tmp = 10 * num + (dc - '0');
            if (tmp <= parenCount) {
              cp++;
              num = tmp;
            }
          }
        }
        if (num == 0) return null; /* $0 or $00 is not valid */
      }
      /* Adjust num from 1 $n-origin to 0 array-index-origin. */
      num--;
      skip[0] = cp - dp;
      return res.getParenSubString(num);
    }

    skip[0] = 2;
    switch (dc) {
      case '$':
        return new SubString("$");
      case '&':
        return res.lastMatch;
      case '+':
        return res.lastParen;
      case '`':
        if (version == Context.VERSION_1_2) {
          /*
           * JS1.2 imitated the Perl4 bug where left context at each step
           * in an iterative use of a global regexp started from last match,
           * not from the start of the target string.  But Perl4 does start
           * $` at the beginning of the target string when it is used in a
           * substitution, so we emulate that special case here.
           */
          res.leftContext.index = 0;
          res.leftContext.length = res.lastMatch.index;
        }
        return res.leftContext;
      case '\'':
        return res.rightContext;
    }
    return null;
  }
示例#22
0
  private void reflect(Scriptable scope, boolean includeProtected) {
    // We reflect methods first, because we want overloaded field/method
    // names to be allocated to the NativeJavaMethod before the field
    // gets in the way.

    Method[] methods = discoverAccessibleMethods(cl, includeProtected, includePrivate);
    for (int i = 0; i < methods.length; i++) {
      Method method = methods[i];
      int mods = method.getModifiers();
      boolean isStatic = Modifier.isStatic(mods);
      Map<String, Object> ht = isStatic ? staticMembers : members;
      String name = method.getName();
      Object value = ht.get(name);
      if (value == null) {
        ht.put(name, method);
      } else {
        ObjArray overloadedMethods;
        if (value instanceof ObjArray) {
          overloadedMethods = (ObjArray) value;
        } else {
          if (!(value instanceof Method)) Kit.codeBug();
          // value should be instance of Method as at this stage
          // staticMembers and members can only contain methods
          overloadedMethods = new ObjArray();
          overloadedMethods.add(value);
          ht.put(name, overloadedMethods);
        }
        overloadedMethods.add(method);
      }
    }

    // replace Method instances by wrapped NativeJavaMethod objects
    // first in staticMembers and then in members
    for (int tableCursor = 0; tableCursor != 2; ++tableCursor) {
      boolean isStatic = (tableCursor == 0);
      Map<String, Object> ht = isStatic ? staticMembers : members;
      for (String name : ht.keySet()) {
        MemberBox[] methodBoxes;
        Object value = ht.get(name);
        if (value instanceof Method) {
          methodBoxes = new MemberBox[1];
          methodBoxes[0] = new MemberBox((Method) value);
        } else {
          ObjArray overloadedMethods = (ObjArray) value;
          int N = overloadedMethods.size();
          if (N < 2) Kit.codeBug();
          methodBoxes = new MemberBox[N];
          for (int i = 0; i != N; ++i) {
            Method method = (Method) overloadedMethods.get(i);
            methodBoxes[i] = new MemberBox(method);
          }
        }
        NativeJavaMethod fun = new NativeJavaMethod(methodBoxes);
        if (scope != null) {
          ScriptRuntime.setFunctionProtoAndParent(fun, scope);
        }
        ht.put(name, fun);
      }
    }

    // Reflect fields.
    Field[] fields = getAccessibleFields();
    for (int i = 0; i < fields.length; i++) {
      Field field = fields[i];
      String name = field.getName();
      int mods = field.getModifiers();
      if (!includePrivate && !Modifier.isPublic(mods)) {
        continue;
      }
      try {
        boolean isStatic = Modifier.isStatic(mods);
        Map<String, Object> ht = isStatic ? staticMembers : members;
        Object member = ht.get(name);
        if (member == null) {
          ht.put(name, field);
        } else if (member instanceof NativeJavaMethod) {
          NativeJavaMethod method = (NativeJavaMethod) member;
          FieldAndMethods fam = new FieldAndMethods(scope, method.methods, field);
          Map<String, FieldAndMethods> fmht = isStatic ? staticFieldAndMethods : fieldAndMethods;
          if (fmht == null) {
            fmht = new HashMap<String, FieldAndMethods>();
            if (isStatic) {
              staticFieldAndMethods = fmht;
            } else {
              fieldAndMethods = fmht;
            }
          }
          fmht.put(name, fam);
          ht.put(name, fam);
        } else if (member instanceof Field) {
          Field oldField = (Field) member;
          // If this newly reflected field shadows an inherited field,
          // then replace it. Otherwise, since access to the field
          // would be ambiguous from Java, no field should be
          // reflected.
          // For now, the first field found wins, unless another field
          // explicitly shadows it.
          if (oldField.getDeclaringClass().isAssignableFrom(field.getDeclaringClass())) {
            ht.put(name, field);
          }
        } else {
          // "unknown member type"
          Kit.codeBug();
        }
      } catch (SecurityException e) {
        // skip this field
        Context.reportWarning(
            "Could not access field "
                + name
                + " of class "
                + cl.getName()
                + " due to lack of privileges.");
      }
    }

    // Create bean properties from corresponding get/set methods first for
    // static members and then for instance members
    for (int tableCursor = 0; tableCursor != 2; ++tableCursor) {
      boolean isStatic = (tableCursor == 0);
      Map<String, Object> ht = isStatic ? staticMembers : members;

      Map<String, BeanProperty> toAdd = new HashMap<String, BeanProperty>();

      // Now, For each member, make "bean" properties.
      for (String name : ht.keySet()) {
        // Is this a getter?
        boolean memberIsGetMethod = name.startsWith("get");
        boolean memberIsSetMethod = name.startsWith("set");
        boolean memberIsIsMethod = name.startsWith("is");
        if (memberIsGetMethod || memberIsIsMethod || memberIsSetMethod) {
          // Double check name component.
          String nameComponent = name.substring(memberIsIsMethod ? 2 : 3);
          if (nameComponent.length() == 0) continue;

          // Make the bean property name.
          String beanPropertyName = nameComponent;
          char ch0 = nameComponent.charAt(0);
          if (Character.isUpperCase(ch0)) {
            if (nameComponent.length() == 1) {
              beanPropertyName = nameComponent.toLowerCase();
            } else {
              char ch1 = nameComponent.charAt(1);
              if (!Character.isUpperCase(ch1)) {
                beanPropertyName = Character.toLowerCase(ch0) + nameComponent.substring(1);
              }
            }
          }

          // If we already have a member by this name, don't do this
          // property.
          if (toAdd.containsKey(beanPropertyName)) continue;
          Object v = ht.get(beanPropertyName);
          if (v != null) {
            // A private field shouldn't mask a public getter/setter
            if (!includePrivate
                || !(v instanceof Member)
                || !Modifier.isPrivate(((Member) v).getModifiers())) {

              continue;
            }
          }

          // Find the getter method, or if there is none, the is-
          // method.
          MemberBox getter = null;
          getter = findGetter(isStatic, ht, "get", nameComponent);
          // If there was no valid getter, check for an is- method.
          if (getter == null) {
            getter = findGetter(isStatic, ht, "is", nameComponent);
          }

          // setter
          MemberBox setter = null;
          NativeJavaMethod setters = null;
          String setterName = "set".concat(nameComponent);

          if (ht.containsKey(setterName)) {
            // Is this value a method?
            Object member = ht.get(setterName);
            if (member instanceof NativeJavaMethod) {
              NativeJavaMethod njmSet = (NativeJavaMethod) member;
              if (getter != null) {
                // We have a getter. Now, do we have a matching
                // setter?
                Class<?> type = getter.method().getReturnType();
                setter = extractSetMethod(type, njmSet.methods, isStatic);
              } else {
                // No getter, find any set method
                setter = extractSetMethod(njmSet.methods, isStatic);
              }
              if (njmSet.methods.length > 1) {
                setters = njmSet;
              }
            }
          }
          // Make the property.
          BeanProperty bp = new BeanProperty(getter, setter, setters);
          toAdd.put(beanPropertyName, bp);
        }
      }

      // Add the new bean properties.
      for (String key : toAdd.keySet()) {
        Object value = toAdd.get(key);
        ht.put(key, value);
      }
    }

    // Reflect constructors
    Constructor<?>[] constructors = getAccessibleConstructors();
    ctors = new MemberBox[constructors.length];
    for (int i = 0; i != constructors.length; ++i) {
      ctors[i] = new MemberBox(constructors[i]);
    }
  }
  /** Type-munging for field setting and method invocation. Conforms to LC3 specification */
  static Object coerceTypeImpl(Class<?> type, Object value) {
    if (value != null && value.getClass() == type) {
      return value;
    }

    switch (getJSTypeCode(value)) {
      case JSTYPE_NULL:
        // raise error if type.isPrimitive()
        if (type.isPrimitive()) {
          reportConversionError(value, type);
        }
        return null;

      case JSTYPE_UNDEFINED:
        if (type == ScriptRuntime.StringClass || type == ScriptRuntime.ObjectClass) {
          return "undefined";
        } else {
          reportConversionError("undefined", type);
        }
        break;

      case JSTYPE_BOOLEAN:
        // Under LC3, only JS Booleans can be coerced into a Boolean value
        if (type == Boolean.TYPE
            || type == ScriptRuntime.BooleanClass
            || type == ScriptRuntime.ObjectClass) {
          return value;
        } else if (type == ScriptRuntime.StringClass) {
          return value.toString();
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_NUMBER:
        if (type == ScriptRuntime.StringClass) {
          return ScriptRuntime.toString(value);
        } else if (type == ScriptRuntime.ObjectClass) {
          return coerceToNumber(Double.TYPE, value);
        } else if ((type.isPrimitive() && type != Boolean.TYPE)
            || ScriptRuntime.NumberClass.isAssignableFrom(type)) {
          return coerceToNumber(type, value);
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_STRING:
        if (type == ScriptRuntime.StringClass || type.isInstance(value)) {
          return value;
        } else if (type == Character.TYPE || type == ScriptRuntime.CharacterClass) {
          // Special case for converting a single char string to a
          // character
          // Placed here because it applies *only* to JS strings,
          // not other JS objects converted to strings
          if (((String) value).length() == 1) {
            return new Character(((String) value).charAt(0));
          } else {
            return coerceToNumber(type, value);
          }
        } else if ((type.isPrimitive() && type != Boolean.TYPE)
            || ScriptRuntime.NumberClass.isAssignableFrom(type)) {
          return coerceToNumber(type, value);
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_JAVA_CLASS:
        if (value instanceof Wrapper) {
          value = ((Wrapper) value).unwrap();
        }

        if (type == ScriptRuntime.ClassClass || type == ScriptRuntime.ObjectClass) {
          return value;
        } else if (type == ScriptRuntime.StringClass) {
          return value.toString();
        } else {
          reportConversionError(value, type);
        }
        break;

      case JSTYPE_JAVA_OBJECT:
      case JSTYPE_JAVA_ARRAY:
        if (value instanceof Wrapper) {
          value = ((Wrapper) value).unwrap();
        }
        if (type.isPrimitive()) {
          if (type == Boolean.TYPE) {
            reportConversionError(value, type);
          }
          return coerceToNumber(type, value);
        } else {
          if (type == ScriptRuntime.StringClass) {
            return value.toString();
          } else {
            if (type.isInstance(value)) {
              return value;
            } else {
              reportConversionError(value, type);
            }
          }
        }
        break;

      case JSTYPE_OBJECT:
        if (type == ScriptRuntime.StringClass) {
          return ScriptRuntime.toString(value);
        } else if (type.isPrimitive()) {
          if (type == Boolean.TYPE) {
            reportConversionError(value, type);
          }
          return coerceToNumber(type, value);
        } else if (type.isInstance(value)) {
          return value;
        } else if (type == ScriptRuntime.DateClass && value instanceof NativeDate) {
          double time = ((NativeDate) value).getJSTimeValue();
          // XXX: This will replace NaN by 0
          return new Date((long) time);
        } else if (type.isArray() && value instanceof NativeArray) {
          // Make a new java array, and coerce the JS array components
          // to the target (component) type.
          NativeArray array = (NativeArray) value;
          long length = array.getLength();
          Class<?> arrayType = type.getComponentType();
          Object Result = Array.newInstance(arrayType, (int) length);
          for (int i = 0; i < length; ++i) {
            try {
              Array.set(Result, i, coerceType(arrayType, array.get(i, array)));
            } catch (EvaluatorException ee) {
              reportConversionError(value, type);
            }
          }

          return Result;
        } else if (value instanceof Wrapper) {
          value = ((Wrapper) value).unwrap();
          if (type.isInstance(value)) return value;
          reportConversionError(value, type);
        } else if (type.isInterface() && value instanceof Callable) {
          // Try to use function as implementation of Java interface.
          //
          // XXX: Currently only instances of ScriptableObject are
          // supported since the resulting interface proxies should
          // be reused next time conversion is made and generic
          // Callable has no storage for it. Weak references can
          // address it but for now use this restriction.
          if (value instanceof ScriptableObject) {
            ScriptableObject so = (ScriptableObject) value;
            Object key = Kit.makeHashKeyFromPair(COERCED_INTERFACE_KEY, type);
            Object old = so.getAssociatedValue(key);
            if (old != null) {
              // Function was already wrapped
              return old;
            }
            Context cx = Context.getContext();
            Object glue = InterfaceAdapter.create(cx, type, (Callable) value);
            // Store for later retrival
            glue = so.associateValue(key, glue);
            return glue;
          }
          reportConversionError(value, type);
        } else {
          reportConversionError(value, type);
        }
        break;
    }

    return value;
  }