    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 }