All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.enunciate.modules.jersey.JerseyValidator Maven / Gradle / Ivy

Go to download

The Enunciate Jersey module generates the Jersey support for the Enunciated project.

There is a newer version: 1.31
Show newest version
/*
 * Copyright 2006-2008 Web Cohesion
 *
 * 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.codehaus.enunciate.modules.jersey;

import org.codehaus.enunciate.contract.jaxrs.ResourceMethod;
import org.codehaus.enunciate.contract.jaxrs.RootResource;
import org.codehaus.enunciate.contract.validation.BaseValidator;
import org.codehaus.enunciate.contract.validation.ValidationResult;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.*;
import java.util.List;
import java.util.ArrayList;

import net.sf.jelly.apt.decorations.type.DecoratedTypeMirror;
import com.sun.mirror.declaration.*;

/**
 * @author Ryan Heaton
 */
public class JerseyValidator extends BaseValidator {

  private final boolean allowWildcardServlet;

  public JerseyValidator(boolean allowWildcardServlet) {
    this.allowWildcardServlet = allowWildcardServlet;
  }

  @Override
  public ValidationResult validateRootResources(List rootResources) {
    ValidationResult result = new ValidationResult();

    for (RootResource rootResource : rootResources) {

      if (rootResource.getDelegate() instanceof InterfaceDeclaration) {
        result.addError(rootResource, "Jersey doesn't support interfaces as root resources. The @Path parameter will need to be applied to the implementation class.");
      }
      else {
        List candidates = new ArrayList();
        boolean springManaged = rootResource.getAnnotation(SpringManagedLifecycle.class) != null;
        CONSTRUCTOR_LOOP:
        for (ConstructorDeclaration constructor : ((ClassDeclaration) rootResource.getDelegate()).getConstructors()) {
          if (constructor.getModifiers().contains(Modifier.PUBLIC)) {
            for (ParameterDeclaration constructorParam : constructor.getParameters()) {
              if (springManaged) {
                if (isSuppliableByJAXRS(constructorParam)) {
                  result.addWarning(constructorParam, "Constructor parameter will not be supplied by JAX-RS if the lifecycle of this resource is Spring-managed.");
                }
              }
              else if (!isSuppliableByJAXRS(constructorParam)) {
                //none of those annotation are available. not a candidate constructor.
                continue CONSTRUCTOR_LOOP;
              }
            }

            candidates.add(constructor);
          }
        }

        if (candidates.isEmpty() && !springManaged) {
          result.addError(rootResource, "A JAX-RS root resource must have a public constructor for which the JAX-RS runtime can provide all parameter values. " +
            "If the resource lifecycle is to be managed by Spring (which will handle the construction of the bean), then please apply the @" +
            SpringManagedLifecycle.class.getName() + " annotation to the resource.");
        }
        else {
          while (!candidates.isEmpty()) {
            ConstructorDeclaration candidate = candidates.remove(0);
            for (ConstructorDeclaration other : candidates) {
              if (candidate.getParameters().size() == other.getParameters().size()) {
                result.addWarning(rootResource, "Ambiguous JAX-RS constructors (same parameter count).");
              }
            }
          }
        }
      }

      for (ResourceMethod resourceMethod : rootResource.getResourceMethods(true)) {
        if ("/*".equals(resourceMethod.getServletPattern())) {
          if (!allowWildcardServlet) {
            result.addError(resourceMethod, "This JAX-RS resource method is designed to catch all requests (including requests to " +
              "Enunciate-generated documentation and other static files). If this is what you want, then please set 'disableWildcardServletError' to 'true'" +
              "in the Enunciate config for the Jersey module.  Otherwise, enable the rest subcontext or adjust the @Path annotation to be more specific.");
          }
          else {
            result.addWarning(resourceMethod, "JAX-RS resource method is designed to catch all requests.");
          }
        }

        for (String producesMime : resourceMethod.getProducesMime()) {
          try {
            MediaType.valueOf(producesMime);
          }
          catch (Exception e) {
            result.addError(resourceMethod, "Invalid produces MIME type: " + producesMime + "(" + e.getMessage() + ").");
          }
        }

        if (resourceMethod.getHttpMethods().size() > 1) {
          result.addError(resourceMethod, "You must not apply multiple HTTP operations to the same method: " + resourceMethod.getHttpMethods());
        }

        for (String method : resourceMethod.getHttpMethods()) {
          if ("GET".equalsIgnoreCase(method) && (resourceMethod.getOutputPayload() == null)) {
            result.addError(resourceMethod, "A resource method that is mapped to HTTP GET must have an output payload. (Does it return void?)");
          }

          if ("GET".equalsIgnoreCase(method) && resourceMethod.getEntityParameter() != null) {
            result.addError(resourceMethod, "A resource method that is mapped to HTTP GET must not specify an entity parameter.");
          }
        }
      }
    }

    return result;
  }

  /**
   * Whether the specified declaration is suppliable by JAX-RS.
   *
   * @param declaration The declaration.
   * @return Whether the specified declaration is suppliable by JAX-RS.
   */
  protected boolean isSuppliableByJAXRS(Declaration declaration) {
    return (declaration.getAnnotation(MatrixParam.class) != null)
        || (declaration.getAnnotation(PathParam.class) != null)
        || (declaration.getAnnotation(QueryParam.class) != null)
        || (declaration.getAnnotation(CookieParam.class) != null)
        || (declaration.getAnnotation(HeaderParam.class) != null)
        || (declaration.getAnnotation(javax.ws.rs.core.Context.class) != null);
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy