Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2011 JBoss, by Red Hat, Inc
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
 package org.jboss.errai.enterprise.rebind;
 
 import static org.jboss.errai.enterprise.rebind.TypeMarshaller.demarshal;
 import static org.jboss.errai.enterprise.rebind.TypeMarshaller.marshal;
 
 import java.util.List;
 import java.util.Set;
 
 
 import  org.jboss.errai.codegen.BlockStatement;
 import  org.jboss.errai.codegen.BooleanOperator;
 import  org.jboss.errai.codegen.Cast;
 import  org.jboss.errai.codegen.DefParameters;
 import  org.jboss.errai.codegen.Parameter;
 import  org.jboss.errai.codegen.Statement;
 import  org.jboss.errai.codegen.StringStatement;
 import  org.jboss.errai.codegen.Variable;
 import  org.jboss.errai.codegen.builder.BlockBuilder;
 import  org.jboss.errai.codegen.builder.ClassStructureBuilder;
 import  org.jboss.errai.codegen.builder.ContextualStatementBuilder;
 import  org.jboss.errai.codegen.builder.impl.BooleanExpressionBuilder;
 import  org.jboss.errai.codegen.builder.impl.ObjectBuilder;
 import  org.jboss.errai.codegen.exception.GenerationException;
 import  org.jboss.errai.codegen.meta.MetaClass;
 import  org.jboss.errai.codegen.meta.MetaClassFactory;
 import  org.jboss.errai.codegen.meta.MetaParameterizedType;
 import  org.jboss.errai.codegen.meta.MetaType;
 import  org.jboss.errai.codegen.util.If;
 import  org.jboss.errai.codegen.util.ProxyUtil;
 import  org.jboss.errai.codegen.util.ProxyUtil.InterceptorProvider;
 import  org.jboss.errai.codegen.util.Stmt;
 import  org.jboss.errai.common.client.api.ErrorCallback;
 import  org.jboss.errai.common.client.api.RemoteCallback;
 import  org.jboss.errai.common.client.framework.CallContextStatus;
 
 import  com.google.gwt.core.ext.GeneratorContext;
 import  com.google.gwt.http.client.RequestBuilder;
 import  com.google.gwt.http.client.Response;
 import  com.google.gwt.http.client.URL;

Generates a JAX-RS remote proxy method.

