You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2015/06/28 22:02:51 UTC

[1/4] wicket git commit: WICKET-5924 FileUploadField does not work with Spring Boot

Repository: wicket
Updated Branches:
  refs/heads/master 0c71fa430 -> 07f4872d8


WICKET-5924 FileUploadField does not work with Spring Boot

Extract ServletPartFileItem as a separate class


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/ccfcf28d
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/ccfcf28d
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/ccfcf28d

Branch: refs/heads/master
Commit: ccfcf28d7ba9888869ed553265950a881d8e371c
Parents: 8b9c87a
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Sun Jun 28 18:09:02 2015 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Jun 28 21:42:32 2015 +0300

----------------------------------------------------------------------
 .../servlet/MultipartServletWebRequestImpl.java | 158 +--------------
 .../http/servlet/ServletPartFileItem.java       | 201 +++++++++++++++++++
 2 files changed, 202 insertions(+), 157 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/ccfcf28d/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
index 46aafb0..05aa17a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
@@ -16,10 +16,8 @@
  */
 package org.apache.wicket.protocol.http.servlet;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -33,20 +31,16 @@ import javax.servlet.http.Part;
 
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileItemFactory;
-import org.apache.commons.fileupload.FileItemHeaders;
 import org.apache.commons.fileupload.FileUploadBase;
 import org.apache.commons.fileupload.FileUploadException;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 import org.apache.commons.fileupload.servlet.ServletRequestContext;
-import org.apache.commons.fileupload.util.FileItemHeadersImpl;
 import org.apache.commons.io.FileCleaningTracker;
 import org.apache.wicket.Application;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.util.file.FileCleanerTrackerAdapter;
 import org.apache.wicket.util.file.IFileCleaner;
-import org.apache.wicket.util.io.ByteArrayOutputStream;
-import org.apache.wicket.util.io.Streams;
 import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.lang.Bytes;
 import org.apache.wicket.util.string.StringValue;
@@ -255,7 +249,7 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 			{
 				for (Part part : parts)
 				{
-					FileItem fileItem = new PartFileItem(part);
+					FileItem fileItem = new ServletPartFileItem(part);
 					itemsFromParts.add(fileItem);
 				}
 			}
@@ -565,154 +559,4 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 		req.getSession().removeAttribute(getSessionKey(upload));
 	}
 
