/**
   * Adapts the source object to a view object.
   *
   * @param mapper An action that is invoked for each source object in the graph that is to be
   *     adapted. The action can influence how the source object is adapted via the provided {@link
   *     SourceObjectMapping}.
   */
  public <T, S> T adapt(
      Class<T> targetType, S sourceObject, Action<? super SourceObjectMapping> mapper) {
    if (sourceObject == null) {
      return null;
    }
    Class<? extends T> wrapperType = targetTypeProvider.getTargetType(targetType, sourceObject);
    DefaultSourceObjectMapping mapping =
        new DefaultSourceObjectMapping(sourceObject, targetType, wrapperType);
    mapper.execute(mapping);
    wrapperType = mapping.wrapperType.asSubclass(targetType);
    if (wrapperType.isInstance(sourceObject)) {
      return wrapperType.cast(sourceObject);
    }
    if (targetType.isEnum()) {
      return adaptToEnum(targetType, sourceObject);
    }

    MixInMethodInvoker mixInMethodInvoker = null;
    if (mapping.mixInType != null) {
      mixInMethodInvoker =
          new MixInMethodInvoker(
              mapping.mixInType, new AdaptingMethodInvoker(mapper, new ReflectionMethodInvoker()));
    }
    MethodInvoker overrideInvoker = chainInvokers(mixInMethodInvoker, mapping.overrideInvoker);
    Object proxy =
        Proxy.newProxyInstance(
            wrapperType.getClassLoader(),
            new Class<?>[] {wrapperType},
            new InvocationHandlerImpl(sourceObject, overrideInvoker, mapper));
    if (mixInMethodInvoker != null) {
      mixInMethodInvoker.setProxy(proxy);
    }
    return wrapperType.cast(proxy);
  }
示例#2
0
 public <T extends Anim> void clearanims(Class<T> type) {
   for (Iterator<Anim> i = nanims.iterator(); i.hasNext(); ) {
     Anim a = i.next();
     if (type.isInstance(a)) i.remove();
   }
   for (Iterator<Anim> i = anims.iterator(); i.hasNext(); ) {
     Anim a = i.next();
     if (type.isInstance(a)) i.remove();
   }
 }
示例#3
0
 private static void netxsurgery() throws Exception {
   /* Force off NetX codebase classloading. */
   Class<?> nxc;
   try {
     nxc = Class.forName("net.sourceforge.jnlp.runtime.JNLPClassLoader");
   } catch (ClassNotFoundException e1) {
     try {
       nxc = Class.forName("netx.jnlp.runtime.JNLPClassLoader");
     } catch (ClassNotFoundException e2) {
       throw (new Exception("No known NetX on classpath"));
     }
   }
   ClassLoader cl = MainFrame.class.getClassLoader();
   if (!nxc.isInstance(cl)) {
     throw (new Exception("Not running from a NetX classloader"));
   }
   Field cblf, lf;
   try {
     cblf = nxc.getDeclaredField("codeBaseLoader");
     lf = nxc.getDeclaredField("loaders");
   } catch (NoSuchFieldException e) {
     throw (new Exception("JNLPClassLoader does not conform to its known structure"));
   }
   cblf.setAccessible(true);
   lf.setAccessible(true);
   Set<Object> loaders = new HashSet<Object>();
   Stack<Object> open = new Stack<Object>();
   open.push(cl);
   while (!open.empty()) {
     Object cur = open.pop();
     if (loaders.contains(cur)) continue;
     loaders.add(cur);
     Object curl;
     try {
       curl = lf.get(cur);
     } catch (IllegalAccessException e) {
       throw (new Exception("Reflection accessibility not available even though set"));
     }
     for (int i = 0; i < Array.getLength(curl); i++) {
       Object other = Array.get(curl, i);
       if (nxc.isInstance(other)) open.push(other);
     }
   }
   for (Object cur : loaders) {
     try {
       cblf.set(cur, null);
     } catch (IllegalAccessException e) {
       throw (new Exception("Reflection accessibility not available even though set"));
     }
   }
 }
