View Javadoc

1   package com.atlassian.plugins.rest.common.validation;
2   
3   import com.atlassian.plugins.rest.common.interceptor.MethodInvocation;
4   import com.atlassian.plugins.rest.common.interceptor.ResourceInterceptor;
5   import com.atlassian.sal.api.message.I18nResolver;
6   import com.sun.jersey.api.model.AbstractResourceMethod;
7   import com.sun.jersey.api.model.Parameter;
8   
9   import javax.validation.Configuration;
10  import javax.validation.ConstraintViolation;
11  import javax.validation.MessageInterpolator;
12  import javax.validation.Validation;
13  import javax.validation.Validator;
14  import javax.validation.ValidatorFactory;
15  import javax.ws.rs.core.Response;
16  import java.lang.reflect.InvocationTargetException;
17  import java.util.Set;
18  
19  /**
20   * Uses JSR-303 to validate incoming entity objects.  If validation fails, it will return a 400 with a {@link ValidationErrors}
21   * instance containing the constraint violations.  The error messages will be processed with either SAL or the
22   * provided custom {@link MessageInterpolator}.
23   *
24   * @since 2.0
25   */
26  public class ValidationInterceptor implements ResourceInterceptor {
27      private final ValidatorFactory factory;
28  
29      public ValidationInterceptor(I18nResolver i18nResolver) {
30          this(new SalMessageInterpolator(i18nResolver));
31  
32      }
33  
34      public ValidationInterceptor(MessageInterpolator messageInterpolator) {
35          // Yes, this cast is unnecessary in Java 6, but seems to be required in Java 5
36          this.factory = ((Configuration) Validation.byDefaultProvider().configure().messageInterpolator(messageInterpolator)).buildValidatorFactory();
37      }
38  
39      public void intercept(MethodInvocation invocation) throws IllegalAccessException, InvocationTargetException {
40          Validator validator = factory.getValidator();
41  
42          // find the entity for the resource method
43          int entityIndex = -1;
44          AbstractResourceMethod method = invocation.getMethod();
45          for (int i = 0; i < method.getParameters().size(); i++) {
46              Parameter parameter = method.getParameters().get(i);
47  
48              if (Parameter.Source.ENTITY == parameter.getSource()) {
49                  entityIndex = i;
50                  break;
51              }
52          }
53  
54  
55          // entity found, so let's validate
56          if (entityIndex > -1) {
57              Set<ConstraintViolation<Object>> constraintViolations = validator.validate(invocation.getParameters()[entityIndex]);
58              if (!constraintViolations.isEmpty()) {
59                  ValidationErrors errors = new ValidationErrors();
60                  for (ConstraintViolation<Object> violation : constraintViolations) {
61                      ValidationError error = new ValidationError();
62                      error.setMessage(violation.getMessage());
63                      error.setPath(violation.getPropertyPath().toString());
64                      errors.addError(error);
65                  }
66                  invocation.getHttpContext().getResponse().setResponse(Response.status(400).entity(errors).build());
67                  return;
68              }
69          }
70  
71          invocation.invoke();
72      }
73  }