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