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 private static final String MULTIPART_FORM_PROPERTY = "com.atlassian.rest.multipart.form";
35
36 private
37 @Context
38 InterceptorChainBuilder interceptorChainBuilder;
39
40 @Override
41 public RequestDispatcher create(AbstractResourceMethod abstractResourceMethod) {
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 for (Parameter param : method.getParameters()) {
50 for (Annotation annotation : param.getAnnotations()) {
51 if (annotation instanceof MultipartFormParam) {
52
53 return new InjectableValuesProvider(getInjectables(method)) {
54 @Override
55 public Object[] getInjectableValues(final HttpContext context) {
56 if (!context.getProperties().containsKey(MULTIPART_FORM_PROPERTY)) {
57 context.getProperties().put(MULTIPART_FORM_PROPERTY, context.getRequest().getEntity(
58 MultipartForm.class, MultipartForm.class, method.getAnnotations()));
59 }
60 return super.getInjectableValues(context);
61 }
62 };
63 }
64 }
65 }
66 return null;
67 }
68
69 private List<Injectable> getInjectables(AbstractResourceMethod method) {
70 List<Injectable> is = new ArrayList<Injectable>(method.getParameters().size());
71 for (int i = 0; i < method.getParameters().size(); i++) {
72 Parameter parameter = method.getParameters().get(i);
73 Injectable<?> injectable = null;
74
75 if (Parameter.Source.ENTITY == parameter.getSource()) {
76 return null;
77 }
78 for (Annotation annotation : parameter.getAnnotations()) {
79 if (annotation instanceof MultipartFormParam) {
80
81 injectable = getMultipartFormInjectable(parameter, (MultipartFormParam) annotation);
82 }
83 }
84 if (injectable == null) {
85
86 injectable = getInjectableProviderContext().getInjectable(parameter, ComponentScope.PerRequest);
87 }
88 if (injectable == null) {
89 return null;
90 }
91 is.add(injectable);
92 }
93 return is;
94 }
95
96 private Injectable<?> getMultipartFormInjectable(final Parameter parameter, final MultipartFormParam annotation) {
97
98 if (parameter.getParameterClass().equals(FilePart.class)) {
99 return new AbstractHttpContextInjectable<FilePart>() {
100 public FilePart getValue(final HttpContext context) {
101 return ((MultipartForm) context.getProperties().get(MULTIPART_FORM_PROPERTY)).getFilePart(annotation.value());
102 }
103 };
104 }
105
106 if (Collection.class.isAssignableFrom(parameter.getParameterClass())) {
107 return new AbstractHttpContextInjectable<Collection<FilePart>>() {
108 public Collection<FilePart> getValue(final HttpContext context) {
109 Collection<FilePart> parts = ((MultipartForm) context.getProperties().get(MULTIPART_FORM_PROPERTY)).getFileParts(annotation.value());
110 if (parameter.getParameterClass().isAssignableFrom(Collection.class)) {
111 return parts;
112 } else if (parameter.getParameterClass().isAssignableFrom(List.class)) {
113 return new ArrayList<FilePart>(parts);
114 } else if (parameter.getParameterClass().isAssignableFrom(Set.class)) {
115 return new HashSet<FilePart>(parts);
116 }
117 return null;
118 }
119 };
120 }
121 return null;
122 }
123 }