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
29
30
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
50 for (Parameter param : method.getParameters())
51 {
52 for (Annotation annotation : param.getAnnotations())
53 {
54 if (annotation instanceof MultipartFormParam)
55 {
56
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
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
93 injectable = getMultipartFormInjectable(parameter, (MultipartFormParam) annotation);
94 }
95 }
96 if (injectable == null)
97 {
98
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
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
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 }