Ejemplo n.º 1
0
 protected String toStringExpression(JParameter arg) {
   Attribute attribute = arg.getAnnotation(Attribute.class);
   if (attribute != null) {
     return arg.getName() + "." + attribute.value();
   }
   return toStringExpression(arg.getType(), arg.getName());
 }
Ejemplo n.º 2
0
  protected String toFormStringExpression(JParameter argument, Style classStyle)
      throws UnableToCompleteException {
    JType type = argument.getType();
    String expr = argument.getName();

    if (type.isPrimitive() != null) {
      return "\"\"+" + expr;
    }
    if (STRING_TYPE == type) {
      return expr;
    }
    if (type.isClass() != null && isOverlayArrayType(type.isClass())) {
      return "(new " + JSON_ARRAY_CLASS + "(" + expr + ")).toString()";
    }
    if (type.isClass() != null && OVERLAY_VALUE_TYPE.isAssignableFrom(type.isClass())) {
      return "(new " + JSON_OBJECT_CLASS + "(" + expr + ")).toString()";
    }
    if (type.getQualifiedBinaryName().startsWith("java.lang.")) {
      return String.format("(%s != null ? %s.toString() : null)", expr, expr);
    }

    Json jsonAnnotation = argument.getAnnotation(Json.class);
    final Style style = jsonAnnotation != null ? jsonAnnotation.style() : classStyle;

    return locator.encodeExpression(type, expr, style) + ".toString()";
  }
Ejemplo n.º 3
0
  protected String toIteratedStringExpression(JParameter arg) {
    StringBuilder result = new StringBuilder();
    result
        .append("new org.fusesource.restygwt.client.StringIterable (")
        .append(arg.getName())
        .append(")");

    return result.toString();
  }
Ejemplo n.º 4
0
 /**
  * @param srcWriter
  * @param type
  * @param parentVariable
  * @param added
  * @param iocContainerVariable
  * @param configurations
  */
 private static void injectMethods(
     SourcePrinter srcWriter,
     JClassType type,
     String parentVariable,
     Set<String> added,
     String iocContainerVariable,
     Map<String, IocConfig<?>> configurations) {
   for (JMethod method : type.getMethods()) {
     Inject inject = method.getAnnotation(Inject.class);
     if (inject != null && !method.isStatic()) {
       String methodName = method.getName();
       if (!added.contains(methodName + "()")) {
         added.add(methodName + "()");
         JParameter[] parameters = method.getParameters();
         List<String> params = new ArrayList<String>();
         for (JParameter parameter : parameters) {
           JType parameterType = parameter.getType();
           if ((parameterType.isPrimitive() != null)) {
             throw new IoCException(
                 "IoC Error Method ["
                     + methodName
                     + "] from class ["
                     + type.getQualifiedSourceName()
                     + "] declares an invalid parameter. Primitive types are not allowed here");
           }
           String variableName = "parameter_" + methodName + "_" + parameter.getName();
           params.add(variableName);
           String injectionExpression =
               getParameterInjectionExpression(parameter, iocContainerVariable, configurations);
           srcWriter.println(
               parameterType.getQualifiedSourceName()
                   + " "
                   + variableName
                   + " = "
                   + injectionExpression
                   + ";");
         }
         srcWriter.print(parentVariable + "." + methodName + "(");
         boolean first = true;
         for (String param : params) {
           if (!first) {
             srcWriter.print(", ");
           }
           first = false;
           srcWriter.print(param);
         }
         srcWriter.println(");");
       }
     }
   }
 }
Ejemplo n.º 5
0
 @SuppressWarnings("deprecation")
 private static String getParameterInjectionExpression(
     JParameter parameter, String iocContainerVariable, Map<String, IocConfig<?>> configurations) {
   JType parameterType = parameter.getType();
   if (parameterType.isClassOrInterface() != null) {
     String fieldTypeName = parameterType.getQualifiedSourceName();
     IocConfigImpl<?> iocConfig = (IocConfigImpl<?>) configurations.get(fieldTypeName);
     if (iocConfig != null) {
       Inject inject = getInjectAnnotation(parameter);
       if (inject.scope().equals(org.cruxframework.crux.core.client.ioc.Inject.Scope.DEFAULT)) {
         return iocContainerVariable
             + ".get"
             + fieldTypeName.replace('.', '_')
             + "("
             + Scope.class.getCanonicalName()
             + "."
             + iocConfig.getScope().name()
             + ", null)";
       }
       return iocContainerVariable
           + ".get"
           + fieldTypeName.replace('.', '_')
           + "("
           + Scope.class.getCanonicalName()
           + "."
           + getScopeName(inject.scope())
           + ", "
           + EscapeUtils.quote(inject.subscope())
           + ")";
     } else {
       return "GWT.create(" + fieldTypeName + ".class)";
     }
   } else {
     throw new IoCException(
         "Error injecting parameter ["
             + parameter.getName()
             + "] from method ["
             + parameter.getEnclosingMethod().getReadableDeclaration()
             + "]. Primitive fields can not be handled by ioc container.");
   }
 }
  @Override
  protected void generateWrapperMethod(JMethod method, SourcePrinter srcWriter) {
    if (mustDelegateToController(method)) {
      JType returnType = method.getReturnType().getErasedType();

      srcWriter.println(method.getReadableDeclaration(false, false, false, false, true) + "{");
      if (returnType != JPrimitiveType.VOID) {
        srcWriter.print("return ");
      }
      srcWriter.print("this._controller." + method.getName() + "(");
      boolean needsComma = false;
      for (JParameter parameter : method.getParameters()) {
        if (needsComma) {
          srcWriter.print(", ");
        }
        needsComma = true;
        srcWriter.print(parameter.getName());
      }
      srcWriter.println(");");

      srcWriter.println("}");
    }
  }
