View Javadoc

1   package com.atlassian.plugins.rest.common.multipart.jersey;
2   
3   import com.atlassian.plugins.rest.common.interceptor.impl.DispatchProviderHelper;
4   import com.atlassian.plugins.rest.common.interceptor.impl.InterceptorChainBuilder;
5   import com.atlassian.plugins.rest.common.multipart.FilePart;
6   import com.atlassian.plugins.rest.common.multipart.MultipartForm;
7   import com.atlassian.plugins.rest.common.multipart.MultipartFormParam;
8   import com.sun.jersey.api.core.HttpContext;
9   import com.sun.jersey.api.model.AbstractResourceMethod;
10  import com.sun.jersey.api.model.Parameter;
11  import com.sun.jersey.core.spi.component.ComponentScope;
12  import com.sun.jersey.server.impl.inject.AbstractHttpContextInjectable;
13  import com.sun.jersey.server.impl.inject.InjectableValuesProvider;
14  import com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider;
15  import com.sun.jersey.spi.dispatch.RequestDispatcher;
16  import com.sun.jersey.spi.inject.Injectable;
17  
18  import java.lang.annotation.Annotation;
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.HashSet;
22  import java.util.List;
23  import java.util.Set;
24  import javax.ws.rs.core.Context;
25  import javax.ws.rs.ext.Provider;
26  
27  /**
28   * Dispatchs requests to methods with MultipartFormParam parameters
29   *
30   * @since 2.4
31   */
32  @Provider
33  public class MultipartFormDispatchProvider extends AbstractResourceMethodDispatchProvider
34  {
35      private static final String MULTIPART_FORM_PROPERTY = "com.atlassian.rest.multipart.form";
36  
37      private @Context InterceptorChainBuilder interceptorChainBuilder;
38  
39      @Override
40      public RequestDispatcher create(AbstractResourceMethod abstractResourceMethod)
41      {
42          DispatchProviderHelper helper = new DispatchProviderHelper(interceptorChainBuilder);
43          return helper.create(abstractResourceMethod, getInjectableValuesProvider(abstractResourceMethod));
44      }
45  
46      @Override
47      protected InjectableValuesProvider getInjectableValuesProvider(final AbstractResourceMethod method)
48      {
49          // We only return one if we find a MultipartFormParam annotated parameter
50          for (Parameter param : method.getParameters())
51          {
52              for (Annotation annotation : param.getAnnotations())
53              {
54                  if (annotation instanceof MultipartFormParam)
55                  {
56                      // Here we return an object that will parse the form (done by MultipartFormMessageBodyReader when getEntity() is called)
57                      return new InjectableValuesProvider(getInjectables(method))
58                      {
59                          @Override
60                          public Object[] getInjectableValues(final HttpContext context)
61                          {
62                              if (!context.getProperties().containsKey(MULTIPART_FORM_PROPERTY))
63                              {
64                                  context.getProperties().put(MULTIPART_FORM_PROPERTY, context.getRequest().getEntity(
65                                          MultipartForm.class, MultipartForm.class, method.getAnnotations()));
66                              }
67                              return super.getInjectableValues(context);
68                          }
69                      };
70                  }
71              }
72          }
73          return null;
74      }
75  
76      private List<Injectable> getInjectables(AbstractResourceMethod method)
77      {
78          List<Injectable> is = new ArrayList<Injectable>(method.getParameters().size());
79          for (int i = 0; i < method.getParameters().size(); i++)
80          {
81              Parameter parameter = method.getParameters().get(i);
82              Injectable<?> injectable = null;
83              // We don't support entities
84              if (Parameter.Source.ENTITY == parameter.getSource())
85              {
86                  return null;
87              }
88              for (Annotation annotation : parameter.getAnnotations())
89              {
90                  if (annotation instanceof MultipartFormParam)
91                  {
92                      // It's a multipart parameter, we get the injectable for it
93                      injectable = getMultipartFormInjectable(parameter, (MultipartFormParam) annotation);
94                  }
95              }
96              if (injectable == null)
97              {
98                  // This defaults back so that everything else, eg @HeaderParam, @Context etc can get injected
99                  injectable = getInjectableProviderContext().getInjectable(parameter, ComponentScope.PerRequest);
100             }
101             if (injectable == null)
102             {
103                 return null;
104             }
105             is.add(injectable);
106         }
107         return is;
108     }
109 
110     private Injectable<?> getMultipartFormInjectable(final Parameter parameter, final MultipartFormParam annotation)
111     {
112         // FilePart
113         if (parameter.getParameterClass().equals(FilePart.class))
114         {
115             return new AbstractHttpContextInjectable<FilePart>()
116             {
117                 public FilePart getValue(final HttpContext context)
118                 {
119                     return ((MultipartForm) context.getProperties().get(MULTIPART_FORM_PROPERTY)).getFilePart(annotation.value());
120                 }
121             };
122         }
123         // Collection of file parts
124         if (Collection.class.isAssignableFrom(parameter.getParameterClass()))
125         {
126             return new AbstractHttpContextInjectable<Collection<FilePart>>()
127             {
128                 public Collection<FilePart> getValue(final HttpContext context)
129                 {
130                     Collection<FilePart> parts = ((MultipartForm) context.getProperties().get(MULTIPART_FORM_PROPERTY)).getFileParts(annotation.value());
131                     if (parameter.getParameterClass().isAssignableFrom(Collection.class))
132                     {
133                         return parts;
134                     }
135                     else if (parameter.getParameterClass().isAssignableFrom(List.class))
136                     {
137                         return new ArrayList<FilePart>(parts);
138                     }
139                     else if (parameter.getParameterClass().isAssignableFrom(Set.class))
140                     {
141                         return new HashSet<FilePart>(parts);
142                     }
143                     return null;
144                 }
145             };
146         }
147         return null;
148     }
149 }