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  {
28      private final ValidatorFactory factory;
29  
30      public ValidationInterceptor(I18nResolver i18nResolver)
31      {
32          this(new SalMessageInterpolator(i18nResolver));
33  
34      }
35  
36      public ValidationInterceptor(MessageInterpolator messageInterpolator)
37      {
38          // Yes, this cast is unnecessary in Java 6, but seems to be required in Java 5
39          this.factory = ((Configuration)Validation.byDefaultProvider().configure().messageInterpolator(messageInterpolator)).buildValidatorFactory();
40      }
41  
42      public void intercept(MethodInvocation invocation) throws IllegalAccessException, InvocationTargetException
43      {
44          Validator validator = factory.getValidator();
45  
46          // find the entity for the resource method
47          int entityIndex = -1;
48          AbstractResourceMethod method = invocation.getMethod();
49          for (int i = 0; i < method.getParameters().size(); i++) {
50              Parameter parameter = method.getParameters().get(i);
51  
52              if (Parameter.Source.ENTITY == parameter.getSource()) {
53                  entityIndex = i;
54                  break;
55              }
56          }
57  
58  
59          // entity found, so let's validate
60          if (entityIndex > -1)
61          {
62              Set <ConstraintViolation<Object>> constraintViolations = validator.validate(invocation.getParameters()[entityIndex]);
63              if (!constraintViolations.isEmpty())
64              {
65                  ValidationErrors errors = new ValidationErrors();
66                  for (ConstraintViolation<Object> violation : constraintViolations)
67                  {
68                      ValidationError error = new ValidationError();
69                      error.setMessage(violation.getMessage());
70                      error.setPath(violation.getPropertyPath().toString());
71                      errors.addError(error);
72                  }
73                  invocation.getHttpContext().getResponse().setResponse(Response.status(400).entity(errors).build());
74                  return;
75              }
76          }
77  
78          invocation.invoke();
79      }
80  }