예제 #1
0
  public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    String generic = invoker.getUrl().getParameter(Constants.GENERIC_KEY);
    if (ProtocolUtils.isGeneric(generic)
        && !Constants.$INVOKE.equals(invocation.getMethodName())
        && invocation instanceof RpcInvocation) {
      RpcInvocation invocation2 = (RpcInvocation) invocation;
      String methodName = invocation2.getMethodName();
      Class<?>[] parameterTypes = invocation2.getParameterTypes();
      Object[] arguments = invocation2.getArguments();

      String[] types = new String[parameterTypes.length];
      for (int i = 0; i < parameterTypes.length; i++) {
        types[i] = ReflectUtils.getName(parameterTypes[i]);
      }
      Object[] args = PojoUtils.generalize(arguments);

      invocation2.setMethodName(Constants.$INVOKE);
      invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
      invocation2.setArguments(new Object[] {methodName, types, args});
      Result result = invoker.invoke(invocation2);

      if (!result.hasException()) {
        Object value = result.getValue();
        try {
          Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
          return new RpcResult(
              PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
        } catch (NoSuchMethodException e) {
          throw new RpcException(e.getMessage(), e);
        }
      } else if (result.getException() instanceof GenericException) {
        GenericException exception = (GenericException) result.getException();
        try {
          String className = exception.getExceptionClass();
          Class<?> clazz = ReflectUtils.forName(className);
          Throwable targetException = null;
          Throwable lastException = null;
          try {
            targetException = (Throwable) clazz.newInstance();
          } catch (Throwable e) {
            lastException = e;
            for (Constructor<?> constructor : clazz.getConstructors()) {
              try {
                targetException =
                    (Throwable)
                        constructor.newInstance(new Object[constructor.getParameterTypes().length]);
                break;
              } catch (Throwable e1) {
                lastException = e1;
              }
            }
          }
          if (targetException != null) {
            try {
              Field field = Throwable.class.getDeclaredField("detailMessage");
              if (!field.isAccessible()) {
                field.setAccessible(true);
              }
              field.set(targetException, exception.getExceptionMessage());
            } catch (Throwable e) {
              logger.warn(e.getMessage(), e);
            }
            result = new RpcResult(targetException);
          } else if (lastException != null) {
            throw lastException;
          }
        } catch (Throwable e) {
          throw new RpcException(
              "Can not deserialize exception "
                  + exception.getExceptionClass()
                  + ", message: "
                  + exception.getExceptionMessage(),
              e);
        }
      }
      return result;
    }

    if (invocation.getMethodName().equals(Constants.$INVOKE)
        && invocation.getArguments() != null
        && invocation.getArguments().length == 3
        && ProtocolUtils.isGeneric(generic)) {

      if (ProtocolUtils.isJavaGenericSerialization(generic)) {
        Object[] args = (Object[]) invocation.getArguments()[2];

        for (Object arg : args) {
          if (!(byte[].class == arg.getClass())) {
            error(arg.getClass().getName());
          }
        }
      }

      ((RpcInvocation) invocation)
          .setAttachment(
              Constants.GENERIC_KEY, invoker.getUrl().getParameter(Constants.GENERIC_KEY));
    }
    return invoker.invoke(invocation);
  }