You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2021/03/31 11:43:06 UTC

[myfaces] branch master updated: MYFACES-4390: HtmlInputFile multiple support

This is an automated email from the ASF dual-hosted git repository.

tandraschko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces.git


The following commit(s) were added to refs/heads/master by this push:
     new 094c20e  MYFACES-4390: HtmlInputFile multiple support
     new 9eff0f5  Merge pull request #191 from melloware/MYFACES-4390
094c20e is described below

commit 094c20e9383fa36d6a587ce2107e06ac7a8378b1
Author: melloware <me...@gmail.com>
AuthorDate: Tue Mar 30 12:48:44 2021 -0400

    MYFACES-4390: HtmlInputFile multiple support
---
 .../faces/component/html/_HtmlInputFile.java       | 10 ++++
 .../html/base/HtmlInputFileRendererBase.java       | 58 +++++++++++++++++++---
 2 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/api/src/main/java/jakarta/faces/component/html/_HtmlInputFile.java b/api/src/main/java/jakarta/faces/component/html/_HtmlInputFile.java
index eb71d58..0d1b275 100644
--- a/api/src/main/java/jakarta/faces/component/html/_HtmlInputFile.java
+++ b/api/src/main/java/jakarta/faces/component/html/_HtmlInputFile.java
@@ -83,6 +83,16 @@ abstract class _HtmlInputFile extends UIInput implements _AccesskeyProperty,
     @JSFProperty
     public abstract String getAccept();
 
+    /**
+     * Flag indicating that this element must allow multiple file selection. A value
+     * of false causes no attribute to be rendered, while a value of true causes the attribute to be rendered as
+     * multiple="multiple".
+     *
+     * @return the multiple value
+     */
+    @JSFProperty(defaultValue="false")
+    public abstract boolean isMultiple();
+
     @Override
     protected void validateValue(FacesContext context, Object convertedValue)
     {
diff --git a/impl/src/main/java/org/apache/myfaces/renderkit/html/base/HtmlInputFileRendererBase.java b/impl/src/main/java/org/apache/myfaces/renderkit/html/base/HtmlInputFileRendererBase.java
index 6c5daa1..c1eef0d 100644
--- a/impl/src/main/java/org/apache/myfaces/renderkit/html/base/HtmlInputFileRendererBase.java
+++ b/impl/src/main/java/org/apache/myfaces/renderkit/html/base/HtmlInputFileRendererBase.java
@@ -31,9 +31,14 @@ import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.Part;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
 import jakarta.faces.FacesException;
 import jakarta.faces.application.FacesMessage;
 import jakarta.faces.application.ProjectStage;
@@ -59,14 +64,26 @@ public class HtmlInputFileRendererBase extends HtmlRenderer
     {
         try
         {
-           Part part = ((HttpServletRequest) facesContext.getExternalContext().getRequest()).
-                   getPart(component.getClientId());
-           if (part == null)
-           {
-               return;
-           }
-
-           ((UIInput) component).setSubmittedValue(new HttpPartWrapper(part));
+            String clientId = component.getClientId();
+            HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
+            Collection<Part> parts = request.getParts();
+            Collection<Part> submittedValues = new ArrayList<>(parts.size());
+            for (Part part : parts)
+            {
+                if (clientId.equals(part.getName()))
+                {
+                    HttpPartWrapper wrapper = new HttpPartWrapper(part);
+                    submittedValues.add(wrapper);
+                }
+            }
+            if (((HtmlInputFile) component).isMultiple())
+            {
+                ((UIInput) component).setSubmittedValue(submittedValues);
+            }
+            else if (!submittedValues.isEmpty())
+            {
+                ((UIInput) component).setSubmittedValue(submittedValues.iterator().next());
+            }
         }
         catch (IOException | ServletException e)
         {
@@ -111,6 +128,21 @@ public class HtmlInputFileRendererBase extends HtmlRenderer
         Assert.notNull(context, "context");
         Assert.notNull(component, "component");
 
+        if (submittedValue instanceof Part)
+        {
+            Part part = (Part) submittedValue;
+            if (isEmpty(part))
+            {
+                return null;
+            }
+        }
+        else if (submittedValue instanceof Collection)
+        {
+            Collection<Part> parts = (Collection<Part>) submittedValue;
+            return Collections.unmodifiableList(parts.stream()
+                        .filter(part -> !isEmpty(part))
+                        .collect(Collectors.toList()));
+        }
         return submittedValue;
     }
 
@@ -203,6 +235,11 @@ public class HtmlInputFileRendererBase extends HtmlRenderer
             writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
         }
 
+        if (inputFile.isMultiple())
+        {
+            writer.writeAttribute(HTML.MULTIPLE_ATTR, HTML.MULTIPLE_ATTR, null);
+        }
+
         if (AUTOCOMPLETE_VALUE_OFF.equals(inputFile.getAutocomplete()))
         {
             writer.writeAttribute(HTML.AUTOCOMPLETE_ATTR, AUTOCOMPLETE_VALUE_OFF, HTML.AUTOCOMPLETE_ATTR);
@@ -220,4 +257,9 @@ public class HtmlInputFileRendererBase extends HtmlRenderer
 
         writer.endElement(HTML.INPUT_ELEM);
     }
+
+    private static boolean isEmpty(Part part)
+    {
+        return part.getSubmittedFileName() == null || part.getSubmittedFileName().isEmpty() || part.getSize() <= 0;
+    }
 }