public Object getDefaultValue(Class<?> hint) {
   Object value;
   if (hint == null) {
     if (javaObject instanceof Boolean) {
       hint = ScriptRuntime.BooleanClass;
     }
   }
   if (hint == null || hint == ScriptRuntime.StringClass) {
     value = javaObject.toString();
   } else {
     String converterName;
     if (hint == ScriptRuntime.BooleanClass) {
       converterName = "booleanValue";
     } else if (hint == ScriptRuntime.NumberClass) {
       converterName = "doubleValue";
     } else {
       throw Context.reportRuntimeError0("msg.default.value");
     }
     Object converterObject = get(converterName, this);
     if (converterObject instanceof Function) {
       Function f = (Function) converterObject;
       value = f.call(Context.getContext(), f.getParentScope(), this, ScriptRuntime.emptyArgs);
     } else {
       if (hint == ScriptRuntime.NumberClass && javaObject instanceof Boolean) {
         boolean b = ((Boolean) javaObject).booleanValue();
         value = ScriptRuntime.wrapNumber(b ? 1.0 : 0.0);
       } else {
         value = javaObject.toString();
       }
     }
   }
   return value;
 }
Beispiel #2
0
  /*
   *   ECMA 3, 15.1.3 URI Handling Function Properties
   *
   *   The following are implementations of the algorithms
   *   given in the ECMA specification for the hidden functions
   *   'Encode' and 'Decode'.
   */
  private static String encode(String str, boolean fullUri) {
    byte[] utf8buf = null;
    StringBuffer sb = null;

    for (int k = 0, length = str.length(); k != length; ++k) {
      char C = str.charAt(k);
      if (encodeUnescaped(C, fullUri)) {
        if (sb != null) {
          sb.append(C);
        }
      } else {
        if (sb == null) {
          sb = new StringBuffer(length + 3);
          sb.append(str);
          sb.setLength(k);
          utf8buf = new byte[6];
        }
        if (0xDC00 <= C && C <= 0xDFFF) {
          throw Context.reportRuntimeError0("msg.bad.uri");
        }
        int V;
        if (C < 0xD800 || 0xDBFF < C) {
          V = C;
        } else {
          k++;
          if (k == length) {
            throw Context.reportRuntimeError0("msg.bad.uri");
          }
          char C2 = str.charAt(k);
          if (!(0xDC00 <= C2 && C2 <= 0xDFFF)) {
            throw Context.reportRuntimeError0("msg.bad.uri");
          }
          V = ((C - 0xD800) << 10) + (C2 - 0xDC00) + 0x10000;
        }
        int L = oneUcs4ToUtf8Char(utf8buf, V);
        for (int j = 0; j < L; j++) {
          int d = 0xff & utf8buf[j];
          sb.append('%');
          sb.append(toHexChar(d >>> 4));
          sb.append(toHexChar(d & 0xf));
        }
      }
    }
    return (sb == null) ? str : sb.toString();
  }
 public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
   ClassLoader loader = null;
   if (args.length != 0) {
     Object arg = args[0];
     if (arg instanceof Wrapper) {
       arg = ((Wrapper) arg).unwrap();
     }
     if (arg instanceof ClassLoader) {
       loader = (ClassLoader) arg;
     }
   }
   if (loader == null) {
     Context.reportRuntimeError0("msg.not.classloader");
     return null;
   }
   NativeJavaPackage pkg = new NativeJavaPackage(true, "", loader);
   ScriptRuntime.setObjectProtoAndParent(pkg, scope);
   return pkg;
 }
 private Scriptable js_getClass(Context cx, Scriptable scope, Object[] args) {
   if (args.length > 0 && args[0] instanceof Wrapper) {
     Scriptable result = this;
     Class<?> cl = ((Wrapper) args[0]).unwrap().getClass();
     // Evaluate the class name by getting successive properties of
     // the string to find the appropriate NativeJavaClass object
     String name = cl.getName();
     int offset = 0;
     for (; ; ) {
       int index = name.indexOf('.', offset);
       String propName = index == -1 ? name.substring(offset) : name.substring(offset, index);
       Object prop = result.get(propName, result);
       if (!(prop instanceof Scriptable)) break; // fall through to error
       result = (Scriptable) prop;
       if (index == -1) return result;
       offset = index + 1;
     }
   }
   throw Context.reportRuntimeError0("msg.not.java.obj");
 }
 @Override
 public void put(int index, Scriptable start, Object value) {
   throw Context.reportRuntimeError0("msg.pkg.int");
 }