示例#4
0
  /**
   * Set the object to be edited.
   *
   * @param value The object to be edited.
   */
  public void setObject(Object value) {
    if (!(_type.isInstance(value))) {
      throw new IllegalArgumentException(value.getClass() + " is not of type " + _type);
    }
    _value = value;

    // Disable event generation.
    _squelchChangeEvents = true;

    // Iterate over each property, doing a lookup on the associated editor
    // and setting the editor's value to the value of the property.
    Iterator it = _prop2Editor.keySet().iterator();
    while (it.hasNext()) {
      PropertyDescriptor desc = (PropertyDescriptor) it.next();
      PropertyEditor editor = (PropertyEditor) _prop2Editor.get(desc);
      Method reader = desc.getReadMethod();
      if (reader != null) {
        try {
          Object val = reader.invoke(_value, null);
          editor.setValue(val);
        } catch (IllegalAccessException ex) {
          ex.printStackTrace();
        } catch (InvocationTargetException ex) {
          ex.getTargetException().printStackTrace();
        }
      }
    }

    // Enable event generation.
    _squelchChangeEvents = false;
  }
示例#5
0
 private static int checkSingleArgument(
     String subroutineName,
     Class expectedType,
     ArgumentsList arguments,
     List<LispObject> args,
     int argsCounter,
     int i) {
   try {
     if (!(expectedType.isInstance(args.get(argsCounter)))) {
       if (expectedType.equals(LispList.class)
           && args.get(argsCounter).equals(LispSymbol.ourNil)) {
         arguments.setValue(i, LispList.list());
         return argsCounter + 1;
       }
       if (expectedType.equals(LispSymbol.class)
           && args.get(argsCounter).equals(LispSymbol.ourNil)) {
         arguments.setValue(i, LispSymbol.ourNil);
         return argsCounter + 1;
       }
       if (arguments.isOptional(i)) return -1;
       throw new WrongTypeArgumentException(expectedType.getSimpleName(), args.get(argsCounter));
     }
     arguments.setValue(i, args.get(argsCounter));
     return argsCounter + 1;
   } catch (IndexOutOfBoundsException e) {
     if (arguments.isOptional(i)) return -1;
     throw new WrongNumberOfArgumentsException(subroutineName, i);
   }
 }
示例#6
0
 @Deprecated
 public <T extends Widget> T findchild(Class<T> cl) {
   for (Widget wdg = child; wdg != null; wdg = wdg.next) {
     if (cl.isInstance(wdg)) return (cl.cast(wdg));
     T ret = wdg.findchild(cl);
     if (ret != null) return (ret);
   }
   return (null);
 }
示例#7
0
 static boolean hasInstance(Object[] array, Class<? extends Annotation>... cs) {
   for (Object o : array) {
     for (Class<?> c : cs) {
       if (c.isInstance(o)) {
         return true;
       }
     }
   }
   return false;
 }
 private void ensureProtectedAccess(T obj) {
   if (cclass.isInstance(obj)) {
     return;
   }
   throw new RuntimeException(
       new IllegalAccessException(
           "Class "
               + cclass.getName()
               + " can not access a protected member of class "
               + tclass.getName()
               + " using an instance of "
               + obj.getClass().getName()));
 }
示例#9
0
 private static int checkArray(
     Class expectedType, ArgumentsList arguments, List<LispObject> args, int argsCounter, int i) {
   Class componentType = expectedType.getComponentType();
   ArrayList<LispObject> array = new ArrayList<>();
   while (argsCounter != args.size()) {
     if (!componentType.isInstance(args.get(argsCounter)))
       throw new WrongTypeArgumentException(componentType.toString(), args.get(argsCounter));
     array.add(args.get(argsCounter));
     ++argsCounter;
   }
   arguments.setValue(i, customizeArrayList(componentType, array));
   return argsCounter;
 }