-	private static class PartFileItem implements FileItem
-	{
-		private final Part part;
-
-		private PartFileItem(Part part) {
-			this.part = part;
-		}
-
-		@Override
-		public InputStream getInputStream() throws IOException
-		{
-			return part.getInputStream();
-		}
-
-		@Override
-		public String getContentType()
-		{
-			return part.getContentType();
-		}
-
-		@Override
-		public String getName()
-		{
-			return getFileName(part);
-		}
-
-		private String getFileName(Part part) {
-			for (String cd : part.getHeader("content-disposition").split(";")) {
-				if (cd.trim().startsWith("filename")) {
-					return cd.substring(cd.indexOf('=') + 1).trim()
-							.replace("\"", "");
-				}
-			}
-			return null;
-		}
-
-		@Override
-		public boolean isInMemory()
-		{
-			return true;
-		}
-
-		@Override
-		public long getSize()
-		{
-			return part.getSize();
-		}
-
-		@Override
-		public byte[] get()
-		{
-			try
-			{
-				ByteArrayOutputStream baos = new ByteArrayOutputStream();
-				Streams.copy(getInputStream() ,baos);
-				return baos.toByteArray();
-			} catch (IOException iox)
-			{
-				throw new WicketRuntimeException("Could not read upload's part input stream", iox);
-			}
-		}
-
-		@Override
-		public String getString(String encoding) throws UnsupportedEncodingException
-		{
-			byte[] bytes = get();
-			return new String(bytes, encoding);
-		}
-
-		@Override
-		public String getString()
-		{
-			try
-			{
-				return getString("UTF-8");
-			} catch (UnsupportedEncodingException uex)
-			{
-				throw new WicketRuntimeException("UTF-8 must be supported", uex);
-			}
-		}
-
-		@Override
-		public void write(File file) throws Exception
-		{
-			part.write(file.getName());
-		}
-
-		@Override
-		public void delete()
-		{
-			try
-			{
-				part.delete();
-			} catch (IOException iox)
-			{
-				throw new WicketRuntimeException("A problem occurred while deleting an upload part", iox);
-			}
-		}
-
-		@Override
-		public String getFieldName()
-		{
-			return part.getName();
-		}
-
-		@Override
-		public void setFieldName(String name)
-		{
-			throw new UnsupportedOperationException("setFieldName");
-		}
-
-		@Override
-		public boolean isFormField()
-		{
-			return false;
-		}
-
-		@Override
-		public void setFormField(boolean state)
-		{
-			throw new UnsupportedOperationException("setFormField");
-		}
-
-		@Override
-		public OutputStream getOutputStream() throws IOException
-		{
-			throw new UnsupportedOperationException("getOutputStream");
-		}
-
-		@Override
-		public FileItemHeaders getHeaders()
-		{
-			FileItemHeadersImpl fileItemHeaders = new FileItemHeadersImpl();
-			for (String headerName : part.getHeaderNames())
-			{
-				Collection<String> headerValues = part.getHeaders(headerName);
-				for (String headerValue : headerValues)
-				{
-					fileItemHeaders.addHeader(headerName, headerValue);
-				}
-			}
-			return fileItemHeaders;
-		}
-
-		@Override
-		public void setHeaders(FileItemHeaders headers)
-		{
-			throw new UnsupportedOperationException("setHeaders");
-		}
-	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/ccfcf28d/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
new file mode 100644
index 0000000..3b04102
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.protocol.http.servlet;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Collection;
+
+import javax.servlet.http.Part;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemHeaders;
+import org.apache.commons.fileupload.util.FileItemHeadersImpl;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.util.io.IOUtils;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.string.Strings;
+
+/**
+ * An adapter of {@link Part} to {@link FileItem}
+ */
+class ServletPartFileItem implements FileItem
+{
+	/**
+	 * The adapted part
+	 */
+	private final Part part;
+
+	/**
+	 * Constructor
+	 */
+	ServletPartFileItem(Part part)
+	{
+		Args.notNull(part, "part");
+		this.part = part;
+	}
+
+	@Override
+	public InputStream getInputStream() throws IOException
+	{
+		return part.getInputStream();
+	}
+
+	@Override
+	public String getContentType()
+	{
+		return part.getContentType();
+	}
+
+	@Override
+	public String getName()
+	{
+		return getFileName(part);
+	}
+
+	private String getFileName(Part part)
+	{
+		String contentDisposition = part.getHeader("content-disposition");
+		for (String cd : Strings.split(contentDisposition, ';'))
+		{
+			if (cd.trim().startsWith("filename"))
+			{
+				return cd.substring(cd.indexOf('=') + 1).trim()
+						.replace("\"", "");
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public boolean isInMemory()
+	{
+		return true;
+	}
+
+	@Override
+	public long getSize()
+	{
+		return part.getSize();
+	}
+
+	@Override
+	public byte[] get()
+	{
+		try
+		{
+			return IOUtils.toByteArray(getInputStream());
+		}
+		catch (IOException iox)
+		{
+			throw new WicketRuntimeException("Could not read upload's part input stream", iox);
+		}
+	}
+
+	@Override
+	public String getString(String encoding) throws UnsupportedEncodingException
+	{
+		byte[] bytes = get();
+		return new String(bytes, encoding);
+	}
+
+	@Override
+	public String getString()
+	{
+		try
+		{
+			return getString("UTF-8");
+		}
+		catch (UnsupportedEncodingException uex)
+		{
+			throw new WicketRuntimeException("UTF-8 must be supported", uex);
+		}
+	}
+
+	@Override
+	public void write(File file) throws Exception
+	{
+		part.write(file.getName());
+	}
+
+	@Override
+	public void delete()
+	{
+		try
+		{
+			part.delete();
+		}
+		catch (IOException iox)
+		{
+			throw new WicketRuntimeException("A problem occurred while deleting an upload part", iox);
+		}
+	}
+
+	@Override
+	public String getFieldName()
+	{
+		return part.getName();
+	}
+
+	@Override
+	public void setFieldName(String name)
+	{
+		throw new UnsupportedOperationException("setFieldName");
+	}
+
+	@Override
+	public boolean isFormField()
+	{
+		return false;
+	}
+
+	@Override
+	public void setFormField(boolean state)
+	{
+		throw new UnsupportedOperationException("setFormField");
+	}
+
+	@Override
+	public OutputStream getOutputStream() throws IOException
+	{
+		throw new UnsupportedOperationException("getOutputStream");
+	}
+
+	@Override
+	public FileItemHeaders getHeaders()
+	{
+		FileItemHeadersImpl fileItemHeaders = new FileItemHeadersImpl();
+		for (String headerName : part.getHeaderNames())
+		{
+			Collection<String> headerValues = part.getHeaders(headerName);
+			for (String headerValue : headerValues)
+			{
+				fileItemHeaders.addHeader(headerName, headerValue);
+			}
+		}
+		return fileItemHeaders;
+	}
+
+	@Override
+	public void setHeaders(FileItemHeaders headers)
+	{
+		throw new UnsupportedOperationException("setHeaders");
+	}
+}


[3/4] wicket git commit: WICKET-5924 FileUploadField does not work with Spring Boot

Posted by mg...@apache.org.
WICKET-5924 FileUploadField does not work with Spring Boot

Add WicketTester support for Servlet 3.0 multipart uploads


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/a6988b06
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/a6988b06
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/a6988b06

Branch: refs/heads/master
Commit: a6988b0681932917753016ffd9d83412889ec2b3
Parents: ccfcf28
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Sun Jun 28 22:43:59 2015 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Jun 28 22:43:59 2015 +0300

----------------------------------------------------------------------
 .../http/mock/MockHttpServletRequest.java       |  15 +-
 .../http/servlet/ServletPartFileItem.java       |   5 +-
 .../request/resource/AbstractResource.java      |   7 +-
 .../form/upload/FileUploadServletPartTest.java  | 150 +++++++++++++++++++
 .../upload/MockPageWithFormAndUploadField.java  |  12 +-
 5 files changed, 173 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/a6988b06/wicket-core/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java
index 354d1c0..cf8087d 100755
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/mock/MockHttpServletRequest.java
@@ -170,13 +170,15 @@ public class MockHttpServletRequest implements HttpServletRequest
 
 	private final ServletContext context;
 
-	private final Map<Cookies.Key, Cookie> cookies = new LinkedHashMap<Cookies.Key, Cookie>();
+	private final Map<Cookies.Key, Cookie> cookies = new LinkedHashMap<>();
 
 	private final ValueMap headers = new ValueMap();
 
 	private String method;
 
-	private final LinkedHashMap<String, String[]> parameters = new LinkedHashMap<String, String[]>();
+	private final LinkedHashMap<String, String[]> parameters = new LinkedHashMap<>();
+
+	private final LinkedHashMap<String, Part> parts = new LinkedHashMap<>();
 
 	private String path;
 
@@ -1228,13 +1230,18 @@ public class MockHttpServletRequest implements HttpServletRequest
 	@Override
 	public Collection<Part> getParts() throws IOException, ServletException
 	{
-		return null;
+		return parts.values();
 	}
 
 	@Override
 	public Part getPart(String name) throws IOException, ServletException
 	{
-		return null;
+		return parts.get(name);
+	}
+
+	public MockHttpServletRequest setPart(String name, Part part) {
+		parts.put(name, part);
+		return this;
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/wicket/blob/a6988b06/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
index 3b04102..c38de71 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/ServletPartFileItem.java
@@ -29,12 +29,13 @@ import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileItemHeaders;
 import org.apache.commons.fileupload.util.FileItemHeadersImpl;
 import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.request.resource.AbstractResource;
 import org.apache.wicket.util.io.IOUtils;
 import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.string.Strings;
 
 /**
- * An adapter of {@link Part} to {@link FileItem}
+ * An adapter of Servlet 3.0 {@link Part} to Apache Commons FileUpload's {@link FileItem}
  */
 class ServletPartFileItem implements FileItem
 {
@@ -72,7 +73,7 @@ class ServletPartFileItem implements FileItem
 
 	private String getFileName(Part part)
 	{
-		String contentDisposition = part.getHeader("content-disposition");
+		String contentDisposition = part.getHeader(AbstractResource.CONTENT_DISPOSITION_HEADER_NAME);
 		for (String cd : Strings.split(contentDisposition, ';'))
 		{
 			if (cd.trim().startsWith("filename"))

http://git-wip-us.apache.org/repos/asf/wicket/blob/a6988b06/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java
index 5e0798d..0d41238 100644
--- a/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java
+++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java
@@ -66,6 +66,8 @@ public abstract class AbstractResource implements IResource
 		private static final long serialVersionUID = 1L;
 	};
 
+	public static final String CONTENT_DISPOSITION_HEADER_NAME = "content-disposition";
+
 	/**
 	 * All available content range types. The type name represents the name used in header
 	 * information.
@@ -76,7 +78,7 @@ public abstract class AbstractResource implements IResource
 
 		private final String typeName;
 
-		private ContentRangeType(String typeName)
+		ContentRangeType(String typeName)
 		{
 			this.typeName = typeName;
 		}
@@ -96,10 +98,9 @@ public abstract class AbstractResource implements IResource
 		INTERNAL_HEADERS.add("last-modified");
 		INTERNAL_HEADERS.add("content-type");
 		INTERNAL_HEADERS.add("content-length");
-		INTERNAL_HEADERS.add("content-disposition");
+		INTERNAL_HEADERS.add(CONTENT_DISPOSITION_HEADER_NAME);
 		INTERNAL_HEADERS.add("transfer-encoding");
 		INTERNAL_HEADERS.add("connection");
-		INTERNAL_HEADERS.add("content-disposition");
 		INTERNAL_HEADERS.add("content-range");
 		INTERNAL_HEADERS.add("accept-range");
 	}

http://git-wip-us.apache.org/repos/asf/wicket/blob/a6988b06/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadServletPartTest.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadServletPartTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadServletPartTest.java
new file mode 100644
index 0000000..bd32c9e
--- /dev/null
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/FileUploadServletPartTest.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.html.form.upload;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.servlet.http.Part;
+
+import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
+import org.apache.wicket.request.resource.AbstractResource;
+import org.apache.wicket.util.io.IOUtils;
+import org.apache.wicket.util.tester.FormTester;
+import org.apache.wicket.util.tester.WicketTestCase;
+import org.junit.Test;
+
+
+/**
+ * Test of FileUpload with simulated Servlet 3.0 multipart config
+ */
+public class FileUploadServletPartTest extends WicketTestCase
+{
+	/**
+	 * Tests support for uploading files with Servlet 3.0 multipart upload
+	 * https://issues.apache.org/jira/browse/WICKET-5924
+	 *
+	 * @throws Exception
+	 */
+	@Test
+	public void uploadServlet30Multipart() throws Exception
+	{
+		MockPageWithFormAndUploadField page = tester.startPage(MockPageWithFormAndUploadField.class);
+
+		MockHttpServletRequest httpServletRequest = tester.getRequest();
+		FormTester formTester = tester.newFormTester(MockPageWithFormAndUploadField.FORM_ID);
+		Servlet3Part part = new Servlet3Part(page.fileUploadField.getInputName());
+		httpServletRequest.setPart(MockPageWithFormAndUploadField.FILE_UPLOAD_ID, part);
+		formTester.submit();
+
+		page = (MockPageWithFormAndUploadField) tester.getLastRenderedPage();
+		FileUpload fileUpload = page.getFileUpload();
+		assertArrayEquals(Servlet3Part.DATA, fileUpload.getBytes());
+		assertEquals(Servlet3Part.class.getSimpleName(), fileUpload.getClientFileName());
+		assertEquals(Servlet3Part.CONTENT_TYPE, fileUpload.getContentType());
+		assertArrayEquals(Servlet3Part.DATA, IOUtils.toByteArray(fileUpload.getInputStream()));
+
+		assertThat(part.written.get(), is(nullValue()));
+		fileUpload.writeToTempFile();
+		assertThat(part.written.get(), is(notNullValue()));
+
+		assertThat(part.deleted.get(), is(false));
+		fileUpload.delete();
+		assertThat(part.deleted.get(), is(true));
+	}
+
+	private static class Servlet3Part implements Part
+	{
+		private static final byte[] DATA = new byte[] {1, 2, 3};
+		public static final String CONTENT_TYPE = "text/plain";
+
+		private final AtomicReference<String> written = new AtomicReference<>();
+		private final AtomicBoolean deleted = new AtomicBoolean(false);
+		private final LinkedHashMap<String, List<String>> headers = new LinkedHashMap<>();
+		public final String fieldName;
+
+		private Servlet3Part(String fieldName) {
+			this.fieldName = fieldName;
+			headers.put(AbstractResource.CONTENT_DISPOSITION_HEADER_NAME, Arrays.asList("attachment;filename=" + Servlet3Part.class.getSimpleName()));
+		}
+
+		@Override
+		public InputStream getInputStream() throws IOException
+		{
+			return new ByteArrayInputStream(DATA);
+		}
+
+		@Override
+		public String getContentType()
+		{
+			return CONTENT_TYPE;
+		}
+
+		@Override
+		public String getName()
+		{
+			return fieldName;
+		}
+
+		@Override
+		public long getSize()
+		{
+			return DATA.length;
+		}
+
+		@Override
+		public void write(String fileName) throws IOException
+		{
+			written.set(fileName);
+		}
+
+		@Override
+		public void delete() throws IOException
+		{
+			deleted.set(true);
+		}
+
+		@Override
+		public String getHeader(String name)
+		{
+			return headers.containsKey(name) ? headers.get(name).get(0) : null;
+		}
+
+		@Override
+		public Collection<String> getHeaders(String name)
+		{
+			return headers.get(name);
+		}
+
+		@Override
+		public Collection<String> getHeaderNames()
+		{
+			return headers.keySet();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/a6988b06/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/MockPageWithFormAndUploadField.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/MockPageWithFormAndUploadField.java b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/MockPageWithFormAndUploadField.java
index ab58b26a..75806ba 100644
--- a/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/MockPageWithFormAndUploadField.java
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/html/form/upload/MockPageWithFormAndUploadField.java
@@ -30,6 +30,9 @@ public class MockPageWithFormAndUploadField extends WebPage
 {
 	private static final long serialVersionUID = 1L;
 
+	public static final String FILE_UPLOAD_ID = "upload";
+	public static final String FORM_ID = "form";
+
 	private final Form<?> form;
 	protected final FileUploadField fileUploadField;
 	private FileUpload fileUpload;
@@ -41,13 +44,8 @@ public class MockPageWithFormAndUploadField extends WebPage
 	{
 		final ListModel<FileUpload> model = new ListModel<FileUpload>();
 
-		form = new StatelessForm<Void>("form")
+		form = new StatelessForm<Void>(FORM_ID)
 		{
-			/**
-			 * 
-			 */
-			private static final long serialVersionUID = 1L;
-
 			@Override
 			protected void onSubmit()
 			{
@@ -61,7 +59,7 @@ public class MockPageWithFormAndUploadField extends WebPage
 				}
 			}
 		};
-		fileUploadField = new FileUploadField("upload", model);
+		fileUploadField = new FileUploadField(FILE_UPLOAD_ID, model);
 		form.add(fileUploadField);
 		add(form);
 	}


[4/4] wicket git commit: WICKET-5924 FileUploadField does not work with Spring Boot

Posted by mg...@apache.org.
WICKET-5924 FileUploadField does not work with Spring Boot

Add some documentation


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/07f4872d
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/07f4872d
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/07f4872d

Branch: refs/heads/master
Commit: 07f4872d848d06d29ff82554bd0dfdae59c7a7f7
Parents: a6988b0
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Sun Jun 28 22:56:44 2015 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Jun 28 22:56:44 2015 +0300

----------------------------------------------------------------------
 .../servlet/MultipartServletWebRequestImpl.java | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/07f4872d/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
index 05aa17a..37c90b0 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
@@ -191,10 +191,13 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 		}
 		else
 		{
+			// try to parse the file uploads by using Apache Commons FileUpload APIs
+			// because they are feature richer (e.g. progress updates, cleaner)
 			items = fileUpload.parseRequest(new ServletRequestContext(request));
 			if (items.isEmpty())
 			{
-				items = readParts(request);
+				// fallback to Servlet 3.0 APIs
+				items = readServlet3Parts(request);
 			}
 		}
 
@@ -239,7 +242,18 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 		}
 	}
 
-	private List<FileItem> readParts(HttpServletRequest request) throws FileUploadException
+	/**
+	 * Reads the uploads' parts by using Servlet 3.0 APIs.
+	 *
+	 * <strong>Note</strong>: By using Servlet 3.0 APIs the application won't be able to use
+	 * upload progress updates.
+	 *
+	 * @param request
+	 *              The http request with the upload data
+	 * @return A list of {@link FileItem}s
+	 * @throws FileUploadException
+	 */
+	private List<FileItem> readServlet3Parts(HttpServletRequest request) throws FileUploadException
 	{
 		List<FileItem> itemsFromParts = new ArrayList<>();
 		try
@@ -255,7 +269,7 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 			}
 		} catch (IOException | ServletException e)
 		{
-			throw new FileUploadException("", e);
+			throw new FileUploadException("An error occurred while reading the upload parts", e);
 		}
 		return itemsFromParts;
 	}


[2/4] wicket git commit: WICKET-5924 FileUploadField does not work with Spring Boot

Posted by mg...@apache.org.
WICKET-5924 FileUploadField does not work with Spring Boot

Add support for reading file uploads from Servlet request's parts


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/8b9c87ac
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/8b9c87ac
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/8b9c87ac

Branch: refs/heads/master
Commit: 8b9c87ac745654757c63d9aafa67d2e594f1e43f
Parents: 0c71fa4
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Fri Jun 26 14:40:33 2015 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Jun 28 21:42:32 2015 +0300

----------------------------------------------------------------------
 .../servlet/MultipartServletWebRequestImpl.java | 187 ++++++++++++++++++-
 1 file changed, 186 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/8b9c87ac/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
index 3609b3b..46aafb0 100644
--- a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
+++ b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
@@ -16,28 +16,37 @@
  */
 package org.apache.wicket.protocol.http.servlet;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
 
 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileItemHeaders;
 import org.apache.commons.fileupload.FileUploadBase;
 import org.apache.commons.fileupload.FileUploadException;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 import org.apache.commons.fileupload.servlet.ServletRequestContext;
+import org.apache.commons.fileupload.util.FileItemHeadersImpl;
 import org.apache.commons.io.FileCleaningTracker;
 import org.apache.wicket.Application;
 import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.util.file.FileCleanerTrackerAdapter;
 import org.apache.wicket.util.file.IFileCleaner;
+import org.apache.wicket.util.io.ByteArrayOutputStream;
+import org.apache.wicket.util.io.Streams;
 import org.apache.wicket.util.lang.Args;
 import org.apache.wicket.util.lang.Bytes;
 import org.apache.wicket.util.string.StringValue;
@@ -162,7 +171,7 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 
 		FileUploadBase fileUpload = newFileUpload(encoding);
 
-		final List<FileItem> items;
+		List<FileItem> items;
 
 		if (wantUploadProgressUpdates())
 		{
@@ -189,6 +198,10 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 		else
 		{
 			items = fileUpload.parseRequest(new ServletRequestContext(request));
+			if (items.isEmpty())
+			{
+				items = readParts(request);
+			}
 		}
 
 		// Loop through items
@@ -232,6 +245,27 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 		}
 	}
 
+	private List<FileItem> readParts(HttpServletRequest request) throws FileUploadException
+	{
+		List<FileItem> itemsFromParts = new ArrayList<>();
+		try
+		{
+			Collection<Part> parts = request.getParts();
+			if (parts != null)
+			{
+				for (Part part : parts)
+				{
+					FileItem fileItem = new PartFileItem(part);
+					itemsFromParts.add(fileItem);
+				}
+			}
+		} catch (IOException | ServletException e)
+		{
+			throw new FileUploadException("", e);
+		}
+		return itemsFromParts;
+	}
+
 	/**
 	 * Factory method for creating new instances of FileUploadBase
 	 *
@@ -530,4 +564,155 @@ public class MultipartServletWebRequestImpl extends MultipartServletWebRequest
 		Args.notNull(upload, "upload");
 		req.getSession().removeAttribute(getSessionKey(upload));
 	}
+
+	private static class PartFileItem implements FileItem
+	{
+		private final Part part;
+
+		private PartFileItem(Part part) {
+			this.part = part;
+		}
+
+		@Override
+		public InputStream getInputStream() throws IOException
+		{
+			return part.getInputStream();
+		}
+
+		@Override
+		public String getContentType()
+		{
+			return part.getContentType();
+		}
+
+		@Override
+		public String getName()
+		{
+			return getFileName(part);
+		}
+
+		private String getFileName(Part part) {
+			for (String cd : part.getHeader("content-disposition").split(";")) {
+				if (cd.trim().startsWith("filename")) {
+					return cd.substring(cd.indexOf('=') + 1).trim()
+							.replace("\"", "");
+				}
+			}
+			return null;
+		}
+
+		@Override
+		public boolean isInMemory()
+		{
+			return true;
+		}
+
+		@Override
+		public long getSize()
+		{
+			return part.getSize();
+		}
+
+		@Override
+		public byte[] get()
+		{
+			try
+			{
+				ByteArrayOutputStream baos = new ByteArrayOutputStream();
+				Streams.copy(getInputStream() ,baos);
+				return baos.toByteArray();
+			} catch (IOException iox)
+			{
+				throw new WicketRuntimeException("Could not read upload's part input stream", iox);
+			}
+		}
+
+		@Override
+		public String getString(String encoding) throws UnsupportedEncodingException
+		{
+			byte[] bytes = get();
+			return new String(bytes, encoding);
+		}
+
+		@Override
+		public String getString()
+		{
+			try
+			{
+				return getString("UTF-8");
+			} catch (UnsupportedEncodingException uex)
+			{
+				throw new WicketRuntimeException("UTF-8 must be supported", uex);
+			}
+		}
+
+		@Override
+		public void write(File file) throws Exception
+		{
+			part.write(file.getName());
+		}
+
+		@Override
+		public void delete()
+		{
+			try
+			{
+				part.delete();
+			} catch (IOException iox)
+			{
+				throw new WicketRuntimeException("A problem occurred while deleting an upload part", iox);
+			}
+		}
+
+		@Override
+		public String getFieldName()
+		{
+			return part.getName();
+		}
+
+		@Override
+		public void setFieldName(String name)
+		{
+			throw new UnsupportedOperationException("setFieldName");
+		}
+
+		@Override
+		public boolean isFormField()
+		{
+			return false;
+		}
+
+		@Override
+		public void setFormField(boolean state)
+		{
+			throw new UnsupportedOperationException("setFormField");
+		}
+
+		@Override
+		public OutputStream getOutputStream() throws IOException
+		{
+			throw new UnsupportedOperationException("getOutputStream");
+		}
+
+		@Override
+		public FileItemHeaders getHeaders()
+		{
+			FileItemHeadersImpl fileItemHeaders = new FileItemHeadersImpl();
+			for (String headerName : part.getHeaderNames())
+			{
+				Collection<String> headerValues = part.getHeaders(headerName);
+				for (String headerValue : headerValues)
+				{
+					fileItemHeaders.addHeader(headerName, headerValue);
+				}
+			}
+			return fileItemHeaders;
+		}
+
+		@Override
+		public void setHeaders(FileItemHeaders headers)
+		{
+			throw new UnsupportedOperationException("setHeaders");
+		}
+	}
 }