Author(s):
Christian Sadilek <csadilek@redhat.com>
 
 public class JaxrsProxyMethodGenerator {
   private static final String APPEND = "append";
 
   private final MetaClass remote;
   private final MetaClass declaringClass;
   private final JaxrsResourceMethod resourceMethod;
   private final BlockBuilder<?> methodBlock;
   private final List<Statement> parameters;
   private final InterceptorProvider interceptorProvider;
   private final GeneratorContext context;
 
   public JaxrsProxyMethodGenerator(final MetaClass remote
       final ClassStructureBuilder<?> classBuilder
       final JaxrsResourceMethod resourceMethod
       final InterceptorProvider interceptorProvider,
       final GeneratorContext context) {
     
     this. = remote;
     this. = classBuilder.getClassDefinition();
     this. = resourceMethod;
     this. = interceptorProvider;
     this. = context;
     
     Parameter[] parms = DefParameters.from(resourceMethod.getMethod()).getParameters().toArray(new Parameter[0]);
     Parameter[] finalParms = new Parameter[parms.length];
      = new ArrayList<Statement>();
     for (int i = 0; i < parms.length; i++) {
       finalParms[i] = Parameter.of(parms[i].getType(), parms[i].getName(), true);
       .add(Stmt.loadVariable(parms[i].getName()));
     }
     this. = classBuilder.publicMethod(resourceMethod.getMethod().getReturnType(),
        resourceMethod.getMethod().getName(), finalParms);
  }
  public void generate() {
    if (.getHttpMethod() != null) {
      .append(generateUrl(jaxrsParams));
      .append(generateRequestBuilder());
      .append(generateHeaders(jaxrsParams));
      List<Class<?>> interceptors = .getInterceptors(.getMethod());
      if (!interceptors.isEmpty()) {
        .append(generateInterceptorLogic(interceptors));
      }
      else {
        .append(generateRequest());
      }
    }
  }

  
Generates a StringBuilder constructing the request URL based on the method parameters annotated with JAX-RS annotations.

Parameters:
params the resource method's parameters
Returns:
the URL statement
  private Statement generateUrl(final JaxrsResourceMethodParameters params) {
    BlockStatement block = new BlockStatement();
    block.addStatement(Stmt.declareVariable("url"StringBuilder.class,
        Stmt.newObject(StringBuilder.classnew StringStatement("getBaseUrl()"))));
    // construct path using @PathParams and @MatrixParams
    String path = .getPath();
    ContextualStatementBuilder pathValue = Stmt.loadLiteral(path);
    for (String pathParamName : JaxrsResourceMethodParameters.getPathParameterNames(path)) {
      String pathParamId = pathParamName;
      if (pathParamName.contains(":")) {
        pathParamId = pathParamName.split(":")[0];
      }
      Statement pathParam = marshal(params.getPathParameter(pathParamId));
      if (params.needsEncoding(pathParamId)) {
        pathParam = encodePath(pathParam);
      }
      pathValue = pathValue.invoke("replace""{" + pathParamName + "}"pathParam);
    }
    if (params.getMatrixParameters() != null) {
      for (String matrixParamName : params.getMatrixParameters().keySet()) {
        pathValue = pathValue.invoke("concat"";" + matrixParamName + "=")
            .invoke("concat"encodePath(marshal(params.getMatrixParameter(matrixParamName))));
      }
    }
    ContextualStatementBuilder urlBuilder = Stmt.loadVariable("url").invoke(pathValue);
    block.addStatement(urlBuilder);
    // construct query using @QueryParams
    if (params.getQueryParameters() != null) {
      urlBuilder = urlBuilder.invoke("?");
      int i = 0;
      for (String queryParamName : params.getQueryParameters().keySet()) {
        for (Statement queryParam : params.getQueryParameters(queryParamName)) {
          MetaClass queryParamType = queryParam.getType();
          if (isListOrSet(queryParamType)) {
            MetaClass paramType = assertValidCollectionParam(queryParamTypequeryParamNameQueryParam.class);
            ContextualStatementBuilder listParam = (queryParam instanceof Parameter) ?
                Stmt.loadVariable(((Parameter) queryParam).getName()) : Stmt.nestedCall(queryParam);
            block.addStatement(listParam.foreach("p")
                .append(If.not(Stmt.loadVariable("url").invoke("toString").invoke("endsWith""?"))
                    .append(Stmt.loadVariable("url").invoke("&")).finish())
                .append(Stmt.loadVariable("url").invoke(queryParamName).invoke("=")
                    .invoke(encodeQuery(marshal(paramType, Stmt.loadVariable("p")))))
                .finish()
                );
          }
          else {
            if (i++ > 0) {
              urlBuilder = urlBuilder.invoke("&");
            }
            urlBuilder = urlBuilder.invoke(queryParamName).invoke("=")
                .invoke(encodeQuery(marshal(queryParam)));
          }
        }
      }
    }
    return block;
  }

  
Checks if the provided type is a List or Set.

Parameters:
paramType the type to check
Returns:
true if the type can be assigned to a List or Set, otherwise false.
  private boolean isListOrSet(MetaClass paramType) {
    return paramType.isAssignableTo(List.class) || paramType.isAssignableTo(Set.class);
  }

  
Asserts that the provided type is a valid collection type for JAX-RS resource parameters.

Parameters:
paramType the provided type.
paramName the name of the resource parameter for error reporting.
jaxrsParamType the JAX-RS resource parameter type for error reporting.
Returns:
the element type.
Throws:
GenerationException if the type parameters of the collection type are invalid for JAX-RS resource parameters.
  private MetaClass assertValidCollectionParam(MetaClass paramTypeString paramNameClass<?> jaxrsParamType) {
    MetaParameterizedType queryParamPType = paramType.getParameterizedType();
    MetaType[] typeParams = (queryParamPType != null) ? queryParamPType.getTypeParameters() : null;
    if (typeParams != null && typeParams.length == 1 && typeParams[0] instanceof MetaClass
          && PrimitiveTypeMarshaller.canHandle((MetaClass) typeParams[0], "text/plain")) {
      return (MetaClass) typeParams[0];
    }
    else {
      throw new GenerationException(
            "Unsupported type parameter found on " + jaxrsParamType.getSimpleName() + " with name "
                + paramName + " in method " + .getMethod() +
                " (check the JavaDocs of " + jaxrsParamType.getName() + " for details!)");
    }
  }

  
Generates the declaration for a new RequestBuilder instance, initialized with the generated URL generateUrl(JaxrsResourceMethodParameters)

Returns:
the RequestBuilder statement
  private Statement generateRequestBuilder() {
    Statement requestBuilder =
        Stmt.declareVariable("requestBuilder", RequestBuilder.class,
            Stmt.newObject(RequestBuilder.class)
                .withParameters(.getHttpMethod(), Stmt.loadVariable("url").invoke("toString")));
    return requestBuilder;
  }

  
Generates calls to set the appropriate headers on the generated RequestBuilder (see generateRequestBuilder()) based on the method parameters annotated with JAX-RS annotations.

Parameters:
params the resource method's parameters
Returns:
a block statement with the corresponding calls to RequestBuilder.setHeader(String, String)
  private Statement generateHeaders(final JaxrsResourceMethodParameters params) {
    BlockStatement block = new BlockStatement();
    // set headers based on method and class
    for (String key : .getHeaders().keySet()) {
      block.addStatement(Stmt.loadVariable("requestBuilder").invoke("setHeader"key,
          .getHeaders().get(key)));
    }
    // set headers based on @HeaderParams
    if (params.getHeaderParameters() != null) {
      for (String headerParamName : params.getHeaderParameters().keySet()) {
        ContextualStatementBuilder headerValueBuilder = Stmt.nestedCall(Stmt.newObject(StringBuilder.class));
        int i = 0;
        for (Statement headerParam : params.getHeaderParameters(headerParamName)) {
          if (i++ > 0) {
            headerValueBuilder = headerValueBuilder.invoke(",");
          }
          headerValueBuilder = headerValueBuilder.invoke(marshal(headerParam));
        }
        block.addStatement(Stmt.loadVariable("requestBuilder").invoke("setHeader"headerParamName,
            headerValueBuilder.invoke("toString")));
      }
    }
    // set cookies based on @CookieParams
    if (params.getCookieParameters() != null) {
      for (String cookieName : params.getCookieParameters().keySet()) {
        Statement cookieParam = params.getCookieParameters().get(cookieName).get(0);
        ContextualStatementBuilder setCookie = (cookieParam instanceof Parameter) ?
            Stmt.loadVariable(((Parameter) cookieParam).getName()) :
              Stmt.nestedCall(cookieParam);
        setCookie.if_(BooleanOperator.NotEquals, null)
            .append(Stmt.invokeStatic(RestClient.class"setCookie"cookieNamemarshal(cookieParam)))
            .finish();
        block.addStatement(setCookie);
      }
    }
    return block.isEmpty() ? null : block;
  }

  
Generates the logic required to make this proxy method interceptable.

Parameters:
interceptors
Returns:
statement representing the interceptor logic.
  private Statement generateInterceptorLogic(List<Class<?>> interceptors) {
    JaxrsResourceMethodParameters jaxrsParams =
        JaxrsResourceMethodParameters.fromMethod(.getMethod(), "parameters");
    
    Statement callContext =
        ProxyUtil.generateProxyMethodCallContext(RestCallContext.class,
            .getMethod(), generateInterceptedRequest(), interceptors)
            .publicOverridesMethod("proceed", Parameter.of(ResponseCallback.class"interceptorCallback"true))
              .append(Stmt.declareVariable(RemoteCallback.class).asFinal().named("providedCallback").initializeWith(
                  Stmt.loadStatic("this").loadField("remoteCallback")))
              .append(
                  Stmt.loadVariable("remoteCallback").assignValue(Stmt.newObject(ResponseCallback.class).extend()
                      .publicOverridesMethod("callback", Parameter.of(Response.class"response"))
                      .append(Stmt.declareVariable(ResponseCallback.class).named("intCallback")
                          .initializeWith(Stmt.loadVariable("interceptorCallback")))
                      .append(StringStatement.of("setResult(response)"))
                      .append(Stmt.loadVariable("intCallback").invoke("callback",
                          Cast.to(Response.class, StringStatement.of("getResult()"Object.class))))
                      .append(Stmt.loadVariable("providedCallback").invoke("callback",
                          StringStatement.of("getResult()"Object.class)))
                      .finish()
                      .finish())
              )
              .append(Stmt.loadVariable("this").invoke("proceed"))
            .finish()
            .publicOverridesMethod("proceed", Parameter.of(ResponseCallback.class"interceptorCallback"true), 
                    Parameter.of(ErrorCallback.class"interceptorErrorCallback"true))
              .append(
                  Stmt.declareVariable(ErrorCallback.class).asFinal().named("providedErrorCallback").initializeWith(
                      Stmt.loadStatic("this").loadField("errorCallback")))
              .append(
                  Stmt.loadVariable("errorCallback").assignValue(Stmt.newObject(ErrorCallback.class).extend()
                      .publicOverridesMethod("error", Parameter.of(Object.class"message"),
                          Parameter.of(Throwable.class"throwable"))
                      .append(
                          Stmt.loadVariable("interceptorErrorCallback").invoke("error", Variable.get("message"),
                              Variable.get("throwable")))
                      .append(
                          Stmt.if_(
                              BooleanExpressionBuilder.create(
                                 StringStatement.of("getResult()"Object.class), BooleanOperator.NotEquals, Stmt
                                      .loadLiteral(null)))
                              .append(
                                  Stmt.loadVariable("remoteCallback").invoke("callback",
                                          StringStatement.of("getResult()"Object.class)))
                              .append(Stmt.load(false).returnValue())
                              .finish()
                          .elseif_(
                              BooleanExpressionBuilder.create(
                                  Stmt.loadVariable("providedErrorCallback"), BooleanOperator.NotEquals, Stmt
                                      .loadLiteral(null)))
                              .append(
                                  Stmt.nestedCall(
                                    Stmt.loadVariable("providedErrorCallback").invoke("error",
                                      Variable.get("message"),
                                      Variable.get("throwable")))
                                  .returnValue())
                              .finish())
                      .append(Stmt.load(true).returnValue())
                      .finish()
                      .finish())
              )
              .append(Stmt.loadVariable("this").invoke("proceed", Variable.get("interceptorCallback")))
            .finish()
            .publicOverridesMethod("setParameters", Parameter.of(Object[].class"parameters"))
              .append(new StringStatement("super.setParameters(parameters)"))
              .append(generateUrl(jaxrsParams))
              .append(generateRequestBuilder())
              .append(generateHeaders(jaxrsParams))
              .append(new StringStatement("setRequestBuilder(requestBuilder)"))
            .finish()
            .finish();
    return Stmt.try_()
            .append(
                Stmt.declareVariable(CallContextStatus.class).asFinal().named("status").initializeWith(
                    Stmt.newObject(CallContextStatus.class).withParameters(interceptors.toArray())))
            .append(
                Stmt.declareVariable(RestCallContext.class).asFinal().named("callContext")
                    .initializeWith(callContext))
            .append(
                Stmt.loadVariable("callContext").invoke("setRequestBuilder", Variable.get("requestBuilder")))
            .append(
                Stmt.loadVariable("callContext").invoke("setParameters",
                    Stmt.newArray(Object.class).initialize(.toArray())))
            .append(
                Stmt.loadVariable("callContext").invoke("proceed"))
            .finish()
            .catch_(Throwable.class"throwable")
            .append(
                Stmt.loadStatic("this").invoke("handleError", Variable.get("throwable"), nullnull))
            .finish();
  }

  
Generates the call to RequestBuilder.sendRequest(String, com.google.gwt.http.client.RequestCallback) for interceptable methods.

Returns:
statement representing the request
  private Statement generateInterceptedRequest() {
    return generateRequest(
            Stmt.nestedCall(new StringStatement("getRequestBuilder()", MetaClassFactory.get(RequestBuilder.class))),
            Stmt.loadStatic("this"));
  }

  
Generates the call to RequestBuilder.sendRequest(String, com.google.gwt.http.client.RequestCallback) for non-interceptable methods.

Returns:
statement representing the request
  private Statement generateRequest() {
    return generateRequest(Stmt.loadVariable("requestBuilder"), Stmt.loadVariable("this"));
  }

  
Generates the call to RequestBuilder.sendRequest(String, com.google.gwt.http.client.RequestCallback) for proxy methods.

Returns:
statement representing the request
  private Statement generateRequest(final ContextualStatementBuilder requestBuilder
          final ContextualStatementBuilder proxy) {
    
    Statement sendRequest = null;
    if (.getParameters().getEntityParameter() == null) {
      sendRequest = proxy.invoke("sendRequest"requestBuildernullresponseDemarshallingCallback());
    }
    else {
      Statement body = marshal(.getParameters().getEntityParameter(),
          .getContentTypeHeader());
      sendRequest = proxy.invoke("sendRequest"requestBuilderbodyresponseDemarshallingCallback());
    }
    return sendRequest;
  }

  
Generates an anonymous implementation/instance of ResponseDemarshallingCallback that will handle the demarshalling of the HTTP response.

Returns:
statement representing the ResponseDemarshallingCallback.
  private Statement responseDemarshallingCallback() {
    Statement result = Stmt.load(null);
    if (!.getMethod().getReturnType().equals(MetaClassFactory.get(void.class))) {
      result = demarshal(
          .getMethod().getReturnType(),
          Stmt.loadVariable("response"),
          .getAcceptHeader());
    }
    return ObjectBuilder
        .newInstanceOf(ResponseDemarshallingCallback.class)
        .extend()
        .publicOverridesMethod("demarshallResponse", Parameter.of(String.class"response"))
        .append(Stmt.nestedCall(result).returnValue())
        .finish()
        .finish();
  }

  
Adds path encoding to the provided statement

Parameters:
s the statement representing an HTTP path that should be encoded
Returns:
statement with path encoding
  private Statement encodePath(Statement s) {
    return Stmt.invokeStatic(URL.class"encodePathSegment"s);
  }

  
Adds query parameter encoding to the provided statement

Parameters:
s the statement representing an HTTP query that should be encoded
Returns:
statement with query param encoding
  private Statement encodeQuery(Statement s) {
    return Stmt.invokeStatic(URL.class"encodeQueryString"s);
  }

  
Generates the return statement of this proxy method if required. If the proxy method returns void, it will just finish the method block.
  private void generateReturnStatement() {
    Statement returnStatement = ProxyUtil.generateProxyMethodReturnStatement(.getMethod());
    if (returnStatement != null) {
      .append(returnStatement);
    }
    .finish();
  }
New to GrepCode? Check out our FAQ X