示例#10
0
  public static BaseModMp getModInstance(Class class1) {
    for (int i = 0; i < ModLoader.getLoadedMods().size(); i++) {
      BaseMod basemod = (BaseMod) ModLoader.getLoadedMods().get(i);
      if (!(basemod instanceof BaseModMp)) {
        continue;
      }
      BaseModMp basemodmp = (BaseModMp) basemod;
      if (class1.isInstance(basemodmp)) {
        return (BaseModMp) ModLoader.getLoadedMods().get(i);
      }
    }

    return null;
  }
 @SuppressWarnings("unchecked")
 private void apply(Object mock) {
   for (Refinement refinement : refinements) {
     ParameterizedType generic =
         (ParameterizedType) refinement.getClass().getGenericInterfaces()[0];
     Class<?> restrained =
         generic.getActualTypeArguments()[0] instanceof ParameterizedType
             ? (Class<?>) ((ParameterizedType) generic.getActualTypeArguments()[0]).getRawType()
             : (Class<?>) generic.getActualTypeArguments()[0];
     if (restrained.isInstance(mock)) {
       refinement.apply(mock);
     }
   }
 }
示例#12
0
  public static void main(String[] args) throws Exception {
    int tests = 0;
    int passed = 0;
    Class testClass = Class.forName(args[0]);
    for (Method m : testClass.getDeclaredMethods()) {
      if (m.isAnnotationPresent(Test.class)) {
        tests++;
        try {
          m.invoke(null);
          passed++;
        } catch (InvocationTargetException wrappedExc) {
          Throwable exc = wrappedExc.getCause();
          System.out.println(m + " failed: " + exc);
        } catch (Exception exc) {
          System.out.println("INVALID @Test: " + m);
        }
      }

      // Array ExceptionTest processing code - Page 174
      if (m.isAnnotationPresent(ExceptionTest.class)) {
        tests++;
        try {
          m.invoke(null);
          System.out.printf("Test %s failed: no exception%n", m);
        } catch (Throwable wrappedExc) {
          Throwable exc = wrappedExc.getCause();
          Class<? extends Exception>[] excTypes = m.getAnnotation(ExceptionTest.class).value();
          int oldPassed = passed;
          for (Class<? extends Exception> excType : excTypes) {
            if (excType.isInstance(exc)) {
              passed++;
              break;
            }
          }
          if (passed == oldPassed) System.out.printf("Test %s failed: %s %n", m, exc);
        }
      }
    }
    System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed);
  }
  /**
   * Derive a ranking based on how "natural" the conversion is. The special value CONVERSION_NONE
   * means no conversion is possible, and CONVERSION_NONTRIVIAL signals that more type conformance
   * testing is required. Based on <a
   * href="http://www.mozilla.org/js/liveconnect/lc3_method_overloading.html">"preferred method
   * conversions" from Live Connect 3</a>
   */
  static int getConversionWeight(Object fromObj, Class<?> to) {
    int fromCode = getJSTypeCode(fromObj);

    switch (fromCode) {
      case JSTYPE_UNDEFINED:
        if (to == ScriptRuntime.StringClass || to == ScriptRuntime.ObjectClass) {
          return 1;
        }
        break;

      case JSTYPE_NULL:
        if (!to.isPrimitive()) {
          return 1;
        }
        break;

      case JSTYPE_BOOLEAN:
        // "boolean" is #1
        if (to == Boolean.TYPE) {
          return 1;
        } else if (to == ScriptRuntime.BooleanClass) {
          return 2;
        } else if (to == ScriptRuntime.ObjectClass) {
          return 3;
        } else if (to == ScriptRuntime.StringClass) {
          return 4;
        }
        break;

      case JSTYPE_NUMBER:
        if (to.isPrimitive()) {
          if (to == Double.TYPE) {
            return 1;
          } else if (to != Boolean.TYPE) {
            return 1 + getSizeRank(to);
          }
        } else {
          if (to == ScriptRuntime.StringClass) {
            // native numbers are #1-8
            return 9;
          } else if (to == ScriptRuntime.ObjectClass) {
            return 10;
          } else if (ScriptRuntime.NumberClass.isAssignableFrom(to)) {
            // "double" is #1
            return 2;
          }
        }
        break;

      case JSTYPE_STRING:
        if (to == ScriptRuntime.StringClass) {
          return 1;
        } else if (to.isInstance(fromObj)) {
          return 2;
        } else if (to.isPrimitive()) {
          if (to == Character.TYPE) {
            return 3;
          } else if (to != Boolean.TYPE) {
            return 4;
          }
        }
        break;

      case JSTYPE_JAVA_CLASS:
        if (to == ScriptRuntime.ClassClass) {
          return 1;
        } else if (to == ScriptRuntime.ObjectClass) {
          return 3;
        } else if (to == ScriptRuntime.StringClass) {
          return 4;
        }
        break;

      case JSTYPE_JAVA_OBJECT:
      case JSTYPE_JAVA_ARRAY:
        Object javaObj = fromObj;
        if (javaObj instanceof Wrapper) {
          javaObj = ((Wrapper) javaObj).unwrap();
        }
        if (to.isInstance(javaObj)) {
          return CONVERSION_NONTRIVIAL;
        }
        if (to == ScriptRuntime.StringClass) {
          return 2;
        } else if (to.isPrimitive() && to != Boolean.TYPE) {
          return (fromCode == JSTYPE_JAVA_ARRAY) ? CONVERSION_NONE : 2 + getSizeRank(to);
        }
        break;

      case JSTYPE_OBJECT:
        // Other objects takes #1-#3 spots
        if (to == fromObj.getClass()) {
          // No conversion required
          return 1;
        }
        if (to.isArray()) {
          if (fromObj instanceof NativeArray) {
            // This is a native array conversion to a java array
            // Array conversions are all equal, and preferable to object
            // and string conversion, per LC3.
            return 1;
          }
        } else if (to == ScriptRuntime.ObjectClass) {
          return 2;
        } else if (to == ScriptRuntime.StringClass) {
          return 3;
        } else if (to == ScriptRuntime.DateClass) {
          if (fromObj instanceof NativeDate) {
            // This is a native date to java date conversion
            return 1;
          }
        } else if (to.isInterface()) {
          if (fromObj instanceof Function) {
            // See comments in coerceType
            if (to.getMethods().length == 1) {
              return 1;
            }
          }
          return 11;
        } else if (to.isPrimitive() && to != Boolean.TYPE) {
          return 3 + getSizeRank(to);
        }
        break;
    }

    return CONVERSION_NONE;
  }
