예제 #1
0
  @Override
  public void parse(ApiDefinition api, OperationDefinition operation, Method method) {
    HttpMethod httpMethod = getHttpMethod(method);
    if (httpMethod != null) {
      operation.setHttpMethod(httpMethod.value());
    }

    Path path = AnnotationUtils.findAnnotation(method, Path.class);
    String methodPath = null;
    if (path != null) {
      methodPath = path.value();
    }
    operation.setPath(buildFullPath(api.getPath(), methodPath));

    Consumes consumes = AnnotationUtils.findAnnotation(method, Consumes.class);
    if (consumes != null) {
      for (String consume : consumes.value()) {
        if (operation.getConsumes() == null) {
          operation.setConsumes(new ArrayList<String>());
        }
        operation.getConsumes().add(consume);
      }
    }

    Produces produces = AnnotationUtils.findAnnotation(method, Produces.class);
    if (produces != null) {
      for (String produce : produces.value()) {
        if (operation.getProduces() == null) {
          operation.setProduces(new ArrayList<String>());
        }
        operation.getProduces().add(produce);
      }
    }
  }
예제 #2
0
  protected static void processMethod(
      ResourceClassBuilder resourceClassBuilder, Class<?> root, Method implementation) {
    Method method = findAnnotatedMethod(root, implementation);
    if (method != null) {
      Path path = method.getAnnotation(Path.class);
      Set<String> httpMethods = IsHttpMethod.getHttpMethods(method);

      ResteasyUriBuilder builder = new ResteasyUriBuilder();
      if (root.isAnnotationPresent(Path.class)) {
        builder.path(root);
      }
      if (path != null) {
        builder.path(method);
      }
      String pathExpression = builder.getPath();
      if (pathExpression == null) pathExpression = "";

      ResourceLocatorBuilder resourceLocatorBuilder;

      if (httpMethods == null) {
        resourceLocatorBuilder = resourceClassBuilder.locator(implementation, method);
      } else {
        ResourceMethodBuilder resourceMethodBuilder =
            resourceClassBuilder.method(implementation, method);
        resourceLocatorBuilder = resourceMethodBuilder;

        for (String httpMethod : httpMethods) {
          if (httpMethod.equalsIgnoreCase(HttpMethod.GET)) resourceMethodBuilder.get();
          else if (httpMethod.equalsIgnoreCase(HttpMethod.PUT)) resourceMethodBuilder.put();
          else if (httpMethod.equalsIgnoreCase(HttpMethod.POST)) resourceMethodBuilder.post();
          else if (httpMethod.equalsIgnoreCase(HttpMethod.DELETE)) resourceMethodBuilder.delete();
          else if (httpMethod.equalsIgnoreCase(HttpMethod.OPTIONS)) resourceMethodBuilder.options();
          else if (httpMethod.equalsIgnoreCase(HttpMethod.HEAD)) resourceMethodBuilder.head();
          else resourceMethodBuilder.httpMethod(httpMethod);
        }
        Produces produces = method.getAnnotation(Produces.class);
        if (produces == null)
          produces = resourceClassBuilder.resourceClass.getClazz().getAnnotation(Produces.class);
        if (produces == null) produces = method.getDeclaringClass().getAnnotation(Produces.class);
        if (produces != null) resourceMethodBuilder.produces(produces.value());

        Consumes consumes = method.getAnnotation(Consumes.class);
        if (consumes == null)
          consumes = resourceClassBuilder.resourceClass.getClazz().getAnnotation(Consumes.class);
        if (consumes == null) consumes = method.getDeclaringClass().getAnnotation(Consumes.class);
        if (consumes != null) resourceMethodBuilder.consumes(consumes.value());
      }
      resourceLocatorBuilder.path(pathExpression);
      for (int i = 0; i < resourceLocatorBuilder.locator.params.length; i++) {
        resourceLocatorBuilder.param(i).fromAnnotations();
      }
      resourceLocatorBuilder.buildMethod();
    }
  }
  private static List<String> parseProduces(Method m) {
    // 读取@Produces注解
    Produces producesAnn = m.getAnnotation(Produces.class);
    List<String> pcbs = null;
    if (producesAnn != null) {
      pcbs = new ArrayList<String>();
      String producesStr = CommonUtil.parsePropValue(producesAnn.value()[0]);
      pcbs.add(producesStr);
    }

    return pcbs;
  }
