1   /*
2    * Copyright 2004-2010 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  
17  package org.seasar.cubby.controller.impl;
18  
19  import static org.easymock.EasyMock.anyObject;
20  import static org.easymock.EasyMock.createMock;
21  import static org.easymock.EasyMock.expect;
22  import static org.easymock.EasyMock.expectLastCall;
23  import static org.easymock.EasyMock.getCurrentArguments;
24  import static org.easymock.EasyMock.replay;
25  import static org.junit.Assert.assertEquals;
26  import static org.junit.Assert.assertTrue;
27  
28  import java.io.ByteArrayInputStream;
29  import java.io.ByteArrayOutputStream;
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.util.Enumeration;
33  import java.util.Hashtable;
34  import java.util.Map;
35  
36  import javax.servlet.ServletInputStream;
37  import javax.servlet.http.HttpServletRequest;
38  
39  import org.apache.commons.fileupload.FileItem;
40  import org.apache.commons.fileupload.FileUpload;
41  import org.apache.commons.fileupload.RequestContext;
42  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
43  import org.apache.commons.fileupload.servlet.ServletFileUpload;
44  import org.apache.commons.fileupload.servlet.ServletRequestContext;
45  import org.apache.commons.httpclient.methods.PostMethod;
46  import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
47  import org.apache.commons.httpclient.methods.multipart.FilePart;
48  import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
49  import org.apache.commons.httpclient.methods.multipart.Part;
50  import org.apache.commons.httpclient.methods.multipart.PartSource;
51  import org.apache.commons.httpclient.methods.multipart.StringPart;
52  import org.easymock.IAnswer;
53  import org.junit.After;
54  import org.junit.Before;
55  import org.junit.Test;
56  import org.seasar.cubby.controller.RequestParser;
57  import org.seasar.cubby.mock.MockContainerProvider;
58  import org.seasar.cubby.plugin.PluginRegistry;
59  import org.seasar.cubby.plugins.BinderPlugin;
60  import org.seasar.cubby.spi.ContainerProvider;
61  import org.seasar.cubby.spi.container.Container;
62  
63  public class MultipartRequestParserImplMultipartRequestTest {
64  
65  	private final PluginRegistry pluginRegistry = PluginRegistry.getInstance();
66  
67  	private final RequestParser requestParser = new MultipartRequestParser();
68  
69  	private HttpServletRequest request;
70  
71  	private final Hashtable<String, Object> attributes = new Hashtable<String, Object>();
72  
73  	private InputStream input;
74  
75  	private MultipartRequestEntity entity;
76  
77  	@Before
78  	@SuppressWarnings("unchecked")
79  	public void setupRequest() throws Exception {
80  		request = createMock(HttpServletRequest.class);
81  		expect(request.getCharacterEncoding()).andStubReturn("UTF-8");
82  		expect(request.getAttribute(String.class.cast(anyObject())))
83  				.andStubAnswer(new IAnswer<Object>() {
84  
85  					public Object answer() throws Throwable {
86  						return attributes.get(getCurrentArguments()[0]);
87  					}
88  
89  				});
90  		request.setAttribute(String.class.cast(anyObject()), anyObject());
91  		expectLastCall().andStubAnswer(new IAnswer<Object>() {
92  
93  			public Object answer() throws Throwable {
94  				attributes.put(String.class.cast(getCurrentArguments()[0]),
95  						getCurrentArguments()[1]);
96  				return null;
97  			}
98  
99  		});
100 		expect(request.getAttributeNames()).andStubAnswer(
101 				new IAnswer<Enumeration>() {
102 
103 					public Enumeration answer() throws Throwable {
104 						return attributes.keys();
105 					}
106 
107 				});
108 		expect(request.getParameterMap()).andStubReturn(attributes);
109 		expect(request.getContentType()).andStubAnswer(new IAnswer<String>() {
110 
111 			public String answer() throws Throwable {
112 				return entity.getContentType();
113 			}
114 
115 		});
116 		expect(request.getContentLength()).andStubAnswer(
117 				new IAnswer<Integer>() {
118 
119 					public Integer answer() throws Throwable {
120 						return (int) entity.getContentLength();
121 					}
122 
123 				});
124 		expect(request.getInputStream()).andStubReturn(
125 				new ServletInputStream() {
126 
127 					@Override
128 					public int read() throws IOException {
129 						return input.read();
130 					}
131 
132 				});
133 		replay(request);
134 
135 		final FileUpload fileUpload = new ServletFileUpload();
136 		fileUpload.setFileItemFactory(new DiskFileItemFactory());
137 		final RequestContext requestContext = new ServletRequestContext(request);
138 		BinderPlugin binderPlugin = new BinderPlugin();
139 		binderPlugin.bind(ContainerProvider.class).toInstance(
140 				new MockContainerProvider(new Container() {
141 
142 					public <T> T lookup(final Class<T> type) {
143 						if (FileUpload.class.equals(type)) {
144 							return type.cast(fileUpload);
145 						}
146 
147 						if (RequestContext.class.equals(type)) {
148 							return type.cast(requestContext);
149 						}
150 
151 						return null;
152 					}
153 
154 				}));
155 		pluginRegistry.register(binderPlugin);
156 	}
157 
158 	@After
159 	public void tearDownProvider() {
160 		pluginRegistry.clear();
161 	}
162 
163 	@Test
164 	public void getParameterMap() throws Exception {
165 		final PartSource filePartSource = new ByteArrayPartSource("upload.txt",
166 				"upload test".getBytes("UTF-8"));
167 		final PostMethod method = new PostMethod();
168 		final Part[] parts = new Part[] { new StringPart("a", "12345"),
169 				new StringPart("b", "abc"), new StringPart("b", "def"),
170 				new FilePart("file", filePartSource) };
171 		this.entity = new MultipartRequestEntity(parts, method.getParams());
172 		final ByteArrayOutputStream out = new ByteArrayOutputStream();
173 		this.entity.writeRequest(out);
174 		out.flush();
175 		out.close();
176 		this.input = new ByteArrayInputStream(out.toByteArray());
177 		this.attributes.put("c", new String[] { "999" });
178 
179 		final Map<String, Object[]> parameterMap = requestParser
180 				.getParameterMap(request);
181 		assertEquals("parameterMap.size()", 4, parameterMap.size());
182 		final Object[] a = parameterMap.get("a");
183 		assertEquals("a.length", 1, a.length);
184 		assertEquals("a[0]", "12345", a[0]);
185 		final Object[] b = parameterMap.get("b");
186 		assertEquals("b.length", 2, b.length);
187 		assertEquals("b[0]", "abc", b[0]);
188 		assertEquals("b[1]", "def", b[1]);
189 		final Object[] c = parameterMap.get("c");
190 		assertEquals("c.length", 1, c.length);
191 		assertEquals("c[0]", "999", c[0]);
192 		final Object[] file = parameterMap.get("file");
193 		assertEquals("file.length", 1, file.length);
194 		assertTrue("file[0]", file[0] instanceof FileItem);
195 		final FileItem item = (FileItem) file[0];
196 		assertEquals("upload test", new String(item.get(), "UTF-8"));
197 	}
198 
199 	@Test
200 	public void getParameterMapEmpty() throws Exception {
201 		final PostMethod method = new PostMethod();
202 		final Part[] parts = new Part[0];
203 		this.entity = new MultipartRequestEntity(parts, method.getParams());
204 		final ByteArrayOutputStream out = new ByteArrayOutputStream();
205 		this.entity.writeRequest(out);
206 		out.flush();
207 		out.close();
208 		this.input = new ByteArrayInputStream(out.toByteArray());
209 
210 		final Map<String, Object[]> parameterMap = requestParser
211 				.getParameterMap(request);
212 		assertTrue("parameterMap.isEmpty()", parameterMap.isEmpty());
213 	}
214 
215 }