Beispiel #6
0
 public Scriptable construct(Context cx, Scriptable scope, Object[] args) {
   throw Context.reportRuntimeError0("msg.script.is.not.constructor");
 }
Beispiel #7
0
  private static void generateMethod(
      ClassFileWriter cfw,
      String genName,
      String methodName,
      Class<?>[] parms,
      Class<?> returnType,
      boolean convertResult) {
    StringBuilder sb = new StringBuilder();
    int paramsEnd = appendMethodSignature(parms, returnType, sb);
    String methodSignature = sb.toString();
    cfw.startMethod(methodName, methodSignature, ClassFileWriter.ACC_PUBLIC);

    // Prepare stack to call method

    // push factory
    cfw.add(ByteCode.ALOAD_0);
    cfw.add(ByteCode.GETFIELD, genName, "factory", "Lorg/mozilla/javascript/ContextFactory;");

    // push self
    cfw.add(ByteCode.ALOAD_0);
    cfw.add(ByteCode.GETFIELD, genName, "self", "Lorg/mozilla/javascript/Scriptable;");

    // push function
    cfw.add(ByteCode.ALOAD_0);
    cfw.add(ByteCode.GETFIELD, genName, "delegee", "Lorg/mozilla/javascript/Scriptable;");
    cfw.addPush(methodName);
    cfw.addInvoke(
        ByteCode.INVOKESTATIC,
        "org/mozilla/javascript/JavaAdapter",
        "getFunction",
        "(Lorg/mozilla/javascript/Scriptable;"
            + "Ljava/lang/String;"
            + ")Lorg/mozilla/javascript/Function;");

    // push arguments
    generatePushWrappedArgs(cfw, parms, parms.length);

    // push bits to indicate which parameters should be wrapped
    if (parms.length > 64) {
      // If it will be an issue, then passing a static boolean array
      // can be an option, but for now using simple bitmask
      throw Context.reportRuntimeError0(
          "JavaAdapter can not subclass methods with more then" + " 64 arguments.");
    }
    long convertionMask = 0;
    for (int i = 0; i != parms.length; ++i) {
      if (!parms[i].isPrimitive()) {
        convertionMask |= (1 << i);
      }
    }
    cfw.addPush(convertionMask);

    // go through utility method, which creates a Context to run the
    // method in.
    cfw.addInvoke(
        ByteCode.INVOKESTATIC,
        "org/mozilla/javascript/JavaAdapter",
        "callMethod",
        "(Lorg/mozilla/javascript/ContextFactory;"
            + "Lorg/mozilla/javascript/Scriptable;"
            + "Lorg/mozilla/javascript/Function;"
            + "[Ljava/lang/Object;"
            + "J"
            + ")Ljava/lang/Object;");

    generateReturnResult(cfw, returnType, convertResult);

    cfw.stopMethod((short) paramsEnd);
  }