예제 #4
0
  /**
   * Generates HTTP headers based on the JAX-RS annotations on the provided method.
   *
   * @param clazz the JAX-RS resource class
   * @return headers
   */
  public static JaxrsHeaders fromMethod(MetaMethod method) {
    JaxrsHeaders headers = new JaxrsHeaders();

    Produces p = method.getAnnotation(Produces.class);
    if (p != null) {
      headers.setAcceptHeader(p.value());
    }

    Consumes c = method.getAnnotation(Consumes.class);
    if (c != null) {
      headers.setContentTypeHeader(c.value());
    }

    return headers;
  }
예제 #5
0
 private MediaType checkFinalContentType(
     MediaType mt, List<WriterInterceptor> writers, boolean checkWriters) {
   if (checkWriters) {
     int mbwIndex = writers.size() == 1 ? 0 : writers.size() - 1;
     MessageBodyWriter<Object> writer = ((WriterInterceptorMBW) writers.get(mbwIndex)).getMBW();
     Produces pm = writer.getClass().getAnnotation(Produces.class);
     if (pm != null) {
       List<MediaType> sorted =
           JAXRSUtils.sortMediaTypes(
               JAXRSUtils.getMediaTypes(pm.value()), JAXRSUtils.MEDIA_TYPE_QS_PARAM);
       mt = JAXRSUtils.intersectMimeTypes(sorted, mt).get(0);
     }
   }
   if (mt.isWildcardType() || mt.isWildcardSubtype()) {
     if ("application".equals(mt.getType()) || mt.isWildcardType()) {
       mt = MediaType.APPLICATION_OCTET_STREAM_TYPE;
     } else {
       throw ExceptionUtils.toNotAcceptableException(null, null);
     }
   }
   return mt;
 }
예제 #6
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("}");
  }