Ejemplo n.º 7
0
  private void writeMethodImpl(JMethod method) throws UnableToCompleteException {
    boolean returnRequest = false;
    if (method.getReturnType() != JPrimitiveType.VOID) {
      if (!method.getReturnType().getQualifiedSourceName().equals(Request.class.getName())
          && !method
              .getReturnType()
              .getQualifiedSourceName()
              .equals(JsonpRequest.class.getName())) {
        getLogger()
            .log(
                ERROR,
                "Invalid rest method. Method must have void, Request or JsonpRequest return types: "
                    + method.getReadableDeclaration());
        throw new UnableToCompleteException();
      } else {
        returnRequest = true;
      }
    }

    Json jsonAnnotation = source.getAnnotation(Json.class);
    final Style classStyle = jsonAnnotation != null ? jsonAnnotation.style() : Style.DEFAULT;

    Options classOptions = source.getAnnotation(Options.class);
    Options options = method.getAnnotation(Options.class);

    p(method.getReadableDeclaration(false, false, false, false, true) + " {").i(1);
    {
      String restMethod = getRestMethod(method);
      LinkedList<JParameter> args =
          new LinkedList<JParameter>(Arrays.asList(method.getParameters()));

      // the last arg should be the callback.
      if (args.isEmpty()) {
        getLogger()
            .log(
                ERROR,
                "Invalid rest method. Method must declare at least a callback argument: "
                    + method.getReadableDeclaration());
        throw new UnableToCompleteException();
      }
      JParameter callbackArg = args.removeLast();
      JClassType callbackType = callbackArg.getType().isClassOrInterface();
      JClassType methodCallbackType = METHOD_CALLBACK_TYPE;
      if (callbackType == null || !callbackType.isAssignableTo(methodCallbackType)) {
        getLogger()
            .log(
                ERROR,
                "Invalid rest method. Last argument must be a "
                    + methodCallbackType.getName()
                    + " type: "
                    + method.getReadableDeclaration());
        throw new UnableToCompleteException();
      }
      JClassType resultType = getCallbackTypeGenericClass(callbackType);

      String pathExpression = null;
      Path pathAnnotation = method.getAnnotation(Path.class);
      if (pathAnnotation != null) {
        pathExpression = wrap(pathAnnotation.value());
      }

      JParameter contentArg = null;
      HashMap<String, JParameter> queryParams = new HashMap<String, JParameter>();
      HashMap<String, JParameter> formParams = new HashMap<String, JParameter>();
      HashMap<String, JParameter> headerParams = new HashMap<String, JParameter>();

      for (JParameter arg : args) {
        PathParam paramPath = arg.getAnnotation(PathParam.class);
        if (paramPath != null) {
          if (pathExpression == null) {
            getLogger()
                .log(
                    ERROR,
                    "Invalid rest method.  Invalid @PathParam annotation. Method is missing the @Path annotation: "
                        + method.getReadableDeclaration());
            throw new UnableToCompleteException();
          }
          pathExpression = pathExpression(pathExpression, arg, paramPath);
          // .replaceAll(Pattern.quote("{" + paramPath.value() + "}"),
          // "\"+com.google.gwt.http.client.URL.encodePathSegment(" + toStringExpression(arg) +
          // ")+\"");
          if (arg.getAnnotation(Attribute.class) != null) {
            // allow part of the arg-object participate in as PathParam and the object goes over the
            // wire
            contentArg = arg;
          }
          continue;
        }

        QueryParam queryParam = arg.getAnnotation(QueryParam.class);
        if (queryParam != null) {
          queryParams.put(queryParam.value(), arg);
          continue;
        }

        FormParam formParam = arg.getAnnotation(FormParam.class);
        if (formParam != null) {
          formParams.put(formParam.value(), arg);
          continue;
        }

        HeaderParam headerParam = arg.getAnnotation(HeaderParam.class);
        if (headerParam != null) {
          headerParams.put(headerParam.value(), arg);
          continue;
        }

        if (!formParams.isEmpty()) {
          getLogger()
              .log(
                  ERROR,
                  "You can not have both @FormParam parameters and a content parameter: "
                      + method.getReadableDeclaration());
          throw new UnableToCompleteException();
        }

        if (contentArg != null) {
          getLogger()
              .log(
                  ERROR,
                  "Invalid rest method. Only one content parameter is supported: "
                      + method.getReadableDeclaration());
          throw new UnableToCompleteException();
        }
        contentArg = arg;
      }

      String acceptTypeBuiltIn = null;
      if (callbackType.equals(TEXT_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_TEXT";
      } else if (callbackType.equals(JSON_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_JSON";
      } else if (callbackType.isAssignableTo(OVERLAY_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_JSON";
      } else if (callbackType.equals(XML_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_XML";
      }

      p("final " + METHOD_CLASS + " __method =");

      p("getResource()");
      if (pathExpression != null) {
        p(".resolve(" + pathExpression + ")");
      }
      for (Map.Entry<String, JParameter> entry : queryParams.entrySet()) {
        String expr = entry.getValue().getName();
        JClassType type = entry.getValue().getType().isClassOrInterface();
        if (type != null && isQueryParamListType(type)) {
          p(
              ".addQueryParams("
                  + wrap(entry.getKey())
                  + ", "
                  + toIteratedStringExpression(entry.getValue())
                  + ")");
        } else {
          p(
              ".addQueryParam("
                  + wrap(entry.getKey())
                  + ", "
                  + toStringExpression(entry.getValue().getType(), expr)
                  + ")");
        }
      }
      // example: .get()
      p("." + restMethod + "();");

      // Handle JSONP specific configuration...
      JSONP jsonpAnnotation = method.getAnnotation(JSONP.class);

      final boolean isJsonp = restMethod.equals(METHOD_JSONP) && jsonpAnnotation != null;
      if (isJsonp) {
        if (returnRequest
            && !method
                .getReturnType()
                .getQualifiedSourceName()
                .equals(JsonpRequest.class.getName())) {
          getLogger()
              .log(
                  ERROR,
                  "Invalid rest method. JSONP method must have void or JsonpRequest return types: "
                      + method.getReadableDeclaration());
          throw new UnableToCompleteException();
        }
        if (jsonpAnnotation.callbackParam().length() > 0) {
          p(
              "(("
                  + JSONP_METHOD_CLASS
                  + ")__method).callbackParam("
                  + wrap(jsonpAnnotation.callbackParam())
                  + ");");
        }
        if (jsonpAnnotation.failureCallbackParam().length() > 0) {
          p(
              "(("
                  + JSONP_METHOD_CLASS
                  + ")__method).failureCallbackParam("
                  + wrap(jsonpAnnotation.failureCallbackParam())
                  + ");");
        }
      } else {
        if (returnRequest
            && !method.getReturnType().getQualifiedSourceName().equals(Request.class.getName())) {
          getLogger()
              .log(
                  ERROR,
                  "Invalid rest method. Non JSONP method must have void or Request return types: "
                      + method.getReadableDeclaration());
          throw new UnableToCompleteException();
        }
      }

      // configure the dispatcher
      if (options != null && options.dispatcher() != Dispatcher.class) {
        // use the dispatcher configured for the method.
        p("__method.setDispatcher(" + options.dispatcher().getName() + ".INSTANCE);");
      } else {
        // use the default dispatcher configured for the service..
        p("__method.setDispatcher(this.dispatcher);");
      }

      // configure the expected statuses..
      if (options != null && options.expect().length != 0) {
        // Using method level defined expected status
        p("__method.expect(" + join(options.expect(), ", ") + ");");
      } else if (classOptions != null && classOptions.expect().length != 0) {
        // Using class level defined expected status
        p("__method.expect(" + join(classOptions.expect(), ", ") + ");");
      }

      // configure the timeout
      if (options != null && options.timeout() >= 0) {
        // Using method level defined value
        p("__method.timeout(" + options.timeout() + ");");
      } else if (classOptions != null && classOptions.timeout() >= 0) {
        // Using class level defined value
        p("__method.timeout(" + classOptions.timeout() + ");");
      }

      if (jsonpAnnotation == null) {
        Produces producesAnnotation = findAnnotationOnMethodOrEnclosingType(method, Produces.class);
        if (producesAnnotation != null) {
          p(
              "__method.header("
                  + RESOURCE_CLASS
                  + ".HEADER_ACCEPT, "
                  + wrap(producesAnnotation.value()[0])
                  + ");");
        } else {
          // set the default accept header....
          if (acceptTypeBuiltIn != null) {
            p(
                "__method.header("
                    + RESOURCE_CLASS
                    + ".HEADER_ACCEPT, "
                    + RESOURCE_CLASS
                    + "."
                    + acceptTypeBuiltIn
                    + ");");
          } else {
            p(
                "__method.header("
                    + RESOURCE_CLASS
                    + ".HEADER_ACCEPT, "
                    + RESOURCE_CLASS
                    + ".CONTENT_TYPE_JSON);");
          }
        }

        Consumes consumesAnnotation = findAnnotationOnMethodOrEnclosingType(method, Consumes.class);
        if (consumesAnnotation != null) {
          p(
              "__method.header("
                  + RESOURCE_CLASS
                  + ".HEADER_CONTENT_TYPE, "
                  + wrap(consumesAnnotation.value()[0])
                  + ");");
        }

        // and set the explicit headers now (could override the accept header)
        for (Map.Entry<String, JParameter> entry : headerParams.entrySet()) {
          String expr = entry.getValue().getName();
          p(
              "__method.header("
                  + wrap(entry.getKey())
                  + ", "
                  + toStringExpression(entry.getValue().getType(), expr)
                  + ");");
        }
      }

      if (!formParams.isEmpty()) {
        p(FORM_POST_CONTENT_CLASS + " __formPostContent = new " + FORM_POST_CONTENT_CLASS + "();");

        for (Map.Entry<String, JParameter> entry : formParams.entrySet()) {
          p(
              "__formPostContent.addParameter("
                  + wrap(entry.getKey())
                  + ", "
                  + toFormStringExpression(entry.getValue(), classStyle)
                  + ");");
        }

        p("__method.form(__formPostContent.getTextContent());");
      }

      if (contentArg != null) {
        if (contentArg.getType() == STRING_TYPE) {
          p("__method.text(" + contentArg.getName() + ");");
        } else if (contentArg.getType() == JSON_VALUE_TYPE) {
          p("__method.json(" + contentArg.getName() + ");");
        } else if (contentArg.getType().isClass() != null
            && isOverlayArrayType(contentArg.getType().isClass())) {
          p("__method.json(new " + JSON_ARRAY_CLASS + "(" + contentArg.getName() + "));");
        } else if (contentArg.getType().isClass() != null
            && contentArg.getType().isClass().isAssignableTo(OVERLAY_VALUE_TYPE)) {
          p("__method.json(new " + JSON_OBJECT_CLASS + "(" + contentArg.getName() + "));");
        } else if (contentArg.getType() == DOCUMENT_TYPE) {
          p("__method.xml(" + contentArg.getName() + ");");
        } else {
          JClassType contentClass = contentArg.getType().isClass();
          if (contentClass == null) {
            contentClass = contentArg.getType().isClassOrInterface();
            if (!locator.isCollectionType(contentClass)) {
              getLogger().log(ERROR, "Content argument must be a class.");
              throw new UnableToCompleteException();
            }
          }

          jsonAnnotation = contentArg.getAnnotation(Json.class);
          Style style = jsonAnnotation != null ? jsonAnnotation.style() : classStyle;

          // example:
          // .json(Listings$_Generated_JsonEncoder_$.INSTANCE.encode(arg0)
          // )
          p(
              "__method.json("
                  + locator.encodeExpression(contentClass, contentArg.getName(), style)
                  + ");");
        }
      }

      List<AnnotationResolver> annotationResolvers = getAnnotationResolvers(context, getLogger());
      getLogger()
          .log(
              TreeLogger.DEBUG,
              "found " + annotationResolvers.size() + " additional AnnotationResolvers");

      for (AnnotationResolver a : annotationResolvers) {
        getLogger()
            .log(
                TreeLogger.DEBUG,
                "("
                    + a.getClass().getName()
                    + ") resolve `"
                    + source.getName()
                    + "#"
                    + method.getName()
                    + "´ ...");
        final Map<String, String[]> addDataParams =
            a.resolveAnnotation(getLogger(), source, method, restMethod);

        if (addDataParams != null) {
          for (String s : addDataParams.keySet()) {
            final StringBuilder sb = new StringBuilder();
            final List<String> classList = Arrays.asList(addDataParams.get(s));

            sb.append("[");
            for (int i = 0; i < classList.size(); ++i) {
              sb.append("\\\"").append(classList.get(i)).append("\\\"");

              if ((i + 1) < classList.size()) {
                sb.append(",");
              }
            }
            sb.append("]");

            getLogger()
                .log(TreeLogger.DEBUG, "add call with (\"" + s + "\", \"" + sb.toString() + "\")");
            p("__method.addData(\"" + s + "\", \"" + sb.toString() + "\");");
          }
        }
      }

      if (acceptTypeBuiltIn != null) {
        // TODO: shouldn't we also have a cach in here?
        p(returnRequest(returnRequest, isJsonp) + "__method.send(" + callbackArg.getName() + ");");
      } else if (isJsonp) {
        p(returnRequest(returnRequest, isJsonp)
                + "(("
                + JSONP_METHOD_CLASS
                + ")__method).send(new "
                + ABSTRACT_ASYNC_CALLBACK_CLASS
                + "<"
                + resultType.getParameterizedQualifiedSourceName()
                + ">(("
                + JSONP_METHOD_CLASS
                + ")__method, "
                + callbackArg.getName()
                + ") {")
            .i(1);
        {
          p("protected "
                  + resultType.getParameterizedQualifiedSourceName()
                  + " parseResult("
                  + JSON_VALUE_CLASS
                  + " result) throws Exception {")
              .i(1);
          {
            if (resultType.getParameterizedQualifiedSourceName().equals("java.lang.Void")) {
              p("return (java.lang.Void) null;");
            } else {
              p("try {").i(1);
              {
                if (resultType.isAssignableTo(locator.LIST_TYPE)) {
                  p("result = new " + JSON_ARRAY_CLASS + "(result.getJavaScriptObject());");
                }
                jsonAnnotation = method.getAnnotation(Json.class);
                Style style = jsonAnnotation != null ? jsonAnnotation.style() : classStyle;
                p("return " + locator.decodeExpression(resultType, "result", style) + ";");
              }
              i(-1).p("} catch (Throwable __e) {").i(1);
              {
                p(
                    "throw new "
                        + RESPONSE_FORMAT_EXCEPTION_CLASS
                        + "(\"Response was NOT a valid JSON document\", __e);");
              }
              i(-1).p("}");
            }
          }
          i(-1).p("}");
        }
        i(-1).p("});");
      } else {
        p("try {").i(1);
        {
          p(returnRequest(returnRequest, isJsonp)
                  + "__method.send(new "
                  + ABSTRACT_REQUEST_CALLBACK_CLASS
                  + "<"
                  + resultType.getParameterizedQualifiedSourceName()
                  + ">(__method, "
                  + callbackArg.getName()
                  + ") {")
              .i(1);
          {
            p("protected "
                    + resultType.getParameterizedQualifiedSourceName()
                    + " parseResult() throws Exception {")
                .i(1);
            {
              if (resultType.getParameterizedQualifiedSourceName().equals("java.lang.Void")) {
                p("return (java.lang.Void) null;");
              } else {
                p("try {").i(1);
                {
                  jsonAnnotation = method.getAnnotation(Json.class);
                  Style style = jsonAnnotation != null ? jsonAnnotation.style() : classStyle;
                  p(
                      "return "
                          + locator.decodeExpression(
                              resultType,
                              JSON_PARSER_CLASS + ".parse(__method.getResponse().getText())",
                              style)
                          + ";");
                }
                i(-1).p("} catch (Throwable __e) {").i(1);
                {
                  p(
                      "throw new "
                          + RESPONSE_FORMAT_EXCEPTION_CLASS
                          + "(\"Response was NOT a valid JSON document\", __e);");
                }
                i(-1).p("}");
              }
            }
            i(-1).p("}");
          }
          i(-1).p("});");
        }
        i(-1).p("} catch (" + REQUEST_EXCEPTION_CLASS + " __e) {").i(1);
        {
          p(callbackArg.getName() + ".onFailure(__method,__e);");
          if (returnRequest) {
            p("return null;");
          }
        }
        i(-1).p("}");
      }
    }
    i(-1).p("}");
  }
  public void generateMethodParamToBodyCode(
      SourcePrinter srcWriter, RestMethodInfo methodInfo, String builder, String httpMethod) {
    JParameter[] parameters = methodInfo.method.getParameters();
    boolean formEncoded = false;
    boolean hasBodyObject = false;

    String formString = getFormString(methodInfo);
    if (!StringUtils.isEmpty(formString)) {
      srcWriter.println("String requestData = " + EscapeUtils.quote(formString) + ";");
    }
    for (int i = 0; i < methodInfo.parameterAnnotations.length; i++) {
      Annotation[] annotations = methodInfo.parameterAnnotations[i];
      if (annotations == null || annotations.length == 0) { // JSON on body
        if (hasBodyObject) {
          throw new CruxGeneratorException(
              "Invalid Method: "
                  + methodInfo.method.getEnclosingType().getName()
                  + "."
                  + methodInfo.method.getName()
                  + "(). "
                  + "Request body can not contain more than one body parameter (JSON serialized object).");
        }

        hasBodyObject = true;
        String serializerName =
            new JSonSerializerProxyCreator(context, logger, parameters[i].getType()).create();
        srcWriter.println(
            builder
                + ".setHeader(\""
                + HttpHeaderNames.CONTENT_TYPE
                + "\", \"application/json\");");
        srcWriter.println(
            "JSONValue serialized = new "
                + serializerName
                + "().encode("
                + parameters[i].getName()
                + ");");
        srcWriter.println(
            "String requestData = (serialized==null||serialized.isNull()!=null)?null:serialized.toString();");
      } else {
        for (Annotation annotation : annotations) {
          JParameter parameter = parameters[i];
          JType parameterType = parameter.getType();
          String parameterName = parameter.getName();
          formEncoded =
              generateMethodParamToBodyCodeForAnnotatedParameter(
                  srcWriter,
                  builder,
                  parameters,
                  formEncoded,
                  i,
                  annotation,
                  parameterType,
                  parameterName);
        }
      }
    }
    if (hasBodyObject && formEncoded) {
      throw new CruxGeneratorException(
          "Invalid Method: "
              + methodInfo.method.getEnclosingType().getName()
              + "."
              + methodInfo.method.getName()
              + "(). "
              + "Request body can not contain form parameters and a JSON serialized object.");
    }
    if (hasBodyObject || formEncoded) {
      if (httpMethod.equals("GET")) {
        throw new CruxGeneratorException(
            "Invalid Method: "
                + methodInfo.method.getEnclosingType().getName()
                + "."
                + methodInfo.method.getName()
                + "(). "
                + "Can not use request body parameters on a GET operation.");
      }
      srcWriter.println(builder + ".setRequestData(requestData);");
    }
  }
Ejemplo n.º 9
0
  /**
   * Generates the client's asynchronous proxy method.
   *
   * @param serializableTypeOracle the type oracle
   */
  protected void generateProxyMethod(
      SourceWriter w,
      SerializableTypeOracle serializableTypeOracle,
      TypeOracle typeOracle,
      JMethod syncMethod,
      JMethod asyncMethod) {

    w.println();

    // Write the method signature
    JType asyncReturnType = asyncMethod.getReturnType().getErasedType();
    w.print("public ");
    w.print(asyncReturnType.getQualifiedSourceName());
    w.print(" ");
    w.print(asyncMethod.getName() + "(");

    boolean needsComma = false;
    NameFactory nameFactory = new NameFactory();
    JParameter[] asyncParams = asyncMethod.getParameters();
    for (int i = 0; i < asyncParams.length; ++i) {
      JParameter param = asyncParams[i];

      if (needsComma) {
        w.print(", ");
      } else {
        needsComma = true;
      }

      /*
       * Ignoring the AsyncCallback parameter, if any method requires a call to
       * SerializationStreamWriter.writeObject we need a try catch block
       */
      JType paramType = param.getType();
      paramType = paramType.getErasedType();

      w.print(paramType.getQualifiedSourceName());
      w.print(" ");

      String paramName = param.getName();
      nameFactory.addName(paramName);
      w.print(paramName);
    }

    w.println(") {");
    w.indent();

    String helperName = nameFactory.createName("helper");
    String helperClassName = RemoteServiceProxy.ServiceHelper.class.getCanonicalName();
    w.println(
        "%s %s = new %s(\"%s\", \"%s\");",
        helperClassName, helperName, helperClassName, getProxySimpleName(), syncMethod.getName());

    w.println("try {");
    w.indent();

    // Write the parameter count followed by the parameter values
    JParameter[] syncParams = syncMethod.getParameters();

    String streamWriterName = nameFactory.createName("streamWriter");
    w.println(
        "%s %s = %s.start(REMOTE_SERVICE_INTERFACE_NAME, %s);",
        SerializationStreamWriter.class.getSimpleName(),
        streamWriterName,
        helperName,
        syncParams.length);

    for (JParameter param : syncParams) {
      JType paramType = param.getType().getErasedType();
      String typeNameExpression = computeTypeNameExpression(paramType);
      assert typeNameExpression != null
          : "Could not compute a type name for " + paramType.getQualifiedSourceName();
      w.println(streamWriterName + ".writeString(" + typeNameExpression + ");");
    }

    // Encode all of the arguments to the asynchronous method, but exclude the
    // last argument which is the callback instance.
    //
    for (int i = 0; i < asyncParams.length - 1; ++i) {
      JParameter asyncParam = asyncParams[i];
      w.print(streamWriterName + ".");
      w.print(Shared.getStreamWriteMethodNameFor(asyncParam.getType()));
      w.println("(" + asyncParam.getName() + ");");
    }

    /*
     * Depending on the return type for the async method, return a
     * RequestBuilder, a Request, or nothing at all.
     */
    JParameter callbackParam = asyncParams[asyncParams.length - 1];
    JType returnType = syncMethod.getReturnType();
    String callbackName = callbackParam.getName();

    if (asyncReturnType == JPrimitiveType.VOID) {
      w.println(
          "%s.finish(%s, ResponseReader.%s);",
          helperName, callbackName, getResponseReaderFor(returnType).name());
    } else if (asyncReturnType.getQualifiedSourceName().equals(RequestBuilder.class.getName())) {
      w.println(
          "return %s.finishForRequestBuilder(%s, ResponseReader.%s);",
          helperName, callbackName, getResponseReaderFor(returnType).name());
    } else if (asyncReturnType.getQualifiedSourceName().equals(Request.class.getName())) {
      w.println(
          "return %s.finish(%s, ResponseReader.%s);",
          helperName, callbackName, getResponseReaderFor(returnType).name());
    } else {
      // This method should have been caught by RemoteServiceAsyncValidator
      throw new RuntimeException(
          "Unhandled return type " + asyncReturnType.getQualifiedSourceName());
    }

    w.outdent();
    w.print("} catch (SerializationException ");
    String exceptionName = nameFactory.createName("ex");
    w.println(exceptionName + ") {");
    w.indent();
    if (!asyncReturnType.getQualifiedSourceName().equals(RequestBuilder.class.getName())) {
      /*
       * If the method returns void or Request, signal the serialization error
       * immediately. If the method returns RequestBuilder, the error will be
       * signaled whenever RequestBuilder.send() is invoked.
       */
      w.println(callbackName + ".onFailure(" + exceptionName + ");");
    }
    if (asyncReturnType.getQualifiedSourceName().equals(RequestBuilder.class.getName())) {
      w.println(
          "return new "
              + FailingRequestBuilder.class.getName()
              + "("
              + exceptionName
              + ", "
              + callbackName
              + ");");
    } else if (asyncReturnType.getQualifiedSourceName().equals(Request.class.getName())) {
      w.println("return new " + FailedRequest.class.getName() + "();");
    } else {
      assert asyncReturnType == JPrimitiveType.VOID;
    }
    w.outdent();
    w.println("}");

    w.outdent();
    w.println("}");
  }
Ejemplo n.º 10
0
 @Override
 public String getName() {
   return parameter.getName();
 }
Ejemplo n.º 11
0
  private void writeMethodImpl(JMethod method) throws UnableToCompleteException {
    if (method.getReturnType().isPrimitive() != JPrimitiveType.VOID) {
      error(
          "Invalid rest method. Method must have void return type: "
              + method.getReadableDeclaration());
    }

    Json jsonAnnotation = source.getAnnotation(Json.class);
    final Style classStyle = jsonAnnotation != null ? jsonAnnotation.style() : Style.DEFAULT;

    Options classOptions = source.getAnnotation(Options.class);
    Options options = method.getAnnotation(Options.class);

    p(method.getReadableDeclaration(false, false, false, false, true) + " {").i(1);
    {
      String restMethod = getRestMethod(method);
      LinkedList<JParameter> args =
          new LinkedList<JParameter>(Arrays.asList(method.getParameters()));

      // the last arg should be the callback.
      if (args.isEmpty()) {
        error(
            "Invalid rest method. Method must declare at least a callback argument: "
                + method.getReadableDeclaration());
      }
      JParameter callbackArg = args.removeLast();
      JClassType callbackType = callbackArg.getType().isClassOrInterface();
      JClassType methodCallbackType = METHOD_CALLBACK_TYPE;
      if (callbackType == null || !callbackType.isAssignableTo(methodCallbackType)) {
        error(
            "Invalid rest method. Last argument must be a "
                + methodCallbackType.getName()
                + " type: "
                + method.getReadableDeclaration());
      }
      JClassType resultType = getCallbackTypeGenericClass(callbackType);

      String pathExpression = null;
      Path pathAnnotation = method.getAnnotation(Path.class);
      if (pathAnnotation != null) {
        pathExpression = wrap(pathAnnotation.value());
      }

      JParameter contentArg = null;
      HashMap<String, JParameter> queryParams = new HashMap<String, JParameter>();
      HashMap<String, JParameter> headerParams = new HashMap<String, JParameter>();

      for (JParameter arg : args) {
        PathParam paramPath = arg.getAnnotation(PathParam.class);
        if (paramPath != null) {
          if (pathExpression == null) {
            error(
                "Invalid rest method.  Invalid @PathParam annotation. Method is missing the @Path annotation: "
                    + method.getReadableDeclaration());
          }
          pathExpression =
              pathExpression.replaceAll(
                  Pattern.quote("{" + paramPath.value() + "}"),
                  "\"+" + toStringExpression(arg) + "+\"");
          continue;
        }

        QueryParam queryParam = arg.getAnnotation(QueryParam.class);
        if (queryParam != null) {
          queryParams.put(queryParam.value(), arg);
          continue;
        }

        HeaderParam headerParam = arg.getAnnotation(HeaderParam.class);
        if (headerParam != null) {
          headerParams.put(headerParam.value(), arg);
          continue;
        }

        if (contentArg != null) {
          error(
              "Invalid rest method. Only one content parameter is supported: "
                  + method.getReadableDeclaration());
        }
        contentArg = arg;
      }

      String acceptTypeBuiltIn = null;
      if (callbackType.equals(TEXT_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_TEXT";
      } else if (callbackType.equals(JSON_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_JSON";
      } else if (callbackType.isAssignableTo(OVERLAY_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_JSON";
      } else if (callbackType.equals(XML_CALLBACK_TYPE)) {
        acceptTypeBuiltIn = "CONTENT_TYPE_XML";
      }

      p("final " + METHOD_CLASS + " __method =");

      p("this.resource");
      if (pathExpression != null) {
        p(".resolve(" + pathExpression + ")");
      }
      for (Map.Entry<String, JParameter> entry : queryParams.entrySet()) {
        String expr = entry.getValue().getName();
        p(
            ".addQueryParam("
                + wrap(entry.getKey())
                + ", "
                + toStringExpression(entry.getValue().getType(), expr)
                + ")");
      }
      // example: .get()
      p("." + restMethod + "();");

      // Handle JSONP specific configuration...
      JSONP jsonpAnnotation = method.getAnnotation(JSONP.class);
      if (restMethod.equals(METHOD_JSONP) && jsonpAnnotation != null) {
        if (jsonpAnnotation.callbackParam().length() > 0) {
          p(
              "(("
                  + JSONP_METHOD_CLASS
                  + ")__method).callbackParam("
                  + wrap(jsonpAnnotation.callbackParam())
                  + ");");
        }
        if (jsonpAnnotation.failureCallbackParam().length() > 0) {
          p(
              "(("
                  + JSONP_METHOD_CLASS
                  + ")__method).failureCallbackParam("
                  + wrap(jsonpAnnotation.failureCallbackParam())
                  + ");");
        }
      }

      // configure the dispatcher
      if (options != null && options.dispatcher() != Dispatcher.class) {
        // use the dispatcher configured for the method.
        p("__method.setDispatcher(" + options.dispatcher().getName() + ".INSTANCE);");
      } else {
        // use the default dispatcher configured for the service..
        p("__method.setDispatcher(this.dispatcher);");
      }

      // configure the expected statuses..
      if (options != null && options.expect().length != 0) {
        // Using method level defined expected status
        p("__method.expect(" + join(options.expect(), ", ") + ");");
      } else if (classOptions != null && classOptions.expect().length != 0) {
        // Using class level defined expected status
        p("__method.expect(" + join(classOptions.expect(), ", ") + ");");
      }

      // configure the timeout
      if (options != null && options.timeout() >= 0) {
        // Using method level defined value
        p("__method.timeout(" + options.timeout() + ");");
      } else if (classOptions != null && classOptions.timeout() >= 0) {
        // Using class level defined value
        p("__method.timeout(" + classOptions.timeout() + ");");
      }

      Produces producesAnnotation = findAnnotationOnMethodOrEnclosingType(method, Produces.class);
      if (producesAnnotation != null) {
        p(
            "__method.header("
                + RESOURCE_CLASS
                + ".HEADER_ACCEPT, "
                + wrap(producesAnnotation.value()[0])
                + ");");
      } else {
        // set the default accept header....
        if (acceptTypeBuiltIn != null) {
          p(
              "__method.header("
                  + RESOURCE_CLASS
                  + ".HEADER_ACCEPT, "
                  + RESOURCE_CLASS
                  + "."
                  + acceptTypeBuiltIn
                  + ");");
        } else {
          p(
              "__method.header("
                  + RESOURCE_CLASS
                  + ".HEADER_ACCEPT, "
                  + RESOURCE_CLASS
                  + ".CONTENT_TYPE_JSON);");
        }
      }

      Consumes consumesAnnotation = findAnnotationOnMethodOrEnclosingType(method, Consumes.class);
      if (consumesAnnotation != null) {
        p(
            "__method.header("
                + RESOURCE_CLASS
                + ".HEADER_CONTENT_TYPE, "
                + wrap(consumesAnnotation.value()[0])
                + ");");
      }

      // and set the explicit headers now (could override the accept header)
      for (Map.Entry<String, JParameter> entry : headerParams.entrySet()) {
        String expr = entry.getValue().getName();
        p(
            "__method.header("
                + wrap(entry.getKey())
                + ", "
                + toStringExpression(entry.getValue().getType(), expr)
                + ");");
      }

      if (contentArg != null) {
        if (contentArg.getType() == STRING_TYPE) {
          p("__method.text(" + contentArg.getName() + ");");
        } else if (contentArg.getType() == JSON_VALUE_TYPE) {
          p("__method.json(" + contentArg.getName() + ");");
        } else if (contentArg.getType().isClass() != null
            && isOverlayArrayType(contentArg.getType().isClass())) {
          p("__method.json(new " + JSON_ARRAY_CLASS + "(" + contentArg.getName() + "));");
        } else if (contentArg.getType().isClass() != null
            && contentArg.getType().isClass().isAssignableTo(OVERLAY_VALUE_TYPE)) {
          p("__method.json(new " + JSON_OBJECT_CLASS + "(" + contentArg.getName() + "));");
        } else if (contentArg.getType() == DOCUMENT_TYPE) {
          p("__method.xml(" + contentArg.getName() + ");");
        } else {
          JClassType contentClass = contentArg.getType().isClass();
          if (contentClass == null) {
            error("Content argument must be a class.");
          }

          jsonAnnotation = contentArg.getAnnotation(Json.class);
          Style style = jsonAnnotation != null ? jsonAnnotation.style() : classStyle;

          // example:
          // .json(Listings$_Generated_JsonEncoder_$.INSTANCE.encode(arg0)
          // )
          p(
              "__method.json("
                  + locator.encodeExpression(contentClass, contentArg.getName(), style)
                  + ");");
        }
      }

      if (acceptTypeBuiltIn != null) {
        p("__method.send(" + callbackArg.getName() + ");");
      } else {
        p("try {").i(1);
        {
          p("__method.send(new "
                  + ABSTRACT_REQUEST_CALLBACK_CLASS
                  + "<"
                  + resultType.getParameterizedQualifiedSourceName()
                  + ">(__method, "
                  + callbackArg.getName()
                  + ") {")
              .i(1);
          {
            p("protected "
                    + resultType.getParameterizedQualifiedSourceName()
                    + " parseResult() throws Exception {")
                .i(1);
            {
              if (resultType.getParameterizedQualifiedSourceName().equals("java.lang.Void")) {
                p("return (java.lang.Void) new java.lang.Object();");
              } else {
                p("try {").i(1);
                {
                  jsonAnnotation = method.getAnnotation(Json.class);
                  Style style = jsonAnnotation != null ? jsonAnnotation.style() : classStyle;
                  p(
                      "return "
                          + locator.decodeExpression(
                              resultType,
                              JSON_PARSER_CLASS + ".parse(__method.getResponse().getText())",
                              style)
                          + ";");
                }
                i(-1).p("} catch (Throwable __e) {").i(1);
                {
                  p(
                      "throw new "
                          + RESPONSE_FORMAT_EXCEPTION_CLASS
                          + "(\"Response was NOT a valid JSON document\", __e);");
                }
                i(-1).p("}");
              }
            }
            i(-1).p("}");
          }
          i(-1).p("});");
        }
        i(-1).p("} catch (" + REQUEST_EXCEPTION_CLASS + " __e) {").i(1);
        {
          p(callbackArg.getName() + ".onFailure(__method,__e);");
        }
        i(-1).p("}");
      }
    }
    i(-1).p("}");
  }