Beispiel #8
0
  private static String decode(String str, boolean fullUri) {
    char[] buf = null;
    int bufTop = 0;

    for (int k = 0, length = str.length(); k != length; ) {
      char C = str.charAt(k);
      if (C != '%') {
        if (buf != null) {
          buf[bufTop++] = C;
        }
        ++k;
      } else {
        if (buf == null) {
          // decode always compress so result can not be bigger then
          // str.length()
          buf = new char[length];
          str.getChars(0, k, buf, 0);
          bufTop = k;
        }
        int start = k;
        if (k + 3 > length) throw Context.reportRuntimeError0("msg.bad.uri");
        int B = unHex(str.charAt(k + 1), str.charAt(k + 2));
        if (B < 0) throw Context.reportRuntimeError0("msg.bad.uri");
        k += 3;
        if ((B & 0x80) == 0) {
          C = (char) B;
        } else {
          // Decode UTF-8 sequence into ucs4Char and encode it into
          // UTF-16
          int utf8Tail, ucs4Char, minUcs4Char;
          if ((B & 0xC0) == 0x80) {
            // First  UTF-8 should be ouside 0x80..0xBF
            throw Context.reportRuntimeError0("msg.bad.uri");
          } else if ((B & 0x20) == 0) {
            utf8Tail = 1;
            ucs4Char = B & 0x1F;
            minUcs4Char = 0x80;
          } else if ((B & 0x10) == 0) {
            utf8Tail = 2;
            ucs4Char = B & 0x0F;
            minUcs4Char = 0x800;
          } else if ((B & 0x08) == 0) {
            utf8Tail = 3;
            ucs4Char = B & 0x07;
            minUcs4Char = 0x10000;
          } else if ((B & 0x04) == 0) {
            utf8Tail = 4;
            ucs4Char = B & 0x03;
            minUcs4Char = 0x200000;
          } else if ((B & 0x02) == 0) {
            utf8Tail = 5;
            ucs4Char = B & 0x01;
            minUcs4Char = 0x4000000;
          } else {
            // First UTF-8 can not be 0xFF or 0xFE
            throw Context.reportRuntimeError0("msg.bad.uri");
          }
          if (k + 3 * utf8Tail > length) throw Context.reportRuntimeError0("msg.bad.uri");
          for (int j = 0; j != utf8Tail; j++) {
            if (str.charAt(k) != '%') throw Context.reportRuntimeError0("msg.bad.uri");
            B = unHex(str.charAt(k + 1), str.charAt(k + 2));
            if (B < 0 || (B & 0xC0) != 0x80) throw Context.reportRuntimeError0("msg.bad.uri");
            ucs4Char = (ucs4Char << 6) | (B & 0x3F);
            k += 3;
          }
          // Check for overlongs and other should-not-present codes
          if (ucs4Char < minUcs4Char || ucs4Char == 0xFFFE || ucs4Char == 0xFFFF) {
            ucs4Char = 0xFFFD;
          }
          if (ucs4Char >= 0x10000) {
            ucs4Char -= 0x10000;
            if (ucs4Char > 0xFFFFF) throw Context.reportRuntimeError0("msg.bad.uri");
            char H = (char) ((ucs4Char >>> 10) + 0xD800);
            C = (char) ((ucs4Char & 0x3FF) + 0xDC00);
            buf[bufTop++] = H;
          } else {
            C = (char) ucs4Char;
          }
        }
        if (fullUri && URI_DECODE_RESERVED.indexOf(C) >= 0) {
          for (int x = start; x != k; x++) {
            buf[bufTop++] = str.charAt(x);
          }
        } else {
          buf[bufTop++] = C;
        }
      }
    }
    return (buf == null) ? str : new String(buf, 0, bufTop);
  }
Beispiel #9
0
  /**
   * The global method escape, as per ECMA-262 15.1.2.4.
   *
   * <p>Includes code for the 'mask' argument supported by the C escape method, which used to be
   * part of the browser imbedding. Blame for the strange constant names should be directed there.
   */
  private Object js_escape(Object[] args) {
    final int URL_XALPHAS = 1, URL_XPALPHAS = 2, URL_PATH = 4;

    String s = ScriptRuntime.toString(args, 0);

    int mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
    if (args.length > 1) { // the 'mask' argument.  Non-ECMA.
      double d = ScriptRuntime.toNumber(args[1]);
      if (d != d
          || ((mask = (int) d) != d)
          || 0 != (mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH))) {
        throw Context.reportRuntimeError0("msg.bad.esc.mask");
      }
    }

    StringBuffer sb = null;
    for (int k = 0, L = s.length(); k != L; ++k) {
      int c = s.charAt(k);
      if (mask != 0
          && ((c >= '0' && c <= '9')
              || (c >= 'A' && c <= 'Z')
              || (c >= 'a' && c <= 'z')
              || c == '@'
              || c == '*'
              || c == '_'
              || c == '-'
              || c == '.'
              || (0 != (mask & URL_PATH) && (c == '/' || c == '+')))) {
        if (sb != null) {
          sb.append((char) c);
        }
      } else {
        if (sb == null) {
          sb = new StringBuffer(L + 3);
          sb.append(s);
          sb.setLength(k);
        }

        int hexSize;
        if (c < 256) {
          if (c == ' ' && mask == URL_XPALPHAS) {
            sb.append('+');
            continue;
          }
          sb.append('%');
          hexSize = 2;
        } else {
          sb.append('%');
          sb.append('u');
          hexSize = 4;
        }

        // append hexadecimal form of c left-padded with 0
        for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
          int digit = 0xf & (c >> shift);
          int hc = (digit < 10) ? '0' + digit : 'A' - 10 + digit;
          sb.append((char) hc);
        }
      }
    }

    return (sb == null) ? s : sb.toString();
  }