예제 #7
0
  public ResourceMethod(
      Class<?> clazz,
      Method method,
      InjectorFactory injector,
      ResourceFactory resource,
      ResteasyProviderFactory providerFactory,
      Set<String> httpMethods) {
    this.injector = injector;
    this.resource = resource;
    this.parentProviderFactory = providerFactory;
    this.httpMethods = httpMethods;
    this.resourceClass = clazz;
    this.method = method;

    resourceInfo =
        new ResourceInfo() {
          @Override
          public Method getResourceMethod() {
            return ResourceMethod.this.method;
          }

          @Override
          public Class<?> getResourceClass() {
            return ResourceMethod.this.resourceClass;
          }
        };

    this.resourceMethodProviderFactory = new ResteasyProviderFactory(providerFactory);
    for (DynamicFeature feature : providerFactory.getServerDynamicFeatures()) {
      feature.configure(resourceInfo, new FeatureContextDelegate(resourceMethodProviderFactory));
    }

    this.methodInjector =
        injector.createMethodInjector(clazz, method, resourceMethodProviderFactory);

    Produces p = method.getAnnotation(Produces.class);
    if (p == null) p = clazz.getAnnotation(Produces.class);
    if (p == null) p = method.getDeclaringClass().getAnnotation(Produces.class);
    Consumes c = methodConsumes = method.getAnnotation(Consumes.class);
    if (c == null) c = clazz.getAnnotation(Consumes.class);
    if (c == null) c = method.getDeclaringClass().getAnnotation(Consumes.class);

    if (p != null) {
      produces = new MediaType[p.value().length];
      int i = 0;
      for (String mediaType : p.value()) {
        produces[i++] = MediaType.valueOf(mediaType);
        preferredProduces.add(WeightedMediaType.valueOf(mediaType));
      }
    }
    if (c != null) {
      consumes = new MediaType[c.value().length];
      int i = 0;
      for (String mediaType : c.value()) {
        consumes[i++] = MediaType.valueOf(mediaType);
        preferredConsumes.add(WeightedMediaType.valueOf(mediaType));
      }
    }
    Collections.sort(preferredProduces);
    Collections.sort(preferredConsumes);

    requestFilters =
        resourceMethodProviderFactory
            .getContainerRequestFilterRegistry()
            .postMatch(resourceClass, method);
    responseFilters =
        resourceMethodProviderFactory
            .getContainerResponseFilterRegistry()
            .postMatch(resourceClass, method);
    writerInterceptors =
        resourceMethodProviderFactory
            .getServerWriterInterceptorRegistry()
            .postMatch(resourceClass, method);

    // we register with parent to lisen for redeploy evens
    providerFactory.getContainerRequestFilterRegistry().getListeners().add(this);
    providerFactory.getContainerResponseFilterRegistry().getListeners().add(this);
    providerFactory.getServerWriterInterceptorRegistry().getListeners().add(this);
    /*
       We get the genericReturnType for the case of:

       interface Foo<T> {
          @GET
          List<T> get();
       }

       public class FooImpl implements Foo<Customer> {
           public List<Customer> get() {...}
       }
    */
    genericReturnType = Types.getGenericReturnTypeOfGenericInterfaceMethod(clazz, method);
    ContextResolver<GeneralValidator> resolver =
        providerFactory.getContextResolver(GeneralValidator.class, MediaType.WILDCARD_TYPE);
    if (resolver != null) {
      validator =
          providerFactory
              .getContextResolver(GeneralValidator.class, MediaType.WILDCARD_TYPE)
              .getContext(null);
    }
  }
예제 #8
0
 private static List<String> getValues(Produces ann) {
   return (ann != null) ? Arrays.asList(ann.value()) : null;
 }
예제 #9
0
 /**
  * Extracts the value for a {@link Produces} annotation, splitting any media types that are
  * combined using , (see the JAX-RS javadoc)
  */
 public static List<String> value(Produces produces) {
   return splitMediaTypes(produces.value());
 }
