Exemple #1
0
 public void quit(Context cx, int exitCode) {
   if (type == SYSTEM_EXIT) {
     System.exit(exitCode);
     return;
   }
   throw Kit.codeBug();
 }
Exemple #2
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();
 }
Exemple #3
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;
  }
 @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);
 }
Exemple #5
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();
    }
  }
Exemple #6
0
 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;
 }
Exemple #7
0
 /** @see Kit#codeBug */
 public static RuntimeException codeBug() throws RuntimeException {
   throw Kit.codeBug();
 }
Exemple #8
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]);
    }
  }
Exemple #9
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;
  }
Exemple #10
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);
    }
  }
Exemple #11
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;
  }