View Javadoc

1   package it.com.atlassian.rest.multipart;
2   
3   import java.util.ArrayList;
4   import java.util.Iterator;
5   
6   import javax.ws.rs.core.Response;
7   import javax.xml.bind.JAXBContext;
8   import javax.xml.bind.Unmarshaller;
9   
10  import com.atlassian.plugins.rest.common.security.jersey.XsrfResourceFilter;
11  import com.atlassian.plugins.rest.multipart.FilePartObject;
12  import com.atlassian.plugins.rest.multipart.FilePartObjects;
13  import com.atlassian.rest.jersey.client.WebResourceFactory;
14  
15  import org.apache.commons.httpclient.HttpClient;
16  import org.apache.commons.httpclient.methods.PostMethod;
17  import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
18  import org.apache.commons.httpclient.methods.multipart.FilePart;
19  import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
20  import org.apache.commons.httpclient.methods.multipart.Part;
21  import org.apache.commons.httpclient.methods.multipart.PartSource;
22  import org.apache.commons.httpclient.methods.multipart.StringPart;
23  import org.apache.commons.httpclient.params.HttpMethodParams;
24  import org.junit.Before;
25  import org.junit.Test;
26  
27  import static junit.framework.Assert.assertTrue;
28  import static org.junit.Assert.assertEquals;
29  
30  
31  public class MultipartResourceTest {
32      private HttpClient client;
33  
34      @Before
35      public void setUp() {
36          client = new HttpClient();
37      }
38  
39      @Test
40      public void testUploadSingleFile() throws Exception {
41          FilePartObject filePartObject = new FilePartObject("file", false, "filename.txt", "text/plain", "Hello world!!");
42          FilePartObject result = (FilePartObject) uploadAndUnmarshalFileParts("single", filePartObject);
43          assertFilePartEquals(filePartObject, result);
44      }
45  
46      @Test
47      public void testUploadSingleSimpleField() throws Exception {
48          FilePartObject filePartObject = new FilePartObject("file", true, null, null, "Hello world!!");
49          FilePartObject result = (FilePartObject) uploadAndUnmarshalFileParts("single", filePartObject);
50          assertFilePartEquals(filePartObject, result);
51      }
52  
53      @Test
54      public void testUploadMultiple() throws Exception {
55          FilePartObject filePartObject1 = new FilePartObject("file", false, "file1.txt", "text/plain", "Hello first world!");
56          FilePartObject filePartObject2 = new FilePartObject("file", false, "file2.txt", "text/plain", "Hello second world!");
57  
58          FilePartObjects result = (FilePartObjects) uploadAndUnmarshalFileParts("multiple", filePartObject1, filePartObject2);
59          assertEquals(2, result.getFileParts().size());
60          Iterator<FilePartObject> iter = result.getFileParts().iterator();
61          assertFilePartEquals(filePartObject1, iter.next());
62          assertFilePartEquals(filePartObject2, iter.next());
63      }
64  
65      @Test
66      public void testMaxFileSizeUnder() throws Exception {
67          FilePartObject filePartObject = new FilePartObject("file", false, "file.txt", "text/plain", "Safe");
68          FilePartObjects result = (FilePartObjects) uploadAndUnmarshalFileParts("config", filePartObject);
69          assertEquals(1, result.getFileParts().size());
70          assertFilePartEquals(filePartObject, result.getFileParts().iterator().next());
71      }
72  
73      @Test
74      public void testMaxFileSizeExceeded() throws Exception {
75          // The config resource is configured for maximum file size of 10 characters
76          FilePartObject filePartObject = new FilePartObject("file", false, "file.txt", "text/plain", "This is longer than 10 characters");
77          PostMethod method = uploadFileParts("config", filePartObject);
78          assertEquals(413, method.getStatusCode());
79          assertTrue(method.getResponseBodyAsString().contains("10"));
80      }
81  
82      @Test
83      public void testMaxSizeExceeded() throws Exception {
84          // The config resource is configured for maximum overall request size of 1000 characters.  This should yield
85          // 1161 characters due to all the multipart headers
86          PostMethod method = uploadFileParts("config", new FilePartObject("file", false, "file.txt", "text/plain", "Safe"),
87                  new FilePartObject("file", false, "file.txt", "text/plain", "Safe"),
88                  new FilePartObject("file", false, "file.txt", "text/plain", "Safe"),
89                  new FilePartObject("file", false, "file.txt", "text/plain", "Safe"),
90                  new FilePartObject("file", false, "file.txt", "text/plain", "Safe"),
91                  new FilePartObject("file", false, "file.txt", "text/plain", "Safe"));
92          assertEquals(413, method.getStatusCode());
93          assertTrue(method.getResponseBodyAsString().contains("1000"));
94      }
95  
96      @Test
97      public void testInterceptorInvoked() throws Exception {
98          FilePartObject filePartObject = new FilePartObject("file", false, "abc.txt", "text/plain", "Upload");
99          PostMethod method = uploadFileParts("fileName", filePartObject);
100         assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><message><message>abc.txt: Bob</message></message>", method.getResponseBodyAsString());
101     }
102 
103     @Test
104     public void uploadWithEncodedNameShouldLeaveFileNameCorrect() throws Exception {
105         FilePartObject filePartObject = new FilePartObject("file", false, "=?utf-8?B?0YLQtdGB0YI=?=", "text/plain", "Hello first world!");
106         FilePartObject result = (FilePartObject) uploadAndUnmarshalFileParts("single", filePartObject);
107         assertEquals("ั‚ะตัั‚", result.getFilename());
108     }
109 
110     @Test
111     public void uploadWithIllegalCharacterEncodingShouldResultInClientError() throws Exception {
112         PostMethod method = uploadFileParts("single", new FilePartObject("file", false, "=?utf-unknown?B?unknown?=", "text/plain", "Hello first world!"));
113         assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), method.getStatusCode());
114     }
115 
116     private static void assertFilePartEquals(FilePartObject o1, FilePartObject o2) {
117         assertEquals("Field name", o1.getFieldName(), o2.getFieldName());
118         assertEquals("Is field", o1.isField(), o2.isField());
119         assertEquals("File name", o1.getFilename(), o2.getFilename());
120         assertEquals("File contents", o1.getValue(), o2.getValue());
121     }
122 
123     private PostMethod uploadFileParts(String to, FilePartObject... fileParts) throws Exception {
124         ArrayList<Part> parts = new ArrayList<Part>();
125         for (FilePartObject o : fileParts) {
126             if (o.isField()) {
127                 StringPart stringPart = new StringPart(o.getFieldName(), o.getValue());
128                 parts.add(stringPart);
129             } else {
130                 PartSource partSource = new ByteArrayPartSource(o.getFilename(), o.getValue().getBytes("UTF-8"));
131                 FilePart filePart = new FilePart(o.getFieldName(), partSource, o.getContentType(), "UTF-8");
132                 parts.add(filePart);
133             }
134         }
135 
136         PostMethod method = new PostMethod(WebResourceFactory.getUriBuilder().path("rest").path("refimpl").path(WebResourceFactory.REST_VERSION).path("multipart").path(to).build().toString() + ".xml");
137         method.setRequestHeader(XsrfResourceFilter.TOKEN_HEADER, XsrfResourceFilter.NO_CHECK);
138         MultipartRequestEntity requestEntity = new MultipartRequestEntity(parts.toArray(new Part[parts.size()]), new HttpMethodParams());
139         method.setRequestEntity(requestEntity);
140         client.executeMethod(method);
141         return method;
142     }
143 
144     private Object uploadAndUnmarshalFileParts(String to, FilePartObject... fileParts) throws Exception {
145         PostMethod method = uploadFileParts(to, fileParts);
146         Unmarshaller unmarshaller = JAXBContext.newInstance(FilePartObject.class, FilePartObjects.class).createUnmarshaller();
147         return unmarshaller.unmarshal(method.getResponseBodyAsStream());
148     }
149 }