예제 #10
0
  @Override
  @SuppressWarnings("unchecked")
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // get the interface describing the resource
    Class<?> proxyIfc = proxy.getClass().getInterfaces()[0];

    // response type
    Class<?> responseType = method.getReturnType();

    // determine method name
    String httpMethod = getHttpMethodName(method);
    if (httpMethod == null) {
      for (Annotation ann : method.getAnnotations()) {
        httpMethod = getHttpMethodName(ann.annotationType());
        if (httpMethod != null) {
          break;
        }
      }
    }

    // create a new UriBuilder appending the @Path attached to the method
    WebTarget newTarget = addPathFromAnnotation(method, target);

    if (httpMethod == null) {
      if (newTarget == target) {
        // no path annotation on the method -> fail
        throw new UnsupportedOperationException("Not a resource method.");
      } else if (!responseType.isInterface()) {
        // the method is a subresource locator, but returns class,
        // not interface - can't help here
        throw new UnsupportedOperationException("Return type not an interface");
      }
    }

    // process method params (build maps of (Path|Form|Cookie|Matrix|Header..)Params
    // and extract entity type
    MultivaluedHashMap<String, Object> headers =
        new MultivaluedHashMap<String, Object>(this.headers);
    LinkedList<Cookie> cookies = new LinkedList<Cookie>(this.cookies);
    Form form = new Form();
    form.asMap().putAll(this.form.asMap());
    Annotation[][] paramAnns = method.getParameterAnnotations();
    Object entity = null;
    Type entityType = null;
    for (int i = 0; i < paramAnns.length; i++) {
      Map<Class, Annotation> anns = new HashMap<Class, Annotation>();
      for (Annotation ann : paramAnns[i]) {
        anns.put(ann.annotationType(), ann);
      }
      Annotation ann;
      Object value = args[i];
      if (anns.isEmpty()) {
        entityType = method.getGenericParameterTypes()[i];
        entity = value;
      } else {
        if (value == null && (ann = anns.get(DefaultValue.class)) != null) {
          value = ((DefaultValue) ann).value();
        }

        if (value != null) {
          if ((ann = anns.get(PathParam.class)) != null) {
            newTarget = newTarget.resolveTemplate(((PathParam) ann).value(), value);
          } else if ((ann = anns.get((QueryParam.class))) != null) {
            if (value instanceof Collection) {
              newTarget =
                  newTarget.queryParam(((QueryParam) ann).value(), convert((Collection) value));
            } else {
              newTarget = newTarget.queryParam(((QueryParam) ann).value(), value);
            }
          } else if ((ann = anns.get((HeaderParam.class))) != null) {
            if (value instanceof Collection) {
              headers.addAll(((HeaderParam) ann).value(), convert((Collection) value));
            } else {
              headers.addAll(((HeaderParam) ann).value(), value);
            }

          } else if ((ann = anns.get((CookieParam.class))) != null) {
            String name = ((CookieParam) ann).value();
            Cookie c;
            if (value instanceof Collection) {
              for (Object v : ((Collection) value)) {
                if (!(v instanceof Cookie)) {
                  c = new Cookie(name, v.toString());
                } else {
                  c = (Cookie) v;
                  if (!name.equals(((Cookie) v).getName())) {
                    // is this the right thing to do? or should I fail? or ignore the difference?
                    c = new Cookie(name, c.getValue(), c.getPath(), c.getDomain(), c.getVersion());
                  }
                }
                cookies.add(c);
              }
            } else {
              if (!(value instanceof Cookie)) {
                cookies.add(new Cookie(name, value.toString()));
              } else {
                c = (Cookie) value;
                if (!name.equals(((Cookie) value).getName())) {
                  // is this the right thing to do? or should I fail? or ignore the difference?
                  cookies.add(
                      new Cookie(name, c.getValue(), c.getPath(), c.getDomain(), c.getVersion()));
                }
              }
            }
          } else if ((ann = anns.get((MatrixParam.class))) != null) {
            if (value instanceof Collection) {
              newTarget =
                  newTarget.matrixParam(((MatrixParam) ann).value(), convert((Collection) value));
            } else {
              newTarget = newTarget.matrixParam(((MatrixParam) ann).value(), value);
            }
          } else if ((ann = anns.get((FormParam.class))) != null) {
            if (value instanceof Collection) {
              for (Object v : ((Collection) value)) {
                form.param(((FormParam) ann).value(), v.toString());
              }
            } else {
              form.param(((FormParam) ann).value(), value.toString());
            }
          }
        }
      }
    }

    if (httpMethod == null) {
      // the method is a subresource locator
      return WebResourceFactory.newResource(responseType, newTarget, true, headers, cookies, form);
    }

    // accepted media types
    Produces produces = method.getAnnotation(Produces.class);
    if (produces == null) {
      produces = proxyIfc.getAnnotation(Produces.class);
    }
    String[] accepts = produces == null ? null : produces.value();

    // determine content type
    String contentType = null;
    if (entity != null) {
      Consumes consumes = method.getAnnotation(Consumes.class);
      if (consumes == null) {
        consumes = proxyIfc.getAnnotation(Consumes.class);
      }
      if (consumes != null && consumes.value().length > 0) {
        // TODO: should consider q/qs instead of picking the first one
        contentType = consumes.value()[0];
      }
    }

    Invocation.Builder builder;
    if (accepts != null) {
      builder = newTarget.request(accepts);
    } else {
      builder = newTarget.request();
    }

    // apply header params and cookies
    builder.headers(headers);

    for (Cookie c : cookies) {
      builder = builder.cookie(c);
    }

    Object result;

    if (entity == null && !form.asMap().isEmpty()) {
      entity = form;
      contentType = MediaType.APPLICATION_FORM_URLENCODED;
    } else {
      if (contentType == null) {
        contentType = MediaType.APPLICATION_OCTET_STREAM;
      }
      if (!form.asMap().isEmpty()) {
        if (entity instanceof Form) {
          ((Form) entity).asMap().putAll(form.asMap());
        } else {
          // TODO: should at least log some warning here
        }
      }
    }

    GenericType responseGenericType = new GenericType(method.getGenericReturnType());
    if (entity != null) {
      if (entityType instanceof ParameterizedType) {
        entity = new GenericEntity(entity, entityType);
      }
      result = builder.method(httpMethod, Entity.entity(entity, contentType), responseGenericType);
    } else {
      result = builder.method(httpMethod, responseGenericType);
    }

    return result;
  }
