You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2019/01/25 18:04:03 UTC
[myfaces-tobago] branch tobago-2.x updated: TOBAGO-1976: Backport
to 2.x: Using Servlet 3.0 for uploading files with
This is an automated email from the ASF dual-hosted git repository.
lofwyr pushed a commit to branch tobago-2.x
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git
The following commit(s) were added to refs/heads/tobago-2.x by this push:
new 4546968 TOBAGO-1976: Backport to 2.x: Using Servlet 3.0 for uploading files with <tc:file>
4546968 is described below
commit 45469686ea6e7dcbb2489cd30fa3fbdaad71c166
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Fri Jan 25 19:03:41 2019 +0100
TOBAGO-1976: Backport to 2.x: Using Servlet 3.0 for uploading files with <tc:file>
---
pom.xml | 14 +-
tobago-assembly/pom.xml | 16 +-
tobago-core/pom.xml | 6 +-
.../tobago/internal/component/AbstractUIFile.java | 6 +-
.../tobago/internal/component/AbstractUIPage.java | 30 --
.../taglib/component/FileDropTagDeclaration.java | 8 +-
.../taglib/component/FileTagDeclaration.java | 8 +-
.../tobago/internal/util/HttpPartWrapper.java | 115 +++++++
.../myfaces/tobago/internal/util/PartUtils.java | 331 +++++++++++++++++++++
.../webapp/TobagoMultipartFormdataRequest.java | 221 --------------
.../tobago/validator/FileItemValidator.java | 4 +-
.../webapp/TobagoMultipartFormdataFilter.java | 86 +-----
.../tobago/internal/util/PartUtilsUnitTest.java | 89 ++++++
.../TobagoMultipartFormdataRequestUnitTest.java | 165 ----------
tobago-example/pom.xml | 2 +-
.../tobago-example-addressbook-cdi/pom.xml | 2 +-
.../tobago/example/addressbook/Picture.java | 8 +-
.../tobago/example/addressbook/web/Controller.java | 12 +-
.../src/main/webapp/WEB-INF/web.xml | 2 +
tobago-example/tobago-example-addressbook/pom.xml | 2 +-
.../tobago/example/addressbook/Picture.java | 8 +-
.../tobago/example/addressbook/web/Controller.java | 12 +-
.../src/main/webapp/WEB-INF/web.xml | 9 +-
tobago-example/tobago-example-assembly/pom.xml | 2 +-
tobago-example/tobago-example-blank/pom.xml | 2 +-
.../src/main/webapp/WEB-INF/web.xml | 14 -
tobago-example/tobago-example-data/pom.xml | 2 +-
tobago-example/tobago-example-demo/pom.xml | 2 +-
.../apache/myfaces/tobago/example/demo/Upload.java | 76 ++---
.../myfaces/tobago/example/demo/UploadItem.java | 6 +-
.../src/main/webapp/WEB-INF/web.xml | 35 +--
.../src/main/webapp/content/40-upload/upload.xhtml | 23 +-
tobago-example/tobago-example-portlet/pom.xml | 2 +-
tobago-example/tobago-example-sandbox/pom.xml | 2 +-
.../src/main/webapp/WEB-INF/web.xml | 23 +-
tobago-example/tobago-example-security/pom.xml | 2 +-
.../src/main/webapp/WEB-INF/web.xml | 9 +-
tobago-example/tobago-example-test/pom.xml | 2 +-
.../src/main/webapp/WEB-INF/web.xml | 36 +--
tobago-extension/pom.xml | 2 +-
tobago-extension/tobago-deprecation/pom.xml | 2 +-
tobago-extension/tobago-fileupload/pom.xml | 2 +-
.../FileUploadFacesContextFactoryImpl.java | 108 +------
tobago-extension/tobago-sandbox/pom.xml | 2 +-
tobago-extension/tobago-security/pom.xml | 2 +-
tobago-theme/pom.xml | 2 +-
tobago-theme/tobago-theme-charlotteville/pom.xml | 2 +-
tobago-theme/tobago-theme-example/pom.xml | 2 +-
tobago-theme/tobago-theme-richmond/pom.xml | 2 +-
tobago-theme/tobago-theme-scarborough/pom.xml | 2 +-
tobago-theme/tobago-theme-speyside/pom.xml | 2 +-
tobago-theme/tobago-theme-standard/pom.xml | 2 +-
.../html/standard/standard/tag/FileRenderer.java | 100 ++++---
tobago-tool/pom.xml | 2 +-
tobago-tool/tobago-theme-plugin/pom.xml | 2 +-
tobago-tool/tobago-tool-annotation/pom.xml | 2 +-
tobago-tool/tobago-tool-apt/pom.xml | 2 +-
57 files changed, 769 insertions(+), 865 deletions(-)
diff --git a/pom.xml b/pom.xml
index 3035c1a..3e9ca16 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,7 +26,7 @@
<artifactId>tobago</artifactId>
<packaging>pom</packaging>
<name>Apache Tobago</name>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
<description>The goal of Tobago is to provide the community with a well designed set of user interface components based on JSF and run on MyFaces.</description>
<prerequisites>
<maven>3.0.4</maven>
@@ -207,7 +207,6 @@
<link>http://download.oracle.com/javaee/5/api/</link>
<link>http://jakarta.apache.org/commons/collections/api-${commons-collection.version}/</link>
<link>http://jakarta.apache.org/commons/lang/api-${commons-lang.version}/</link>
- <link>http://jakarta.apache.org/commons/fileupload/apidocs</link>
<link>http://jakarta.apache.org/commons/io/api-${commons-io.version}/</link>
<link>http://jakarta.apache.org/commons/logging/commons-logging-${commons-logging.version}/apidocs/</link>
<link>http://www.slf4j.org/apidocs</link>
@@ -416,9 +415,9 @@
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-servlet_2.5_spec</artifactId>
- <version>1.2</version>
+ <artifactId>geronimo-servlet_3.0_spec</artifactId>
<scope>provided</scope>
+ <version>1.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -478,11 +477,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>commons-fileupload</groupId>
- <artifactId>commons-fileupload</artifactId>
- <version>1.3.3</version>
- </dependency>
- <dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.4</version>
@@ -574,7 +568,7 @@
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-servlet_2.5_spec</artifactId>
+ <artifactId>geronimo-servlet_3.0_spec</artifactId>
</dependency>
<dependency>
diff --git a/tobago-assembly/pom.xml b/tobago-assembly/pom.xml
index 7c95ac0..1c0cdf2 100644
--- a/tobago-assembly/pom.xml
+++ b/tobago-assembly/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<dependencies>
@@ -84,19 +84,13 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>tobago-fileupload</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
- <artifactId>geronimo-servlet_2.5_spec</artifactId>
- <scope>provided</scope>
+ <artifactId>geronimo-servlet_3.0_spec</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -269,12 +263,6 @@
<version>${project.version}</version>
<classifier>sources</classifier>
</artifactItem>
- <artifactItem>
- <groupId>${project.groupId}</groupId>
- <artifactId>tobago-fileupload</artifactId>
- <version>${project.version}</version>
- <classifier>sources</classifier>
- </artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/src
diff --git a/tobago-core/pom.xml b/tobago-core/pom.xml
index 9d9917b..e847c9f 100644
--- a/tobago-core/pom.xml
+++ b/tobago-core/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-core</artifactId>
<packaging>jar</packaging>
@@ -163,10 +163,6 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>commons-fileupload</groupId>
- <artifactId>commons-fileupload</artifactId>
- </dependency>
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
index d3e69c5..2c03cef 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
@@ -19,7 +19,6 @@
package org.apache.myfaces.tobago.internal.component;
-import org.apache.commons.fileupload.FileItem;
import org.apache.myfaces.tobago.component.UIFileInput;
import org.apache.myfaces.tobago.layout.LayoutComponent;
import org.apache.myfaces.tobago.util.MessageUtils;
@@ -27,13 +26,14 @@ import org.apache.myfaces.tobago.util.MessageUtils;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
+import javax.servlet.http.Part;
public abstract class AbstractUIFile extends UIInput implements LayoutComponent, UIFileInput {
public void validate(final FacesContext facesContext) {
if (isRequired()) {
- if (getSubmittedValue() instanceof FileItem) {
- final FileItem file = (FileItem) getSubmittedValue();
+ if (getSubmittedValue() instanceof Part) {
+ final Part file = (Part) getSubmittedValue();
if (file == null || file.getName().length() == 0) {
addErrorMessage(facesContext);
setValid(false);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java
index e19978e..2c8a8e5 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java
@@ -31,7 +31,6 @@ import org.apache.myfaces.tobago.internal.ajax.AjaxResponseRenderer;
import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
import org.apache.myfaces.tobago.internal.util.Deprecation;
import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
-import org.apache.myfaces.tobago.internal.webapp.TobagoMultipartFormdataRequest;
import org.apache.myfaces.tobago.layout.Box;
import org.apache.myfaces.tobago.layout.LayoutComponent;
import org.apache.myfaces.tobago.layout.LayoutContainer;
@@ -52,13 +51,10 @@ import org.slf4j.LoggerFactory;
import javax.el.ELContext;
import javax.el.ValueExpression;
-import javax.faces.application.FacesMessage;
import javax.faces.component.ContextCallback;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
@@ -125,8 +121,6 @@ public abstract class AbstractUIPage extends AbstractUIForm
private void processDecodes0(final FacesContext facesContext) {
- checkTobagoRequest(facesContext);
-
decode(facesContext);
markSubmittedForm(facesContext);
@@ -283,30 +277,6 @@ public abstract class AbstractUIPage extends AbstractUIForm
}
}
- private void checkTobagoRequest(final FacesContext facesContext) {
- // multipart/form-data must use TobagoMultipartFormdataRequest
- final String contentType = facesContext.getExternalContext().getRequestHeaderMap().get("content-type");
- if (contentType != null && contentType.startsWith("multipart/form-data")) {
- final Object request = facesContext.getExternalContext().getRequest();
- boolean okay = false;
- if (request instanceof TobagoMultipartFormdataRequest) {
- okay = true;
- } else if (request instanceof HttpServletRequestWrapper) {
- final ServletRequest wrappedRequest = ((HttpServletRequestWrapper) request).getRequest();
- if (wrappedRequest instanceof TobagoMultipartFormdataRequest) {
- okay = true;
- }
- }
- // TODO PortletRequest ??
- if (!okay) {
- LOG.error("Can't process multipart/form-data without TobagoRequest. "
- + "Please check the web.xml and define a TobagoMultipartFormdataFilter. "
- + "See documentation for <tc:file>");
- facesContext.addMessage(null, new FacesMessage("An error has occurred!"));
- }
- }
- }
-
/**
* @deprecated PageState is deprecated since 1.5.0
*/
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileDropTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileDropTagDeclaration.java
index 9a60800..f4db455 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileDropTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileDropTagDeclaration.java
@@ -52,10 +52,6 @@ import javax.faces.component.UIInput;
/**
* Renders a file drop component.
* This component always makes a partial (ajax) upload!
- * You need to define an org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter in your web.xml or
- * add the tobago-fileupload.jar to your project.
- * The tobago-fileupload.jar contains a FacesContextFactory that wraps the
- * multipart-formdata request inside the facesContext.
* <p />
* For content constraints please use <a href="validateFileItem.html">tc:validateFileItem</a>.
*/
@@ -75,12 +71,12 @@ public interface FileDropTagDeclaration
/**
* Value binding expression pointing to a
- * <code>org.apache.commons.fileupload.FileItem</code> property to store the
+ * <code>javax.servlet.http.Part</code> property to store the
* uploaded file.
*/
@TagAttribute()
@UIComponentTagAttribute(
- type = { "org.apache.commons.fileupload.FileItem", "org.apache.commons.fileupload.FileItem[]" },
+ type = { "javax.servlet.http.Part", "org.apache.commons.fileupload.FileItem[]" },
expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
void setValue(String value);
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java
index f5b4e16..8a699b2 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java
@@ -51,10 +51,6 @@ import javax.faces.component.UIInput;
/**
* Renders a file input field.
- * You need to define an org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter in your web.xml or
- * add the tobago-fileupload.jar to your project.
- * The tobago-fileupload.jar contains a FacesContextFactory that wraps the
- * multipart-formdata request inside the facesContext.
* <p />
* For content constraints please use <a href="validateFileItem.html">tc:validateFileItem</a>.
*/
@@ -78,12 +74,12 @@ public interface FileTagDeclaration
/**
* Value binding expression pointing to a
- * <code>org.apache.commons.fileupload.FileItem</code> property to store the
+ * <code>javax.servlet.http.Part</code> property to store the
* uploaded file.
*/
@TagAttribute()
@UIComponentTagAttribute(
- type = { "org.apache.commons.fileupload.FileItem", "org.apache.commons.fileupload.FileItem[]" },
+ type = { "javax.servlet.http.Part", "javax.servlet.http.Part[]" },
expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
void setValue(String value);
}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HttpPartWrapper.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HttpPartWrapper.java
new file mode 100644
index 0000000..f898032
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HttpPartWrapper.java
@@ -0,0 +1,115 @@
+/*
+ * 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.myfaces.tobago.internal.util;
+
+import javax.faces.FacesException;
+import javax.faces.FacesWrapper;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+public class HttpPartWrapper implements Part, FacesWrapper<Part>, StateHolder {
+ private Part delegate;
+
+ public HttpPartWrapper() {
+ }
+
+ public HttpPartWrapper(Part delegate) {
+ this.delegate = delegate;
+ }
+
+ public void delete() throws IOException {
+ getWrapped().delete();
+ }
+
+ public String getContentType() {
+ return getWrapped().getContentType();
+ }
+
+ public String getHeader(String headerName) {
+ return getWrapped().getHeader(headerName);
+ }
+
+ public Collection<String> getHeaderNames() {
+ return getWrapped().getHeaderNames();
+ }
+
+ public Collection<String> getHeaders(String headerName) {
+ return getWrapped().getHeaders(headerName);
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return getWrapped().getInputStream();
+ }
+
+ public String getName() {
+ return getWrapped().getName();
+ }
+
+ public long getSize() {
+ return getWrapped().getSize();
+ }
+
+ public void write(String fileName) throws IOException {
+ getWrapped().write(fileName);
+ }
+
+ public String getSubmittedFileName() {
+ Part wrapped = getWrapped();
+ try {
+ Method m = wrapped.getClass().getMethod("getSubmittedFileName");
+ return (String) m.invoke(wrapped);
+ } catch (NoSuchMethodException ex) {
+ throw new FacesException(ex);
+ } catch (SecurityException ex) {
+ throw new FacesException(ex);
+ } catch (IllegalAccessException ex) {
+ throw new FacesException(ex);
+ } catch (IllegalArgumentException ex) {
+ throw new FacesException(ex);
+ } catch (InvocationTargetException ex) {
+ throw new FacesException(ex);
+ }
+ }
+
+ public Object saveState(FacesContext context) {
+ return null;
+ }
+
+ public void restoreState(FacesContext context, Object state) {
+ }
+
+ public boolean isTransient() {
+ return true;
+ }
+
+ public void setTransient(boolean newTransientValue) {
+ }
+
+ public Part getWrapped() {
+ return delegate;
+ }
+
+}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/PartUtils.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/PartUtils.java
new file mode 100644
index 0000000..04c90d8
--- /dev/null
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/PartUtils.java
@@ -0,0 +1,331 @@
+/*
+ * 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.myfaces.tobago.internal.util;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+import javax.servlet.http.Part;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Only needed for Servlet 3.0. Not needed for Servlet 3.1 or higher.
+ *
+ * Basically taken from Apache Tomcat 8
+ */
+public final class PartUtils {
+
+ private PartUtils() {
+ }
+
+ /**
+ * This is a helper method, to get the original file name of the upload.
+ * If you have at least Servlet 3.1, you wouldn't need this function.
+ *
+ * @since Tobago 3.0.0
+ */
+ public static String getSubmittedFileName(Part part) {
+
+ try { // try to call the Servlet 3.1 function
+ return (String) PropertyUtils.getProperty(part, "submittedFileName");
+ } catch (Exception e) {
+ // ignore
+ }
+
+ String fileName = null;
+ String cd = part.getHeader("Content-Disposition");
+ if (cd != null) {
+ String cdl = cd.toLowerCase(Locale.ENGLISH);
+ if (cdl.startsWith("form-data") || cdl.startsWith("attachment")) {
+ ParameterParser paramParser = new ParameterParser();
+ paramParser.setLowerCaseNames(true);
+ // Parameter parser can handle null input
+ Map<String, String> params =
+ paramParser.parse(cd, ';');
+ if (params.containsKey("filename")) {
+ fileName = params.get("filename");
+ if (fileName != null) {
+ fileName = fileName.trim();
+ // XXX seems to be wrong in the code?
+ fileName = fileName.replaceAll("\\\\\\\"", "\""); // replaces \" with "
+ } else {
+ // Even if there is no value, the parameter is present,
+ // so we return an empty file name rather than no file
+ // name.
+ fileName = "";
+ }
+ }
+ }
+ }
+ return fileName;
+ }
+
+ private static class ParameterParser {
+
+ /**
+ * String to be parsed.
+ */
+ private char[] chars = null;
+
+ /**
+ * Current position in the string.
+ */
+ private int pos = 0;
+
+ /**
+ * Maximum position in the string.
+ */
+ private int len = 0;
+
+ /**
+ * Start of a token.
+ */
+ private int i1 = 0;
+
+ /**
+ * End of a token.
+ */
+ private int i2 = 0;
+
+ /**
+ * Whether names stored in the map should be converted to lower case.
+ */
+ private boolean lowerCaseNames = false;
+
+ /**
+ * Default ParameterParser constructor.
+ */
+ public ParameterParser() {
+ super();
+ }
+
+ /**
+ * Are there any characters left to parse?
+ *
+ * @return {@code true} if there are unparsed characters,
+ * {@code false} otherwise.
+ */
+ private boolean hasChar() {
+ return this.pos < this.len;
+ }
+
+ /**
+ * A helper method to process the parsed token. This method removes
+ * leading and trailing blanks as well as enclosing quotation marks,
+ * when necessary.
+ *
+ * @param quoted {@code true} if quotation marks are expected,
+ * {@code false} otherwise.
+ * @return the token
+ */
+ private String getToken(boolean quoted) {
+ // Trim leading white spaces
+ while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
+ i1++;
+ }
+ // Trim trailing white spaces
+ while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
+ i2--;
+ }
+ // Strip away quotation marks if necessary
+ if (quoted
+ && ((i2 - i1) >= 2)
+ && (chars[i1] == '"')
+ && (chars[i2 - 1] == '"')) {
+ i1++;
+ i2--;
+ }
+ String result = null;
+ if (i2 > i1) {
+ result = new String(chars, i1, i2 - i1);
+ }
+ return result;
+ }
+
+ /**
+ * Tests if the given character is present in the array of characters.
+ *
+ * @param ch the character to test for presense in the array of characters
+ * @param charray the array of characters to test against
+ * @return {@code true} if the character is present in the array of
+ * characters, {@code false} otherwise.
+ */
+ private boolean isOneOf(char ch, final char[] charray) {
+ boolean result = false;
+ for (char element : charray) {
+ if (ch == element) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parses out a token until any of the given terminators
+ * is encountered.
+ *
+ * @param terminators the array of terminating characters. Any of these
+ * characters when encountered signify the end of the token
+ * @return the token
+ */
+ private String parseToken(final char[] terminators) {
+ char ch;
+ i1 = pos;
+ i2 = pos;
+ while (hasChar()) {
+ ch = chars[pos];
+ if (isOneOf(ch, terminators)) {
+ break;
+ }
+ i2++;
+ pos++;
+ }
+ return getToken(false);
+ }
+
+ /**
+ * Parses out a token until any of the given terminators
+ * is encountered outside the quotation marks.
+ *
+ * @param terminators the array of terminating characters. Any of these
+ * characters when encountered outside the quotation marks signify the end
+ * of the token
+ * @return the token
+ */
+ private String parseQuotedToken(final char[] terminators) {
+ char ch;
+ i1 = pos;
+ i2 = pos;
+ boolean quoted = false;
+ boolean charEscaped = false;
+ while (hasChar()) {
+ ch = chars[pos];
+ if (!quoted && isOneOf(ch, terminators)) {
+ break;
+ }
+ if (!charEscaped && ch == '"') {
+ quoted = !quoted;
+ }
+ charEscaped = (!charEscaped && ch == '\\');
+ i2++;
+ pos++;
+
+ }
+ return getToken(true);
+ }
+
+ /**
+ * Sets the flag if parameter names are to be converted to lower case when
+ * name/value pairs are parsed.
+ *
+ * @param b {@code true} if parameter names are to be
+ * converted to lower case when name/value pairs are parsed.
+ * {@code false} otherwise.
+ */
+ public void setLowerCaseNames(boolean b) {
+ this.lowerCaseNames = b;
+ }
+
+ /**
+ * Extracts a map of name/value pairs from the given string. Names are
+ * expected to be unique.
+ *
+ * @param str the string that contains a sequence of name/value pairs
+ * @param separator the name/value pairs separator
+ * @return a map of name/value pairs
+ */
+ public Map<String, String> parse(final String str, char separator) {
+ if (str == null) {
+ return new HashMap<String, String>();
+ }
+ return parse(str.toCharArray(), separator);
+ }
+
+ /**
+ * Extracts a map of name/value pairs from the given array of
+ * characters. Names are expected to be unique.
+ *
+ * @param charArray the array of characters that contains a sequence of
+ * name/value pairs
+ * @param separator the name/value pairs separator
+ * @return a map of name/value pairs
+ */
+ public Map<String, String> parse(final char[] charArray, char separator) {
+ if (charArray == null) {
+ return new HashMap<String, String>();
+ }
+ return parse(charArray, 0, charArray.length, separator);
+ }
+
+ /**
+ * Extracts a map of name/value pairs from the given array of
+ * characters. Names are expected to be unique.
+ *
+ * @param charArray the array of characters that contains a sequence of
+ * name/value pairs
+ * @param offset - the initial offset.
+ * @param length - the length.
+ * @param separator the name/value pairs separator
+ * @return a map of name/value pairs
+ */
+ public Map<String, String> parse(
+ final char[] charArray,
+ int offset,
+ int length,
+ char separator) {
+
+ if (charArray == null) {
+ return new HashMap<String, String>();
+ }
+ HashMap<String, String> params = new HashMap<String, String>();
+ this.chars = charArray;
+ this.pos = offset;
+ this.len = length;
+
+ String paramName;
+ String paramValue;
+ while (hasChar()) {
+ paramName = parseToken(new char[]{
+ '=', separator
+ });
+ paramValue = null;
+ if (hasChar() && (charArray[pos] == '=')) {
+ pos++; // skip '='
+ paramValue = parseQuotedToken(new char[]{
+ separator
+ });
+ }
+ if (hasChar() && (charArray[pos] == separator)) {
+ pos++; // skip separator
+ }
+ if ((paramName != null) && (paramName.length() > 0)) {
+ if (this.lowerCaseNames) {
+ paramName = paramName.toLowerCase(Locale.ENGLISH);
+ }
+
+ params.put(paramName, paramValue);
+ }
+ }
+ return params;
+ }
+ }
+}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoMultipartFormdataRequest.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoMultipartFormdataRequest.java
deleted file mode 100644
index da5a254..0000000
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoMultipartFormdataRequest.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * 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.myfaces.tobago.internal.webapp;
-
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.myfaces.tobago.internal.component.AbstractUIPage;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.faces.FacesException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-public class TobagoMultipartFormdataRequest extends HttpServletRequestWrapper {
-
- private static final Logger LOG = LoggerFactory.getLogger(TobagoMultipartFormdataRequest.class);
-
- public static final long ONE_KB = 1024;
- public static final long ONE_MB = ONE_KB * ONE_KB;
- public static final long ONE_GB = ONE_KB * ONE_MB;
-
- private Map<String, String[]> parameters;
-
- private Map<String, List<FileItem>> fileItems;
-
- public TobagoMultipartFormdataRequest(final HttpServletRequest request) {
- this(request, System.getProperty("java.io.tmpdir"), ONE_MB);
- }
-
- public TobagoMultipartFormdataRequest(
- final HttpServletRequest request, final String repositoryPath, final long maxSize) {
- super(request);
- init(request, repositoryPath, maxSize);
- }
-
- private void init(final HttpServletRequest request, final String repositoryPath, final long maxSize) {
- if (!ServletFileUpload.isMultipartContent(request)) {
- final String errorText = "contentType is not multipart/form-data but '" + request.getContentType() + "'";
- LOG.error(errorText);
- throw new FacesException(errorText);
- } else {
- parameters = new HashMap<String, String[]>();
- fileItems = new HashMap<String, List<FileItem>>();
- final DiskFileItemFactory factory = new DiskFileItemFactory();
-
- factory.setRepository(new File(repositoryPath));
-
- final ServletFileUpload upload = new ServletFileUpload(factory);
-
- upload.setSizeMax(maxSize);
-
- if (upload.getHeaderEncoding() != null) {
- // TODO: enable configuration of 'accept-charset'
- upload.setHeaderEncoding(AbstractUIPage.FORM_ACCEPT_CHARSET);
- }
- final List<FileItem> itemList;
- try {
- itemList = (List<FileItem>) upload.parseRequest(request);
- } catch (final FileUploadException e) {
- //LOG.error(e);
- throw new FacesException(e);
- }
- if (LOG.isDebugEnabled()) {
- LOG.debug("parametercount = " + itemList.size() + " + " + request.getParameterMap().size());
- }
- for (final FileItem item : itemList) {
- final String key = item.getFieldName();
- if (LOG.isDebugEnabled()) {
- String value = item.getString();
- if (value.length() > 100) {
- value = value.substring(0, 100) + " [...]";
- }
- LOG.debug("Parameter: '" + key + "'='" + value + "' isFormField=" + item.isFormField()
- + " contentType='" + item.getContentType() + "'");
- }
- if (item.isFormField()) {
- String newValue;
- try {
- // TODO: enable configuration of 'accept-charset'
- newValue = item.getString(AbstractUIPage.FORM_ACCEPT_CHARSET);
- } catch (final UnsupportedEncodingException e) {
- LOG.error("Caught: " + e.getMessage(), e);
- newValue = item.getString();
- }
-
- addParameter(key, newValue);
- } else {
- List<FileItem> help = this.fileItems.get(key);
- if (help == null) {
- help = new ArrayList<FileItem>();
- this.fileItems.put(key, help);
- }
- help.add(item);
- }
- }
-
- // merging the GET parameters:
- final Enumeration e = request.getParameterNames();
- while(e.hasMoreElements()) {
- final String name = (String) e.nextElement();
- final String[] newValues = request.getParameterValues(name);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Parameter: '" + name + "'='" + Arrays.toString(newValues) + "' (GET)");
- }
- for (final String newValue : newValues) {
- addParameter(name, newValue);
- }
- }
- }
- }
-
- private void addParameter(final String key, final String newValue) {
- final String[] inStock = parameters.get(key);
- final String[] values;
- if (inStock == null) {
- values = new String[]{newValue};
- } else {
- values = new String[inStock.length + 1];
- System.arraycopy(inStock, 0, values, 0, inStock.length);
- values[inStock.length] = newValue;
- }
- parameters.put(key, values);
- }
-
- public FileItem getFileItem(final String key) {
- if (fileItems != null) {
- final List<FileItem> fileItemsForKey = this.fileItems.get(key);
- if (fileItemsForKey != null && fileItemsForKey.size() > 0) {
- return fileItemsForKey.get(0);
- } else {
- return null;
- }
- }
- return null;
- }
-
- public FileItem[] getFileItems(final String key) {
- if (fileItems != null) {
- final List<FileItem> fileItemsForKey = this.fileItems.get(key);
- if (fileItemsForKey != null) {
- return fileItemsForKey.toArray(new FileItem[fileItemsForKey.size()]);
- }
- }
- return null;
- }
-
- public String getParameter(final String key) {
- String parameter = null;
- final String[] values = (String[]) parameters.get(key);
- if (values != null) {
- parameter = values[0];
- }
- return parameter;
- }
-
- public Enumeration getParameterNames() {
- return Collections.enumeration(parameters.keySet());
- }
-
- public String[] getParameterValues(final String key) {
- return (String[]) parameters.get(key);
- }
-
- public Map getParameterMap() {
- return parameters;
- }
-
- public static long getMaxSize(final String param) {
- if (param != null) {
- String number = param.toLowerCase(Locale.ENGLISH);
- long factor = 1;
- if (number.endsWith("g")) {
- factor = ONE_GB;
- number = number.substring(0, number.length() - 1);
- } else if (number.endsWith("m")) {
- factor = ONE_MB;
- number = number.substring(0, number.length() - 1);
- } else if (number.endsWith("k")) {
- factor = ONE_KB;
- number = number.substring(0, number.length() - 1);
- }
- try {
- return Long.parseLong(number.trim()) * factor;
- } catch (final NumberFormatException e) {
- LOG.error("Given max file size for "
- + TobagoMultipartFormdataRequest.class.getName() + " " + param + " couldn't parsed to a number");
- }
- }
- return ONE_MB;
- }
-}
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java
index 30864cd..14c648b 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java
@@ -19,7 +19,6 @@
package org.apache.myfaces.tobago.validator;
-import org.apache.commons.fileupload.FileItem;
import org.apache.myfaces.tobago.internal.component.AbstractUIFile;
import org.apache.myfaces.tobago.internal.util.ContentType;
import org.apache.myfaces.tobago.util.MessageUtils;
@@ -30,6 +29,7 @@ import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
+import javax.servlet.http.Part;
import java.util.Arrays;
/**
@@ -54,7 +54,7 @@ public class FileItemValidator implements Validator, StateHolder {
public void validate(final FacesContext facesContext, final UIComponent component, final Object value)
throws ValidatorException {
if (value != null && component instanceof AbstractUIFile) {
- final FileItem file = (FileItem) value;
+ final Part file = (Part) value;
if (maxSize != null && file.getSize() > maxSize) {
final FacesMessage facesMessage = MessageUtils.getMessage(
facesContext, facesContext.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR,
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataFilter.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataFilter.java
index 38ed8e8..17aa873 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataFilter.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataFilter.java
@@ -21,7 +21,6 @@ package org.apache.myfaces.tobago.webapp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.myfaces.tobago.internal.webapp.TobagoMultipartFormdataRequest;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -29,99 +28,24 @@ import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.io.File;
import java.io.IOException;
-import java.util.Locale;
-
/**
- * This filter handles multipart request. It must be enabled in the web.xml of your web application.
- * Usage:
- * <p/>
- * <p><blockquote><pre>
- * <filter>
- * <filter-name>multipartFormdataFilter</filter-name>
- * <filter-class>org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter</filter-class>
- * <init-param>
- * <description>Set the size limit for uploaded files. Default value is 1 MB.
- * Format: 10 = 10 bytes
- * 10k = 10 KB
- * 10m = 10 MB
- * 1g = 1 GB
- * </description>
- * <param-name>uploadMaxFileSize</param-name>
- * <param-value>20m</param-value>
- * </init-param>
- * <init-param>
- * <description>Set the upload repository path for uploaded files.
- * Default value is java.io.tmpdir.</description>
- * <param-name>uploadRepositoryPath</param-name>
- * <param-value>/tmp</param-value>
- * </init-param>
- * </filter>
- * <filter-mapping>
- * <filter-name>multipartFormdataFilter</filter-name>
- * <url-pattern>/faces/*</url-pattern>
- * </filter-mapping>
- * </pre></blockquote><p>
+ * @deprecated since 2.4.0
*/
+@Deprecated
public class TobagoMultipartFormdataFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(TobagoMultipartFormdataFilter.class);
- private String repositoryPath = System.getProperty("java.io.tmpdir");
- private long maxSize = TobagoMultipartFormdataRequest.ONE_MB;
-
public void init(final FilterConfig filterConfig) throws ServletException {
- final String repositoryPath = filterConfig.getInitParameter("uploadRepositoryPath");
- if (repositoryPath != null) {
- final File file = new File(repositoryPath);
- if (!file.exists()) {
- LOG.error("Given repository Path for " + getClass().getName() + " " + repositoryPath + " doesn't exists");
- } else if (!file.isDirectory()) {
- LOG.error("Given repository Path for " + getClass().getName() + " " + repositoryPath + " is not a directory");
- } else {
- this.repositoryPath = repositoryPath;
- }
- }
-
-
- maxSize = TobagoMultipartFormdataRequest.getMaxSize(filterConfig.getInitParameter("uploadMaxFileSize"));
- if (LOG.isInfoEnabled()) {
- LOG.info("Configure uploadRepositoryPath for " + getClass().getName() + " to " + this.repositoryPath);
- LOG.info("Configure uploadMaxFileSize for " + getClass().getName() + " to " + this.maxSize);
- }
-
+ LOG.error("This class is no longer needed! Please remove from web.xml. "
+ + "See the release notes for Tobago 2.4.0.");
}
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
- final ServletRequest wrapper;
- if (request instanceof HttpServletRequest) {
- if (request instanceof TobagoMultipartFormdataRequest) {
- wrapper = request;
- } else {
- final String contentType = request.getContentType();
- if (contentType != null
- && contentType.toLowerCase(Locale.ENGLISH).startsWith("multipart/form-data")) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Wrapping " + request.getClass().getName()
- + " with ContentType=\"" + contentType + "\" "
- + "into TobagoMultipartFormdataRequest");
- }
- wrapper = new TobagoMultipartFormdataRequest(
- (HttpServletRequest) request, repositoryPath, maxSize);
- } else {
- wrapper = request;
- }
- }
- } else {
- LOG.error("Not implemented for non HttpServletRequest");
- wrapper = request;
- }
-
- chain.doFilter(wrapper, response);
+ chain.doFilter(request, response);
}
public void destroy() {
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/PartUtilsUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/PartUtilsUnitTest.java
new file mode 100644
index 0000000..298f295
--- /dev/null
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/PartUtilsUnitTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.myfaces.tobago.internal.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+public class PartUtilsUnitTest {
+
+ @Test
+ public void testGetSubmittedFileName() throws Exception {
+
+ final String dc0 = "form-data; name=\"page:file\"; filename=\"foo.jpg\"";
+ Assert.assertEquals("foo.jpg", PartUtils.getSubmittedFileName(new PartMock(dc0)));
+
+ final String dc1 = "form-data; name=\"page:file\"; filename=\"foo;bar=\\\"boo\\\"-bar.jpg\"";
+ Assert.assertEquals("foo;bar=\"boo\"-bar.jpg", PartUtils.getSubmittedFileName(new PartMock(dc1)));
+ }
+
+ private static final class PartMock implements Part {
+
+ private String contentDisposition;
+
+ public PartMock(String contentDisposition) {
+ this.contentDisposition = contentDisposition;
+ }
+
+ public void delete() throws IOException {
+ }
+
+ public String getContentType() {
+ return null;
+ }
+
+ public String getHeader(String headerName) {
+ if (headerName.equals("Content-Disposition")) {
+ return contentDisposition;
+ } else {
+ return null;
+ }
+ }
+
+ public Collection<String> getHeaderNames() {
+ return null;
+ }
+
+ public Collection<String> getHeaders(String headerName) {
+ return null;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return null;
+ }
+
+ public String getName() {
+ return null;
+ }
+
+ public long getSize() {
+ return 0;
+ }
+
+ public void write(String fileName) throws IOException {
+
+ }
+ }
+}
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataRequestUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataRequestUnitTest.java
deleted file mode 100644
index d4c6908..0000000
--- a/tobago-core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataRequestUnitTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.myfaces.tobago.webapp;
-
-import org.apache.commons.fileupload.FileItem;
-import org.apache.myfaces.tobago.internal.mock.servlet.MockHttpServletRequest;
-import org.apache.myfaces.tobago.internal.webapp.TobagoMultipartFormdataRequest;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class TobagoMultipartFormdataRequestUnitTest {
-
- private static final String SNIP = "--";
-
- private static final String BOUNDARY = "xxx";
-
- private static final String NEWLINE = "\r\n";
-
- private TobagoMultipartFormdataRequest request;
-
- public TobagoMultipartFormdataRequestUnitTest() throws UnsupportedEncodingException {
- final String body
- = SNIP + BOUNDARY + NEWLINE
- + parameter("color", "red")
- + parameter("city", "Amsterdam")
- + parameter("city", "Bonn")
- + parameter("city", "Pisa")
- + parameter("color", "green")
- + fileItem("file", "hello.txt", "Hello World!")
- + parameter("color", "blue")
- + parameter("color", "yellow")
- + parameter("country", "Trinidad & Tobago")
- + SNIP + BOUNDARY + SNIP + NEWLINE;
-
- final MockHttpServletRequest mockRequest
- = new MockHttpServletRequest(body.getBytes("UTF-8"));
- mockRequest.setMethod("post");
-
- request = new TobagoMultipartFormdataRequest(mockRequest, System.getProperty("java.io.tmpdir"), 1024 * 1024);
- }
-
- private String parameter(final String key, final String value) {
- return SNIP + BOUNDARY + NEWLINE
- + "Content-Disposition: form-data; name=\"" + key + "\"" + NEWLINE
- + NEWLINE
- + value + NEWLINE;
- }
-
- private String fileItem(final String key, final String filename, final String value) {
- return SNIP + BOUNDARY + NEWLINE
- + "Content-Disposition: form-data; name=\""
- + key + "\"; filename=\"" + filename + "\"" + NEWLINE
- + "Content-Type: text/plain" + NEWLINE
- + NEWLINE
- + value + NEWLINE;
- }
-
- @Test
- public void testGetFileItem() {
-
- final FileItem item = request.getFileItem("file");
- Assert.assertNotNull(item);
- Assert.assertEquals("filename", "hello.txt", item.getName());
- Assert.assertEquals("content", "Hello World!", item.getString());
- }
-
- @Test
- public void testGetParameter() {
-
- Assert.assertEquals("red", request.getParameter("color"));
- Assert.assertEquals("Amsterdam", request.getParameter("city"));
- Assert.assertEquals("Trinidad & Tobago", request.getParameter("country"));
- Assert.assertEquals(null, request.getParameter("empty"));
- }
-
- @Test
- public void testGetParameterValues() {
-
- Set<String> expectedSet;
- Set<String> actualSet;
-
- expectedSet = new HashSet<String>(
- Arrays.asList("red", "green", "blue", "yellow"));
- actualSet
- = new HashSet<String>(Arrays.asList(request.getParameterValues("color")));
- Assert.assertEquals("color", expectedSet, actualSet);
-
- expectedSet = new HashSet<String>(
- Arrays.asList("Amsterdam", "Bonn", "Pisa"));
- actualSet = new HashSet<String>(Arrays.asList(request.getParameterValues("city")));
- Assert.assertEquals("city", expectedSet, actualSet);
-
- expectedSet = new HashSet<String>(
- Arrays.asList("Trinidad & Tobago"));
- actualSet
- = new HashSet<String>(Arrays.asList(request.getParameterValues("country")));
- Assert.assertEquals("country", expectedSet, actualSet);
-
- Assert.assertEquals("empty", null, request.getParameterValues("empty"));
- }
-
- @Test
- public void testGetParameterNames() {
-
- final Set<Object> actual = new HashSet<Object>();
- final Enumeration e = request.getParameterNames();
- while (e.hasMoreElements()) {
- actual.add(e.nextElement());
- }
-
- final Set<String> expected = new HashSet<String>(
- Arrays.asList("color", "city", "country"));
-
- Assert.assertEquals(expected, actual);
- }
-
- @Test
- public void testGetParameterMap() {
-
- final Map actual = request.getParameterMap();
-
- final Map<String, String[]> expected = new HashMap<String, String[]>();
- expected.put("color", new String[]{"red", "green", "blue", "yellow"});
- expected.put("city", new String[]{"Amsterdam", "Bonn", "Pisa"});
- expected.put("country", new String[]{"Trinidad & Tobago"});
-
- Assert.assertEquals(expected.keySet(), actual.keySet());
-
- final Set keys = actual.keySet();
- for (final Object key1 : keys) {
- final String key = (String) key1;
- final String[] expectedStrings = expected.get(key);
- final String[] actualStrings = (String[]) actual.get(key);
- Assert.assertEquals(expectedStrings.length, actualStrings.length);
- final Set<String> expectedSet = new HashSet<String>(Arrays.asList(expectedStrings));
- final Set<String> actualSet = new HashSet<String>(Arrays.asList(actualStrings));
- Assert.assertEquals(expectedSet, actualSet);
- }
- }
-}
diff --git a/tobago-example/pom.xml b/tobago-example/pom.xml
index a903709..bcd5822 100644
--- a/tobago-example/pom.xml
+++ b/tobago-example/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>
<name>Tobago Examples</name>
diff --git a/tobago-example/tobago-example-addressbook-cdi/pom.xml b/tobago-example/tobago-example-addressbook-cdi/pom.xml
index ed38692..c108d3b 100644
--- a/tobago-example/tobago-example-addressbook-cdi/pom.xml
+++ b/tobago-example/tobago-example-addressbook-cdi/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-addressbook-cdi</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java b/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
index 26adc96..7f60763 100644
--- a/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
+++ b/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
@@ -19,6 +19,8 @@
package org.apache.myfaces.tobago.example.addressbook;
+import org.apache.commons.io.IOUtils;
+
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -26,6 +28,8 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.Serializable;
@Entity
@@ -43,9 +47,9 @@ public class Picture implements Serializable {
public Picture() {
}
- public Picture(final String contentType, final byte[] content) {
+ public Picture(final String contentType, final InputStream inputStream) throws IOException {
this.contentType = contentType;
- this.content = content;
+ this.content = IOUtils.toByteArray(inputStream);
}
public Integer getId() {
diff --git a/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java b/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
index 1c52dda..d2bc460 100644
--- a/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
+++ b/tobago-example/tobago-example-addressbook-cdi/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
@@ -19,7 +19,6 @@
package org.apache.myfaces.tobago.example.addressbook.web;
-import org.apache.commons.fileupload.FileItem;
import org.apache.deltaspike.core.api.scope.WindowScoped;
import org.apache.myfaces.tobago.component.UIColumn;
import org.apache.myfaces.tobago.component.UISheet;
@@ -45,6 +44,7 @@ import javax.faces.validator.ValidatorException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
@@ -93,7 +93,7 @@ public class Controller implements Serializable {
@Inject
private AddressDao addressDao;
- private FileItem uploadedFile;
+ private Part uploadedFile;
private boolean renderFileUploadPopup;
static {
@@ -282,9 +282,9 @@ public class Controller implements Serializable {
return OUTCOME_LIST;
}
- public String okFileUpload() {
+ public String okFileUpload() throws IOException {
setRenderFileUploadPopup(false);
- final Picture picture = new Picture(uploadedFile.getContentType(), uploadedFile.get());
+ final Picture picture = new Picture(uploadedFile.getContentType(), uploadedFile.getInputStream());
currentAddress.setPicture(picture);
return null;
}
@@ -380,11 +380,11 @@ public class Controller implements Serializable {
this.renderDayOfBirth = renderDayOfBirth;
}
- public FileItem getUploadedFile() {
+ public Part getUploadedFile() {
return uploadedFile;
}
- public void setUploadedFile(final FileItem uploadedFile) {
+ public void setUploadedFile(final Part uploadedFile) {
this.uploadedFile = uploadedFile;
}
diff --git a/tobago-example/tobago-example-addressbook-cdi/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-addressbook-cdi/src/main/webapp/WEB-INF/web.xml
index de330e1..008e9a1 100644
--- a/tobago-example/tobago-example-addressbook-cdi/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-addressbook-cdi/src/main/webapp/WEB-INF/web.xml
@@ -55,6 +55,8 @@
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
+ <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+ <multipart-config/>
</servlet>
<servlet>
diff --git a/tobago-example/tobago-example-addressbook/pom.xml b/tobago-example/tobago-example-addressbook/pom.xml
index 13bfd49..aa0c1a6 100644
--- a/tobago-example/tobago-example-addressbook/pom.xml
+++ b/tobago-example/tobago-example-addressbook/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-addressbook</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java b/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
index 26adc96..7f60763 100644
--- a/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
+++ b/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
@@ -19,6 +19,8 @@
package org.apache.myfaces.tobago.example.addressbook;
+import org.apache.commons.io.IOUtils;
+
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -26,6 +28,8 @@ import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.Serializable;
@Entity
@@ -43,9 +47,9 @@ public class Picture implements Serializable {
public Picture() {
}
- public Picture(final String contentType, final byte[] content) {
+ public Picture(final String contentType, final InputStream inputStream) throws IOException {
this.contentType = contentType;
- this.content = content;
+ this.content = IOUtils.toByteArray(inputStream);
}
public Integer getId() {
diff --git a/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java b/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
index cfc753a..f296d02 100644
--- a/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
+++ b/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
@@ -19,7 +19,6 @@
package org.apache.myfaces.tobago.example.addressbook.web;
-import org.apache.commons.fileupload.FileItem;
import org.apache.myfaces.tobago.component.UIColumn;
import org.apache.myfaces.tobago.component.UISheet;
import org.apache.myfaces.tobago.config.TobagoConfig;
@@ -45,6 +44,7 @@ import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -91,7 +91,7 @@ public class Controller {
@Resource(name = "addressDao")
private AddressDao addressDao;
- private FileItem uploadedFile;
+ private Part uploadedFile;
private boolean renderFileUploadPopup;
static {
@@ -280,9 +280,9 @@ public class Controller {
return OUTCOME_LIST;
}
- public String okFileUpload() {
+ public String okFileUpload() throws IOException {
setRenderFileUploadPopup(false);
- final Picture picture = new Picture(uploadedFile.getContentType(), uploadedFile.get());
+ final Picture picture = new Picture(uploadedFile.getContentType(), uploadedFile.getInputStream());
currentAddress.setPicture(picture);
return null;
}
@@ -383,11 +383,11 @@ public class Controller {
this.renderDayOfBirth = renderDayOfBirth;
}
- public FileItem getUploadedFile() {
+ public Part getUploadedFile() {
return uploadedFile;
}
- public void setUploadedFile(final FileItem uploadedFile) {
+ public void setUploadedFile(final Part uploadedFile) {
this.uploadedFile = uploadedFile;
}
diff --git a/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml
index 6fe65a9..a89f329 100644
--- a/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml
@@ -17,10 +17,11 @@
* limitations under the License.
-->
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
<display-name>A simple addressbook demo with Tobago</display-name>
@@ -75,6 +76,8 @@
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
+ <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+ <multipart-config/>
</servlet>
<servlet>
diff --git a/tobago-example/tobago-example-assembly/pom.xml b/tobago-example/tobago-example-assembly/pom.xml
index 575d574..7cc7518 100644
--- a/tobago-example/tobago-example-assembly/pom.xml
+++ b/tobago-example/tobago-example-assembly/pom.xml
@@ -25,7 +25,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<profiles>
diff --git a/tobago-example/tobago-example-blank/pom.xml b/tobago-example/tobago-example-blank/pom.xml
index 12a28dd..ff873df 100644
--- a/tobago-example/tobago-example-blank/pom.xml
+++ b/tobago-example/tobago-example-blank/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-blank</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml
index dea7873..85ac5c1 100644
--- a/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml
@@ -24,20 +24,6 @@
<display-name>Blank Tobago Application</display-name>
- <filter>
- <filter-name>multipartFormdataFilter</filter-name>
- <filter-class>org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>multipartFormdataFilter</filter-name>
- <url-pattern>/faces/*</url-pattern>
- </filter-mapping>
-
-<!-- workaround (e.g. for Oracle AS 10.1.2.0.0)-->
- <listener>
- <listener-class>org.apache.myfaces.tobago.webapp.TobagoServletContextListener</listener-class>
- </listener>
-
<!-- servlet -->
<servlet>
<servlet-name>FacesServlet</servlet-name>
diff --git a/tobago-example/tobago-example-data/pom.xml b/tobago-example/tobago-example-data/pom.xml
index 8a30946..2fc48d9 100644
--- a/tobago-example/tobago-example-data/pom.xml
+++ b/tobago-example/tobago-example-data/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-data</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-example/tobago-example-demo/pom.xml b/tobago-example/tobago-example-demo/pom.xml
index c7fcda6..92b2b56 100644
--- a/tobago-example/tobago-example-demo/pom.xml
+++ b/tobago-example/tobago-example-demo/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-demo</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Upload.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Upload.java
index db3c84a..f2ae483 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Upload.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Upload.java
@@ -19,10 +19,11 @@
package org.apache.myfaces.tobago.example.demo;
-import org.apache.commons.fileupload.FileItem;
+import org.apache.myfaces.tobago.internal.util.PartUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.servlet.http.Part;
import java.util.ArrayList;
import java.util.List;
@@ -30,86 +31,85 @@ public class Upload {
private static final Logger LOG = LoggerFactory.getLogger(Upload.class);
- private FileItem file1;
- private FileItem file2;
- private FileItem[] fileMulti;
- private FileItem[] fileAjax;
- private FileItem[] fileDnd;
+ private Part file1;
+ private Part file2;
+ private Part[] fileMulti;
+ private Part[] fileAjax;
+ private Part[] fileDnd;
private List<UploadItem> list = new ArrayList<UploadItem>();
public String upload() {
- upload(file1);
- upload(file2);
- upload(fileMulti);
- upload(fileAjax);
- upload(fileDnd);
- return null;
- }
+ upload(file1);
+ upload(file2);
+ upload(fileMulti);
+ upload(fileAjax);
+ upload(fileDnd);
+ file1 = null;
+ file2 = null;
+ fileMulti = null;
+ fileAjax = null;
+ fileDnd = null;
+ return null;
+ }
- public void upload(FileItem[] files) {
+ public void upload(Part[] files) {
if (files != null) {
- for (FileItem file : files) {
+ for (Part file : files) {
upload(file);
}
}
}
- public void upload(FileItem file) {
+ public void upload(Part part) {
LOG.info("checking file item");
- if (file == null || file.get().length == 0) {
+ if (part == null || part.getSize() == 0) {
return;
}
- LOG.info("type=" + file.getContentType());
- LOG.info("size=" + file.get().length);
- String name = file.getName();
- final int pos = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\'));
- if (pos >= 0) {
- // some old browsers send the name with path.
- // modern browsers doesn't because of security reasons.
- name = name.substring(pos + 1);
- }
- LOG.info("name=" + name);
- list.add(new UploadItem(name, file.get().length, file.getContentType()));
+ LOG.info("type='{}'", part.getContentType());
+ LOG.info("size={}", part.getSize());
+ final String submittedFileName = PartUtils.getSubmittedFileName(part);
+ LOG.info("name=" + submittedFileName);
+ list.add(new UploadItem(submittedFileName, part.getSize(), part.getContentType()));
}
- public FileItem getFile1() {
+ public Part getFile1() {
return file1;
}
- public void setFile1(FileItem file1) {
+ public void setFile1(Part file1) {
this.file1 = file1;
}
- public FileItem getFile2() {
+ public Part getFile2() {
return file2;
}
- public void setFile2(FileItem file2) {
+ public void setFile2(Part file2) {
this.file2 = file2;
}
- public FileItem[] getFileMulti() {
+ public Part[] getFileMulti() {
return fileMulti;
}
- public void setFileMulti(FileItem[] fileMulti) {
+ public void setFileMulti(Part[] fileMulti) {
this.fileMulti = fileMulti;
}
- public FileItem[] getFileAjax() {
+ public Part[] getFileAjax() {
return fileAjax;
}
- public void setFileAjax(FileItem[] fileAjax) {
+ public void setFileAjax(Part[] fileAjax) {
this.fileAjax = fileAjax;
}
- public FileItem[] getFileDnd() {
+ public Part[] getFileDnd() {
return fileDnd;
}
- public void setFileDnd(FileItem[] fileDnd) {
+ public void setFileDnd(Part[] fileDnd) {
this.fileDnd = fileDnd;
}
diff --git a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java
index 2968d61..9a2e790 100644
--- a/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java
+++ b/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java
@@ -27,10 +27,10 @@ public class UploadItem {
private static final Logger LOG = LoggerFactory.getLogger(UploadItem.class);
private String name;
- private int size;
+ private long size;
private String type;
- public UploadItem(final String name, final int size, final String type) {
+ public UploadItem(final String name, final long size, final String type) {
this.name = name;
this.size = size;
this.type = type;
@@ -44,7 +44,7 @@ public class UploadItem {
this.name = name;
}
- public int getSize() {
+ public long getSize() {
return size;
}
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml
index 52d3f54..1676138 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml
@@ -17,10 +17,11 @@
* limitations under the License.
-->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version="2.5">
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
<display-name>Tobago Demo Application</display-name>
@@ -83,30 +84,6 @@
<param-value>true</param-value>
</context-param>
- <filter>
- <filter-name>multipartFormdataFilter</filter-name>
- <filter-class>org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter</filter-class>
- <init-param>
- <description>Set the size limit for uploaded files. Default value is 1 MB.
- Format: 10 = 10 bytes
- 10k = 10 KB
- 10m = 10 MB
- 1g = 1 GB
- </description>
- <param-name>uploadMaxFileSize</param-name>
- <param-value>20m</param-value>
- </init-param>
- <!--<init-param>
- <description>Set the upload repository path for uploaded files. Default value is java.io.tmpdir.</description>
- <param-name>uploadRepositoryPath</param-name>
- <param-value>/tmp</param-value>
- </init-param>-->
- </filter>
- <filter-mapping>
- <filter-name>multipartFormdataFilter</filter-name>
- <url-pattern>/faces/*</url-pattern>
- </filter-mapping>
-
<listener>
<listener-class>org.apache.myfaces.tobago.example.demo.info.ActivitySessionListener</listener-class>
</listener>
@@ -156,6 +133,8 @@
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+ <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+ <multipart-config/>
</servlet>
<servlet-mapping>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/40-upload/upload.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/40-upload/upload.xhtml
index d573127..712bdce 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/40-upload/upload.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/40-upload/upload.xhtml
@@ -25,10 +25,31 @@
<ui:param name="title" value="File Upload"/>
<tc:panel id="uploadPanel">
<f:facet name="layout">
- <tc:gridLayout rows="auto;*"/>
+ <tc:gridLayout rows="200px;auto;*"/>
</f:facet>
<tc:panel>
+ <p>
+ To load up files to the server for JSF 2.0 and 2.1 you will need to
+ add an multipart-config entry to the FacesServlet in the <code>web.xml</code> file.
+ Since JSF 2.2 this is not required.
+ </p>
+
+ <p>
+ Here you can configure some more general information.
+ </p>
+
+ <pre><code class="language-markup">
+ <multipart-config>
+ <location>/tmp</location>
+ <max-file-size>20848820</max-file-size>
+ <max-request-size>418018841</max-request-size>
+ <file-size-threshold>1048576</file-size-threshold>
+ </multipart-config>
+ </code></pre>
+ </tc:panel>
+
+ <tc:panel>
<f:facet name="layout">
<tc:gridLayout columns="*;auto"/>
</f:facet>
diff --git a/tobago-example/tobago-example-portlet/pom.xml b/tobago-example/tobago-example-portlet/pom.xml
index 44dd40b..0370675 100644
--- a/tobago-example/tobago-example-portlet/pom.xml
+++ b/tobago-example/tobago-example-portlet/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-portlet</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-sandbox/pom.xml b/tobago-example/tobago-example-sandbox/pom.xml
index 8daf44b..44fe8fe 100644
--- a/tobago-example/tobago-example-sandbox/pom.xml
+++ b/tobago-example/tobago-example-sandbox/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-sandbox</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-sandbox/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-sandbox/src/main/webapp/WEB-INF/web.xml
index ba1f716..740a2fa 100644
--- a/tobago-example/tobago-example-sandbox/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-sandbox/src/main/webapp/WEB-INF/web.xml
@@ -17,10 +17,11 @@
* limitations under the License.
-->
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
<display-name>Tobago Sandbox Application</display-name>
@@ -44,25 +45,13 @@
<param-value>.xml</param-value>
</context-param>
- <filter>
- <filter-name>multipartFormdataFilter</filter-name>
- <filter-class>org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>multipartFormdataFilter</filter-name>
- <url-pattern>/faces/*</url-pattern>
- </filter-mapping>
-
-<!-- workaround (e.g. for Oracle AS 10.1.2.0.0)-->
- <listener>
- <listener-class>org.apache.myfaces.tobago.webapp.TobagoServletContextListener</listener-class>
- </listener>
-
<!-- servlet -->
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>3</load-on-startup>
+ <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+ <multipart-config/>
</servlet>
<servlet>
diff --git a/tobago-example/tobago-example-security/pom.xml b/tobago-example/tobago-example-security/pom.xml
index 38b3977..fdc2d6b 100644
--- a/tobago-example/tobago-example-security/pom.xml
+++ b/tobago-example/tobago-example-security/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-security</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-security/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-security/src/main/webapp/WEB-INF/web.xml
index 3ec1857..88a87c3 100644
--- a/tobago-example/tobago-example-security/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-security/src/main/webapp/WEB-INF/web.xml
@@ -17,10 +17,11 @@
* limitations under the License.
-->
-<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
- version="2.4">
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
<display-name>A simple security demo with Tobago</display-name>
@@ -35,6 +36,8 @@
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
+ <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+ <multipart-config/>
</servlet>
<servlet>
diff --git a/tobago-example/tobago-example-test/pom.xml b/tobago-example/tobago-example-test/pom.xml
index 8f45608..e3d6994 100644
--- a/tobago-example/tobago-example-test/pom.xml
+++ b/tobago-example/tobago-example-test/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-example</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-example-test</artifactId>
<packaging>war</packaging>
diff --git a/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml b/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml
index fdfcfd2..3b71c0d 100644
--- a/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml
+++ b/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml
@@ -17,10 +17,11 @@
* limitations under the License.
-->
-<web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version="2.5">
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
<display-name>Tobago Application for Quality Assurance</display-name>
<description>Will be used for automated tests in the build process.</description>
@@ -55,6 +56,8 @@
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>3</load-on-startup>
+ <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+ <multipart-config/>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
@@ -153,29 +156,4 @@
<url-pattern>/image/wait/*</url-pattern>
</filter-mapping>
- <filter>
- <filter-name>multipartFormdataFilter</filter-name>
- <filter-class>org.apache.myfaces.tobago.webapp.TobagoMultipartFormdataFilter</filter-class>
- <init-param>
- <description>Set the size limit for uploaded files. Default value is 1 MB.
- Format: 10 = 10 bytes
- 10k = 10 KB
- 10m = 10 MB
- 1g = 1 GB
- </description>
- <param-name>uploadMaxFileSize</param-name>
- <param-value>20m</param-value>
- </init-param>
- <!--<init-param>
- <description>Set the upload repository path for uploaded files. Default value is java.io.tmpdir.</description>
- <param-name>uploadRepositoryPath</param-name>
- <param-value>/tmp</param-value>
- </init-param>-->
- </filter>
- <filter-mapping>
- <filter-name>multipartFormdataFilter</filter-name>
- <url-pattern>/faces/*</url-pattern>
- </filter-mapping>
-
-
</web-app>
diff --git a/tobago-extension/pom.xml b/tobago-extension/pom.xml
index edb7e46..f3b7b43 100644
--- a/tobago-extension/pom.xml
+++ b/tobago-extension/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>
<name>Tobago Extensions</name>
diff --git a/tobago-extension/tobago-deprecation/pom.xml b/tobago-extension/tobago-deprecation/pom.xml
index 96759c8..868a303 100644
--- a/tobago-extension/tobago-deprecation/pom.xml
+++ b/tobago-extension/tobago-deprecation/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-extension</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-deprecation</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-extension/tobago-fileupload/pom.xml b/tobago-extension/tobago-fileupload/pom.xml
index b398cf3..b740c9a 100644
--- a/tobago-extension/tobago-fileupload/pom.xml
+++ b/tobago-extension/tobago-fileupload/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-extension</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<name>Tobago Fileupload</name>
diff --git a/tobago-extension/tobago-fileupload/src/main/java/org/apache/myfaces/tobago/fileupload/FileUploadFacesContextFactoryImpl.java b/tobago-extension/tobago-fileupload/src/main/java/org/apache/myfaces/tobago/fileupload/FileUploadFacesContextFactoryImpl.java
index 2c05b7b..a3dcddc 100644
--- a/tobago-extension/tobago-fileupload/src/main/java/org/apache/myfaces/tobago/fileupload/FileUploadFacesContextFactoryImpl.java
+++ b/tobago-extension/tobago-fileupload/src/main/java/org/apache/myfaces/tobago/fileupload/FileUploadFacesContextFactoryImpl.java
@@ -21,126 +21,32 @@ package org.apache.myfaces.tobago.fileupload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.myfaces.tobago.internal.util.JndiUtils;
-import org.apache.myfaces.tobago.internal.webapp.TobagoMultipartFormdataRequest;
import javax.faces.FacesException;
-import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-import javax.servlet.http.HttpServletRequest;
-import java.io.File;
/**
- * This FacesContextFactory handles multipart request. Add the tobago-fileupload.jar to your web application.
- * Configuration:
- *
- * <p><blockquote><pre>
- <env-entry>
- <description>Set the size limit for uploaded files. Default value is 1 MB.
- Format: 10 = 10 bytes
- 10k = 10 KB
- 10m = 10 MB
- 1g = 1 GB
- </description>
- <env-entry-name>uploadMaxFileSize</env-entry-name>
- <env-entry-type>java.lang.String</env-entry-type>
- <env-entry-value>20m</env-entry-value>
- </env-entry>
- <env-entry>
- <description>Set the upload repository path for uploaded files.
- Default value is java.io.tmpdir.</description>
- <env-entry-name>uploadRepositoryPath</env-entry-name>
- <env-entry-type>java.lang.String</env-entry-type>
- <env-entry-value>/tmp</env-entry-value>
- </env-entry>
- </pre></blockquote><p>
-
- *
+ * @deprecated Since 2.4.0
*/
+@Deprecated
public class FileUploadFacesContextFactoryImpl extends FacesContextFactory {
+
private static final Logger LOG = LoggerFactory.getLogger(FileUploadFacesContextFactoryImpl.class);
+
private FacesContextFactory facesContextFactory;
- private String repositoryPath = System.getProperty("java.io.tmpdir");
- private long maxSize = TobagoMultipartFormdataRequest.ONE_MB;
public FileUploadFacesContextFactoryImpl(final FacesContextFactory facesContextFactory) {
- // TODO get Configuration from env entries in the web.xml or context-param
- this.facesContextFactory = facesContextFactory;
- if (LOG.isDebugEnabled()) {
- LOG.debug("Wrap FacesContext for file upload");
- }
- InitialContext ic = null;
- try {
- ic = new InitialContext();
- try {
- final String repositoryPath = (String) JndiUtils.getJndiProperty(ic, "uploadRepositoryPath");
- if (repositoryPath != null) {
- final File file = new File(repositoryPath);
- if (!file.exists()) {
- LOG.error("Given repository Path for "
- + getClass().getName() + " " + repositoryPath + " doesn't exists");
- } else if (!file.isDirectory()) {
- LOG.error("Given repository Path for "
- + getClass().getName() + " " + repositoryPath + " is not a directory");
- } else {
- this.repositoryPath = repositoryPath;
- }
- }
- } catch (final NamingException ne) {
- // ignore
- }
-
- try {
- final String size = (String) JndiUtils.getJndiProperty(ic, "uploadMaxFileSize");
- maxSize = TobagoMultipartFormdataRequest.getMaxSize(size);
- } catch (final NamingException ne) {
- // ignore
- }
- } catch (final NamingException e) {
- // ignore no naming available
- } finally {
- if (ic != null) {
- try {
- ic.close();
- } catch (final NamingException e) {
- // ignore
- }
- }
- }
- if (LOG.isInfoEnabled()) {
- LOG.info("Configure uploadMaxFileSize for "+ getClass().getName() + " to "+ this.maxSize);
- LOG.info("Configure uploadRepositoryPath for "+ getClass().getName() + " to "+ this.repositoryPath);
- }
+ this.facesContextFactory = facesContextFactory;
+ LOG.error("This class is no longer needed! Please remove from web.xml. "
+ + "See the release notes for Tobago 2.4.0.");
}
public FacesContext getFacesContext(
final Object context, Object request, final Object response, final Lifecycle lifecycle)
throws FacesException {
- if (request instanceof HttpServletRequest && !(request instanceof TobagoMultipartFormdataRequest)) {
- final String contentType = ((HttpServletRequest) request).getContentType();
- if (contentType != null && contentType.toLowerCase().startsWith("multipart/form-data")) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Wrap HttpServletRequest for file upload");
- }
- try {
- request = new TobagoMultipartFormdataRequest((HttpServletRequest) request, repositoryPath, maxSize);
- } catch (final FacesException e) {
- LOG.error("", e);
- final FacesContext facesContext = facesContextFactory.getFacesContext(context, request, response, lifecycle);
- // TODO better Message i18n Message?
- final FacesMessage facesMessage
- = new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getCause().getMessage(), null);
- facesContext.addMessage(null, facesMessage);
- facesContext.renderResponse();
- return facesContext;
- }
- }
- }
return facesContextFactory.getFacesContext(context, request, response, lifecycle);
}
}
diff --git a/tobago-extension/tobago-sandbox/pom.xml b/tobago-extension/tobago-sandbox/pom.xml
index 4d46a36..721af6e 100644
--- a/tobago-extension/tobago-sandbox/pom.xml
+++ b/tobago-extension/tobago-sandbox/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-extension</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-sandbox</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-extension/tobago-security/pom.xml b/tobago-extension/tobago-security/pom.xml
index 6ebeeaa..c0ab349 100644
--- a/tobago-extension/tobago-security/pom.xml
+++ b/tobago-extension/tobago-security/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-extension</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<name>Tobago Security</name>
diff --git a/tobago-theme/pom.xml b/tobago-theme/pom.xml
index a245397..618a9c7 100644
--- a/tobago-theme/pom.xml
+++ b/tobago-theme/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>
<name>Tobago Themes</name>
diff --git a/tobago-theme/tobago-theme-charlotteville/pom.xml b/tobago-theme/tobago-theme-charlotteville/pom.xml
index 75e5152..7d11016 100644
--- a/tobago-theme/tobago-theme-charlotteville/pom.xml
+++ b/tobago-theme/tobago-theme-charlotteville/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-theme</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-charlotteville</artifactId>
<name>Tobago Theme Charlotteville</name>
diff --git a/tobago-theme/tobago-theme-example/pom.xml b/tobago-theme/tobago-theme-example/pom.xml
index 59eb8be..c4b2519 100644
--- a/tobago-theme/tobago-theme-example/pom.xml
+++ b/tobago-theme/tobago-theme-example/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-theme</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-example</artifactId>
<name>Tobago Theme Example</name>
diff --git a/tobago-theme/tobago-theme-richmond/pom.xml b/tobago-theme/tobago-theme-richmond/pom.xml
index 92e5f63..38d38eb 100644
--- a/tobago-theme/tobago-theme-richmond/pom.xml
+++ b/tobago-theme/tobago-theme-richmond/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-theme</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-richmond</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-theme/tobago-theme-scarborough/pom.xml b/tobago-theme/tobago-theme-scarborough/pom.xml
index 14b16ce..1639e51 100644
--- a/tobago-theme/tobago-theme-scarborough/pom.xml
+++ b/tobago-theme/tobago-theme-scarborough/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-theme</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-scarborough</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-theme/tobago-theme-speyside/pom.xml b/tobago-theme/tobago-theme-speyside/pom.xml
index a4fe088..4f63f0d 100644
--- a/tobago-theme/tobago-theme-speyside/pom.xml
+++ b/tobago-theme/tobago-theme-speyside/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-theme</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-speyside</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-theme/tobago-theme-standard/pom.xml b/tobago-theme/tobago-theme-standard/pom.xml
index 013c602..158d64b 100644
--- a/tobago-theme/tobago-theme-standard/pom.xml
+++ b/tobago-theme/tobago-theme-standard/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-theme</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-standard</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/FileRenderer.java b/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/FileRenderer.java
index 4cb2642..1d1faf2 100644
--- a/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/FileRenderer.java
+++ b/tobago-theme/tobago-theme-standard/src/main/java/org/apache/myfaces/tobago/renderkit/html/standard/standard/tag/FileRenderer.java
@@ -19,12 +19,11 @@
package org.apache.myfaces.tobago.renderkit.html.standard.standard.tag;
-import org.apache.commons.fileupload.FileItem;
-
+import org.apache.myfaces.tobago.internal.util.HttpPartWrapper;
import org.apache.myfaces.tobago.context.ResourceManagerUtils;
import org.apache.myfaces.tobago.internal.component.AbstractUIFile;
import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
-import org.apache.myfaces.tobago.internal.webapp.TobagoMultipartFormdataRequest;
+import org.apache.myfaces.tobago.internal.util.PartUtils;
import org.apache.myfaces.tobago.layout.Measure;
import org.apache.myfaces.tobago.renderkit.InputRendererBase;
import org.apache.myfaces.tobago.renderkit.css.Classes;
@@ -34,15 +33,19 @@ import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
import org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils;
import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.validator.FileItemValidator;
import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
+import javax.faces.validator.Validator;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
public class FileRenderer extends InputRendererBase {
@@ -62,46 +65,39 @@ public class FileRenderer extends InputRendererBase {
return;
}
- final AbstractUIFile input = (AbstractUIFile) component;
-
- TobagoMultipartFormdataRequest request = null;
- final Object requestObject = facesContext.getExternalContext().getRequest();
- if (requestObject instanceof TobagoMultipartFormdataRequest) {
- request = (TobagoMultipartFormdataRequest) requestObject;
- } else if (requestObject instanceof HttpServletRequestWrapper) {
- final ServletRequest wrappedRequest
- = ((HttpServletRequestWrapper) requestObject).getRequest();
- if (wrappedRequest instanceof TobagoMultipartFormdataRequest) {
- request = (TobagoMultipartFormdataRequest) wrappedRequest;
- }
- }
- // TODO PortletRequest ??
- if (request == null) {
- // should not be possible, because of the check in UIPage
- LOG.error("Can't process multipart/form-data without TobagoRequest. "
- + "Please check the web.xml and define a TobagoMultipartFormdataFilter. "
- + "See documentation for <tc:file>");
- } else {
-
- if (input.isMultiple()) {
- final FileItem[] items = request.getFileItems(input.getClientId(facesContext));
- if (LOG.isDebugEnabled()) {
- for (FileItem item : items) {
- LOG.debug("Uploaded file name : \"" + item.getName()
- + "\" size = " + item.getSize());
+ final AbstractUIFile file = (AbstractUIFile) component;
+ final boolean multiple = file.isMultiple() && !file.isRequired();
+ final Object request = facesContext.getExternalContext().getRequest();
+ if (request instanceof HttpServletRequest) {
+ try {
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ if (multiple) {
+ final List<Part> parts = new ArrayList<Part>();
+ for (final Part part : httpServletRequest.getParts()) {
+ if (file.getClientId(facesContext).equals(part.getName())) {
+ LOG.debug("Uploaded file '{}', size={}, type='{}'",
+ PartUtils.getSubmittedFileName(part), part.getSize(), part.getContentType());
+ parts.add(new HttpPartWrapper(part));
+ }
+ file.setSubmittedValue(parts.toArray(new Part[0]));
+ }
+ } else {
+ final Part part = httpServletRequest.getPart(file.getClientId(facesContext));
+ final String submittedFileName = PartUtils.getSubmittedFileName(part);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Uploaded file '{}', size={}, type='{}'",
+ submittedFileName, part.getSize(), part.getContentType());
+ }
+ if (submittedFileName.length() > 0) {
+ file.setSubmittedValue(new HttpPartWrapper(part));
}
}
- input.setSubmittedValue(items);
- } else {
- final FileItem item = request.getFileItem(input.getClientId(facesContext));
- if (LOG.isDebugEnabled()) {
- LOG.debug("Uploaded file name : \"" + item.getName()
- + "\" size = " + item.getSize());
- }
- input.setSubmittedValue(item);
+ } catch (final Exception e) {
+ LOG.error("", e);
+ file.setValid(false);
}
- //TODO remove this
- input.setValid(true);
+ } else { // todo: PortletRequest
+ LOG.warn("Unsupported request type: " + request.getClass().getName());
}
}
@@ -110,6 +106,7 @@ public class FileRenderer extends InputRendererBase {
final AbstractUIFile file = (AbstractUIFile) component;
final String clientId = file.getClientId(facesContext);
final Style style = new Style(facesContext, file);
+ final String accept = createAcceptFromValidators(file);
final TobagoResponseWriter writer = HtmlRendererUtils.getTobagoResponseWriter(facesContext);
@@ -127,6 +124,7 @@ public class FileRenderer extends InputRendererBase {
writer.writeAttribute(HtmlAttributes.MULTIPLE, file.isMultiple());
writer.writeIdAttribute(clientId + ComponentUtils.SUB_SEPARATOR + "real");
writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.FILE, false);
+ writer.writeAttribute(HtmlAttributes.ACCEPT, accept, true);
writer.writeClassAttribute(getCssClasses(file, "real"));
writer.writeNameAttribute(clientId);
String multiFormat = ResourceManagerUtils.getPropertyNotNull(facesContext, "tobago", "tobago.file.multiFormat");
@@ -150,6 +148,24 @@ public class FileRenderer extends InputRendererBase {
writer.endElement(HtmlElements.DIV);
}
+ private String createAcceptFromValidators(final AbstractUIFile file) {
+ final StringBuilder builder = new StringBuilder();
+ for (Validator validator : file.getValidators()) {
+ if (validator instanceof FileItemValidator) {
+ final FileItemValidator fileItemValidator = (FileItemValidator) validator;
+ for (final String contentType : fileItemValidator.getContentType()) {
+ builder.append(",");
+ builder.append(contentType);
+ }
+ }
+ }
+ if (builder.length() > 0) {
+ return builder.substring(1);
+ } else {
+ return null;
+ }
+ }
+
protected Classes getCssClasses(UIComponent component, String sub) {
return Classes.create(component, sub);
}
diff --git a/tobago-tool/pom.xml b/tobago-tool/pom.xml
index 376a125..0c4105c 100644
--- a/tobago-tool/pom.xml
+++ b/tobago-tool/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<packaging>pom</packaging>
<name>Tobago Tool</name>
diff --git a/tobago-tool/tobago-theme-plugin/pom.xml b/tobago-tool/tobago-theme-plugin/pom.xml
index 4d5ed9c..2362e27 100644
--- a/tobago-tool/tobago-theme-plugin/pom.xml
+++ b/tobago-tool/tobago-theme-plugin/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-tool</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-theme-plugin</artifactId>
<packaging>maven-plugin</packaging>
diff --git a/tobago-tool/tobago-tool-annotation/pom.xml b/tobago-tool/tobago-tool-annotation/pom.xml
index ab4e507..1998e71 100644
--- a/tobago-tool/tobago-tool-annotation/pom.xml
+++ b/tobago-tool/tobago-tool-annotation/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-tool</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-tool-annotation</artifactId>
<packaging>jar</packaging>
diff --git a/tobago-tool/tobago-tool-apt/pom.xml b/tobago-tool/tobago-tool-apt/pom.xml
index 90fd188..42c97f3 100644
--- a/tobago-tool/tobago-tool-apt/pom.xml
+++ b/tobago-tool/tobago-tool-apt/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.apache.myfaces.tobago</groupId>
<artifactId>tobago-tool</artifactId>
- <version>2.3.1-SNAPSHOT</version>
+ <version>2.4.0-SNAPSHOT</version>
</parent>
<artifactId>tobago-tool-apt</artifactId>
<packaging>jar</packaging>