示例#14
0
 private static boolean compatible(Class type, Object o) {
   if (type == Frame.class && o instanceof ValueArray) return true;
   return type.isInstance(o);
 }
  /** 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;
  }
示例#16
0
 public <T extends Widget> T getparent(Class<T> cl) {
   for (Widget w = this; w != null; w = w.parent) {
     if (cl.isInstance(w)) return (cl.cast(w));
   }
   return (null);
 }
 void targetCheck(T obj) {
   if (!tclass.isInstance(obj)) throw new ClassCastException();
   if (cclass != null) ensureProtectedAccess(obj);
 }
示例#18
0
  @Override
  public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    // Find a method that matches the types given.
    if (methods.length == 0) {
      throw new RuntimeException("No methods defined for call");
    }

    int index = findFunction(cx, methods, args);
    if (index < 0) {
      Class<?> c = methods[0].method().getDeclaringClass();
      String sig = c.getName() + '.' + getFunctionName() + '(' + scriptSignature(args) + ')';
      throw Context.reportRuntimeError1("msg.java.no_such_method", sig);
    }

    MemberBox meth = methods[index];
    Class<?>[] argTypes = meth.argTypes;

    if (meth.vararg) {
      // marshall the explicit parameters
      Object[] newArgs = new Object[argTypes.length];
      for (int i = 0; i < argTypes.length - 1; i++) {
        newArgs[i] = Context.jsToJava(args[i], argTypes[i]);
      }

      Object varArgs;

      // Handle special situation where a single variable parameter
      // is given and it is a Java or ECMA array or is null.
      if (args.length == argTypes.length
          && (args[args.length - 1] == null
              || args[args.length - 1] instanceof NativeArray
              || args[args.length - 1] instanceof NativeJavaArray)) {
        // convert the ECMA array into a native array
        varArgs = Context.jsToJava(args[args.length - 1], argTypes[argTypes.length - 1]);
      } else {
        // marshall the variable parameters
        Class<?> componentType = argTypes[argTypes.length - 1].getComponentType();
        varArgs = Array.newInstance(componentType, args.length - argTypes.length + 1);
        for (int i = 0; i < Array.getLength(varArgs); i++) {
          Object value = Context.jsToJava(args[argTypes.length - 1 + i], componentType);
          Array.set(varArgs, i, value);
        }
      }

      // add varargs
      newArgs[argTypes.length - 1] = varArgs;
      // replace the original args with the new one
      args = newArgs;
    } else {
      // First, we marshall the args.
      Object[] origArgs = args;
      for (int i = 0; i < args.length; i++) {
        Object arg = args[i];
        Object coerced = Context.jsToJava(arg, argTypes[i]);
        if (coerced != arg) {
          if (origArgs == args) {
            args = args.clone();
          }
          args[i] = coerced;
        }
      }
    }
    Object javaObject;
    if (meth.isStatic()) {
      javaObject = null; // don't need an object
    } else {
      Scriptable o = thisObj;
      Class<?> c = meth.getDeclaringClass();
      for (; ; ) {
        if (o == null) {
          throw Context.reportRuntimeError3(
              "msg.nonjava.method",
              getFunctionName(),
              ScriptRuntime.toString(thisObj),
              c.getName());
        }
        if (o instanceof Wrapper) {
          javaObject = ((Wrapper) o).unwrap();
          if (c.isInstance(javaObject)) {
            break;
          }
        }
        o = o.getPrototype();
      }
    }
    if (debug) {
      printDebug("Calling ", meth, args);
    }

    Object retval = meth.invoke(javaObject, args);
    Class<?> staticType = meth.method().getReturnType();

    if (debug) {
      Class<?> actualType = (retval == null) ? null : retval.getClass();
      System.err.println(
          " ----- Returned " + retval + " actual = " + actualType + " expect = " + staticType);
    }

    Object wrapped =
        cx.getWrapFactory()
            .wrap(
                cx, scope,
                retval, staticType);
    if (debug) {
      Class<?> actualType = (wrapped == null) ? null : wrapped.getClass();
      System.err.println(" ----- Wrapped as " + wrapped + " class = " + actualType);
    }

    if (wrapped == null && staticType == Void.TYPE) {
      wrapped = Undefined.instance;
    }
    return wrapped;
  }
 void updateCheck(T obj, V update) {
   if (!tclass.isInstance(obj)
       || (update != null && vclass != null && !vclass.isInstance(update)))
     throw new ClassCastException();
   if (cclass != null) ensureProtectedAccess(obj);
 }
示例#20
0
  /**
   * Performs conversions on argument types if needed and invokes the underlying Java method or
   * constructor.
   *
   * <p>Implements Function.call.
   *
   * @see gov.nbcs.rp.common.js.javascript.Function#call( Context, Scriptable, Scriptable, Object[])
   */
  public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
    Object result;
    boolean checkMethodResult = false;

    if (parmsLength < 0) {
      if (parmsLength == VARARGS_METHOD) {
        Object[] invokeArgs = {cx, thisObj, args, this};
        result = member.invoke(null, invokeArgs);
        checkMethodResult = true;
      } else {
        boolean inNewExpr = (thisObj == null);
        Boolean b = inNewExpr ? Boolean.TRUE : Boolean.FALSE;
        Object[] invokeArgs = {cx, args, this, b};
        result =
            (member.isCtor()) ? member.newInstance(invokeArgs) : member.invoke(null, invokeArgs);
      }

    } else {
      if (!isStatic) {
        Class clazz = member.getDeclaringClass();
        if (!clazz.isInstance(thisObj)) {
          boolean compatible = false;
          if (thisObj == scope) {
            Scriptable parentScope = getParentScope();
            if (scope != parentScope) {
              // Call with dynamic scope for standalone function,
              // use parentScope as thisObj
              compatible = clazz.isInstance(parentScope);
              if (compatible) {
                thisObj = parentScope;
              }
            }
          }
          if (!compatible) {
            // Couldn't find an object to call this on.
            throw ScriptRuntime.typeError1("msg.incompat.call", functionName);
          }
        }
      }

      Object[] invokeArgs;
      if (parmsLength == args.length) {
        // Do not allocate new argument array if java arguments are
        // the same as the original js ones.
        invokeArgs = args;
        for (int i = 0; i != parmsLength; ++i) {
          Object arg = args[i];
          Object converted = convertArg(cx, scope, arg, typeTags[i]);
          if (arg != converted) {
            if (invokeArgs == args) {
              invokeArgs = (Object[]) args.clone();
            }
            invokeArgs[i] = converted;
          }
        }
      } else if (parmsLength == 0) {
        invokeArgs = ScriptRuntime.emptyArgs;
      } else {
        invokeArgs = new Object[parmsLength];
        for (int i = 0; i != parmsLength; ++i) {
          Object arg = (i < args.length) ? args[i] : Undefined.instance;
          invokeArgs[i] = convertArg(cx, scope, arg, typeTags[i]);
        }
      }

      if (member.isMethod()) {
        result = member.invoke(thisObj, invokeArgs);
        checkMethodResult = true;
      } else {
        result = member.newInstance(invokeArgs);
      }
    }

    if (checkMethodResult) {
      if (hasVoidReturn) {
        result = Undefined.instance;
      } else if (returnTypeTag == JAVA_UNSUPPORTED_TYPE) {
        result = cx.getWrapFactory().wrap(cx, scope, result, null);
      }
      // XXX: the code assumes that if returnTypeTag == JAVA_OBJECT_TYPE
      // then the Java method did a proper job of converting the
      // result to JS primitive or Scriptable to avoid
      // potentially costly Context.javaToJS call.
    }

    return result;
  }
  private Object getParam(
      final Class<?> pClass,
      final String pName,
      final ParamType pType,
      final String pXpath,
      final HttpMessage pMessage)
      throws XmlException {
    Object result = null;
    switch (pType) {
      case GET:
        result = getParamGet(pName, pMessage);
        break;
      case POST:
        result = getParamPost(pName, pMessage);
        break;
      case QUERY:
        result = getParamGet(pName, pMessage);
        if (result == null) {
          result = getParamPost(pName, pMessage);
        }
        break;
      case VAR:
        result = mPathParams.get(pName);
        break;
      case XPATH:
        result = getParamXPath(pClass, pXpath, pMessage.getBody());
        break;
      case BODY:
        result = getBody(pClass, pMessage);
        break;
      case ATTACHMENT:
        result = getAttachment(pClass, pName, pMessage);
        break;
      case PRINCIPAL:
        {
          final Principal principal = pMessage.getUserPrincipal();
          if (pClass.isAssignableFrom(String.class)) {
            result = principal.getName();
          } else {
            result = principal;
          }
          break;
        }
    }
    // XXX generizice this and share the same approach to unmarshalling in ALL code
    // TODO support collection/list parameters
    if ((result != null) && (!pClass.isInstance(result))) {
      if ((Types.isPrimitive(pClass) || (Types.isPrimitiveWrapper(pClass)))
          && (result instanceof String)) {
        try {
          result = Types.parsePrimitive(pClass, ((String) result));
        } catch (NumberFormatException e) {
          throw new HttpResponseException(
              HttpServletResponse.SC_BAD_REQUEST, "The argument given is invalid", e);
        }
      } else if (Enum.class.isAssignableFrom(pClass)) {
        @SuppressWarnings({"rawtypes"})
        final Class clazz = pClass;
        @SuppressWarnings("unchecked")
        final Enum<?> tmpResult = Enum.valueOf(clazz, result.toString());
        result = tmpResult;
      } else if (result instanceof Node) {
        XmlDeserializer factory = pClass.getAnnotation(XmlDeserializer.class);
        if (factory != null) {
          try {
            result =
                factory
                    .value()
                    .newInstance()
                    .deserialize(XmlStreaming.newReader(new DOMSource((Node) result)));
          } catch (IllegalAccessException | InstantiationException e) {
            throw new XmlException(e);
          }
        } else {
          result = JAXB.unmarshal(new DOMSource((Node) result), pClass);
        }
      } else {
        final String s = result.toString();
        // Only wrap when we don't start with <
        final char[] requestBody =
            (s.startsWith("<") ? s : "<wrapper>" + s + "</wrapper>").toCharArray();
        if (requestBody.length > 0) {
          result = JAXB.unmarshal(new CharArrayReader(requestBody), pClass);
        } else {
          result = null;
        }
      }
    }

    return result;
  }