예제 #11
0
 private static List<MediaType> extractMediaTypes(final Produces annotation) {
   return (annotation != null)
       ? extractMediaTypes(annotation.value())
       : Collections.<MediaType>emptyList();
 }
예제 #12
0
 private String[] producedMediaTypesIfAvailable(Produces producedMediaTypes) {
   return producedMediaTypes != null ? producedMediaTypes.value() : new String[] {};
 }
예제 #13
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("}");
  }
예제 #14
0
 public static ContainerException badMethodProduces(
     Exception e, Class resourceClass, Method m, Produces p) {
   return new ContainerException(
       ImplMessages.BAD_METHOD_PRODUCEMIME(resourceClass, p.value(), m.toString()), e);
 }
예제 #15
0
 public static ContainerException badClassProduces(Exception e, Class resourceClass, Produces p) {
   return new ContainerException(ImplMessages.BAD_CLASS_PRODUCEMIME(resourceClass, p.value()), e);
 }
  private void handleResult() throws Exception {

    this.exeActionLog();

    if (retn == null) return;
    String baseUrl =
        (String) this.context.getServletContext().getAttribute(MVCConfigConstant.BASE_URL_KEY);
    if (File.class.isAssignableFrom(retn.getClass())) {
      File file = (File) retn;
      this.handleDownload(file);
      return;
    } else if (File[].class.isAssignableFrom(retn.getClass())) {
      File[] files = (File[]) retn;

      String fileName = CommonUtil.getNowTime("yyyyMMddHHmmss") + "_" + "download.zip";

      HttpServletResponse resp = this.context.getResponse();
      resp.reset();
      resp.setContentType("application/zip");
      resp.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

      ServletOutputStream outputStream = resp.getOutputStream();
      ZipOutputStream zip = new ZipOutputStream(outputStream);

      for (File file : files) {
        byte[] b = new byte[1024];
        int len;
        zip.putNextEntry(new ZipEntry(file.getName()));
        FileInputStream fis = new FileInputStream(file);
        while ((len = fis.read(b)) != -1) {
          zip.write(b, 0, len);
        }

        fis.close();
      }

      zip.flush();
      zip.close();
      outputStream.flush();

      return;
    }

    if (!String.class.isAssignableFrom(retn.getClass())) {
      String mimeType = null;
      Produces prod = this.method.getAnnotation(Produces.class);
      if (prod != null && prod.value() != null && prod.value().length > 0)
        mimeType = prod.value()[0];

      if (mimeType == null || mimeType.trim().length() == 0)
        mimeType =
            this.context.getRequest().getParameter(MVCConfigConstant.HTTP_HEADER_ACCEPT_PARAM);

      if (mimeType == null || mimeType.trim().length() == 0) {
        String contentType = this.context.getRequest().getContentType();
        if (contentType != null) {
          this.context.getResponse().setContentType(contentType);
          mimeType = contentType.split(";")[0];
        }
      }

      if (this.context.getWriter() == null)
        this.context.setWriter(this.context.getResponse().getWriter());

      if (MIMEType.JSON.equals(mimeType) || "json".equalsIgnoreCase(mimeType)) {
        this.context.getResponse().setContentType(MIMEType.JSON);
        this.context.getWriter().print(CommonUtil.toJson(retn));
      } else if (MIMEType.XML.equals(mimeType) || "xml".equalsIgnoreCase(mimeType)) {
        Class<?> cls = retn.getClass();
        if (Collection.class.isAssignableFrom(cls)) {
          Class<?> _cls = ClassUtil.getPojoClass(this.method);
          if (_cls != null) cls = _cls;
        }

        XMLWriter writer = BeanXMLUtil.getBeanXMLWriter(retn);
        writer.setCheckStatck(true);
        writer.setSubNameAuto(true);
        writer.setClass(cls);
        writer.setRootElementName(null);
        this.context.getResponse().setContentType(MIMEType.XML);
        this.context.getWriter().print(writer.toXml());
      } else {
        this.context.getWriter().print("暂时不支持JSON 、XML以外的表述形式");
      }

      this.context.getWriter().flush();

      return;
    }

    List<String> produces = this.context.getActionConfigBean().getProduces();
    if (produces != null && produces.size() > 0)
      for (String produce : produces) {
        this.context.getResponse().setContentType(produce);
        break;
      }

    String re = String.valueOf(retn);

    for (Field f : fields) {
      Method getter = ru.getGetter(f.getName());
      if (getter == null) continue;

      String name = f.getName();
      if (this.context.getModel().containsKey(name)) continue;

      this.context.getModel().put(name, getter.invoke(actionObject));
    }

    this.context.getModel().put(MVCConfigConstant.BASE_URL_KEY, baseUrl);

    // 客户端重定向
    if (re.startsWith(RenderType.REDIRECT + ":")) {
      String url = re.substring((RenderType.REDIRECT + ":").length());
      String location = url;

      this.context.getResponse().sendRedirect(CommonUtil.replaceChinese2Utf8(location));

      return;
    } else if (re.startsWith(RenderType.ACTION + ":")) {
      String path = re.substring((RenderType.ACTION + ":").length());
      // ACTION 重定向
      handleActionRedirect(context, path, baseUrl);

      return;
    } else if (re.startsWith(RenderType.OUT + ":")) {
      String location = re.substring((RenderType.OUT + ":").length());
      this.context.getWriter().print(location);
      this.context.getWriter().flush();

      return;
    } else if (re.startsWith(RenderType.FORWARD + ":")) {
      String location = re.substring((RenderType.FORWARD + ":").length());
      HttpServletRequest request = this.context.getRequest();
      request.setAttribute(MVCConfigConstant.REQ_PARAM_MAP_NAME, this.context.getQueryParamMap());

      for (Iterator<Entry<String, Object>> it = this.context.getModel().entrySet().iterator();
          it.hasNext(); ) {
        Entry<String, Object> entry = it.next();
        request.setAttribute(entry.getKey(), entry.getValue());
      }

      // 服务端跳转
      request
          .getRequestDispatcher(MVCConfigConstant.FORWARD_BASE_PATH + "/" + location)
          .forward(request, this.context.getResponse());

      return;
    } else if (re.startsWith(RenderType.FREEMARKER + ":")) {
      String location = re.substring((RenderType.FREEMARKER + ":").length());
      // FreeMarker 渲染
      Configuration cfg = new Configuration();
      // 指定模板从何处加载的数据源,这里设置成一个文件目录。
      cfg.setDirectoryForTemplateLoading(
          new File(ConfigConstant.ROOT_PATH + MVCConfigConstant.FORWARD_BASE_PATH));
      // 指定模板如何检索数据模型
      cfg.setObjectWrapper(new DefaultObjectWrapper());
      cfg.setDefaultEncoding("utf-8");

      Template template = cfg.getTemplate(location);
      template.setEncoding("utf-8");

      template.process(this.context.getModel(), this.context.getWriter());

      return;
    } else if (re.startsWith(RenderType.VELOCITY + ":")) {
      String location = re.substring((RenderType.VELOCITY + ":").length());
      File viewsDir = new File(ConfigConstant.ROOT_PATH + MVCConfigConstant.FORWARD_BASE_PATH);
      // 初始化Velocity模板引擎
      Properties p = new Properties();
      p.setProperty("resource.loader", "file");
      p.setProperty(
          "file.resource.loader.class",
          "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
      p.setProperty("file.resource.loader.path", viewsDir.getAbsolutePath());
      p.setProperty("file.resource.loader.cache", "true");
      p.setProperty("file.resource.loader.modificationCheckInterval", "2");
      p.setProperty("input.encoding", "utf-8");
      p.setProperty("output.encoding", "utf-8");
      VelocityEngine ve = new VelocityEngine(p);
      // Velocity获取模板文件,得到模板引用
      org.apache.velocity.Template t = ve.getTemplate(location);
      VelocityContext velocityCtx = new VelocityContext();
      for (Iterator<Entry<String, Object>> it = this.context.getModel().entrySet().iterator();
          it.hasNext(); ) {
        Entry<String, Object> e = it.next();
        velocityCtx.put(e.getKey(), e.getValue());
      }

      // 将环境变量和输出部分结合
      t.merge(velocityCtx, this.context.getWriter());
      this.context.getWriter().flush();
      return;
    } else {
      List<ResultConfigBean> results = this.context.getActionConfigBean().getResult();

      if (results == null || results.size() == 0) {
        this.context.getWriter().print(retn);
        this.context.getWriter().flush();
        return;
      }

      boolean isOut = true;
      for (ResultConfigBean r : results) {
        if (!"_props_".equals(r.getName()) && !r.getName().equals(re) && !"".equals(re)) {
          continue;
        }

        isOut = false;
        String type = r.getType();
        String location = r.getLocation();
        if (RenderType.REDIRECT.equalsIgnoreCase(type)) {
          this.context.getResponse().sendRedirect(CommonUtil.replaceChinese2Utf8(location));

          return;
        } else if (RenderType.FORWARD.equalsIgnoreCase(type)) {
          HttpServletRequest request = this.context.getRequest();
          request.setAttribute(
              MVCConfigConstant.REQ_PARAM_MAP_NAME, this.context.getQueryParamMap());

          fields = ru.getFields();
          if (fields == null) return;

          for (Iterator<Entry<String, Object>> it = this.context.getModel().entrySet().iterator();
              it.hasNext(); ) {
            Entry<String, Object> entry = it.next();
            request.setAttribute(entry.getKey(), entry.getValue());
          }
          // 服务端跳转
          request
              .getRequestDispatcher(MVCConfigConstant.FORWARD_BASE_PATH + location)
              .forward(request, this.context.getResponse());

          return;
        } else if (RenderType.FREEMARKER.equalsIgnoreCase(type)) {
          // FreeMarker 渲染
          Configuration cfg = new Configuration();
          // 指定模板从何处加载的数据源,这里设置成一个文件目录。
          cfg.setDirectoryForTemplateLoading(
              new File(ConfigConstant.ROOT_PATH + MVCConfigConstant.FORWARD_BASE_PATH));
          // 指定模板如何检索数据模型
          cfg.setObjectWrapper(new DefaultObjectWrapper());
          cfg.setDefaultEncoding("utf-8");

          Template template = cfg.getTemplate(location);
          template.setEncoding("utf-8");

          template.process(this.context.getModel(), this.context.getWriter());

          return;
        } else if (RenderType.ACTION.equalsIgnoreCase(type)) {
          // ACTION 重定向
          handleActionRedirect(context, location, baseUrl);

          return;
        } else if (RenderType.OUT.equalsIgnoreCase(type) || location.trim().length() == 0) {
          this.context.getWriter().print(location);
          this.context.getWriter().flush();

          return;
        }
      }

      if (isOut) {
        this.context.getWriter().print(retn);
        this.context.getWriter().flush();
      }
    }
  }