]> source.dussan.org Git - vaadin-framework.git/commitdiff
Make sure that no fileIds are replayed to the client (#12330)
authorHenrik Paul <henrik@vaadin.com>
Thu, 15 Aug 2013 05:59:03 +0000 (08:59 +0300)
committerVaadin Code Review <review@vaadin.com>
Thu, 15 Aug 2013 10:49:25 +0000 (10:49 +0000)
Due to how ProxyReceivers are constructed and serialized, we don't want
to resend the ProxyReceivers for files that already are in the queue.
Either we needed to change the way ProxyReceivers behave, or just make
sure that they aren't resent. I chose the double-check method.

Change-Id: I7c4e866ba4287afd3e80329be3640335d4ff00af

server/src/com/vaadin/ui/DragAndDropWrapper.java
uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropBatchUpload.java [new file with mode: 0644]

index 6c6aa3c3f47d5c7afe6f89fa3828345c4861035c..5d6825c868d5be87af8a12371659135c0a1773ed 100644 (file)
@@ -17,10 +17,12 @@ package com.vaadin.ui;
 
 import java.io.OutputStream;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import com.vaadin.event.Transferable;
 import com.vaadin.event.TransferableImpl;
@@ -183,6 +185,8 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
     private final Map<String, Object> html5DataFlavors = new LinkedHashMap<String, Object>();
     private DragStartMode dragStartMode = DragStartMode.NONE;
 
+    private Set<String> sentIds = new HashSet<String>();
+
     /**
      * Wraps given component in a {@link DragAndDropWrapper}.
      * 
@@ -229,10 +233,24 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
                 ProxyReceiver proxyReceiver = entry.getValue();
                 Html5File html5File = proxyReceiver.file;
                 if (html5File.getStreamVariable() != null) {
-                    target.addVariable(this, "rec-" + id, new ProxyReceiver(id,
-                            html5File));
-                    // these are cleaned from receivers once the upload has
-                    // started
+                    if (!sentIds.contains(id)) {
+                        target.addVariable(this, "rec-" + id,
+                                new ProxyReceiver(id, html5File));
+
+                        /*
+                         * if a new batch is requested to be uploaded before the
+                         * last one is done, any remaining ids will be replayed.
+                         * We want to avoid a new ProxyReceiver to be made since
+                         * it'll get a new URL, so we need to keep extra track
+                         * on what has been sent.
+                         * 
+                         * See #12330.
+                         */
+                        sentIds.add(id);
+
+                        // these are cleaned from receivers once the upload has
+                        // started
+                    }
                 } else {
                     // instructs the client side not to send the file
                     target.addVariable(this, "rec-" + id, (String) null);
@@ -317,6 +335,7 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
             }
             // no need tell to the client about this receiver on next paint
             receivers.remove(id);
+            sentIds.remove(id);
             // let the terminal GC the streamvariable and not to accept other
             // file uploads to this variable
             event.disposeStreamVariable();
diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropBatchUpload.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropBatchUpload.java
new file mode 100644 (file)
index 0000000..adb5cd9
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ * 
+ * Licensed 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 com.vaadin.tests.components.draganddropwrapper;
+
+import java.io.OutputStream;
+
+import org.apache.commons.io.output.NullOutputStream;
+
+import com.vaadin.event.Transferable;
+import com.vaadin.event.dd.DragAndDropEvent;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.acceptcriteria.AcceptAll;
+import com.vaadin.event.dd.acceptcriteria.AcceptCriterion;
+import com.vaadin.server.StreamVariable;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.DragAndDropWrapper;
+import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable;
+import com.vaadin.ui.Html5File;
+import com.vaadin.ui.Label;
+
+public class DragAndDropBatchUpload extends AbstractTestUI {
+
+    private int batchId = 0;
+    private Label console = new Label("No activity detected yet",
+            ContentMode.HTML);
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        final DragAndDropWrapper dndWrapper = new DragAndDropWrapper(
+                new Button("Upload here by drag and dropping"));
+        dndWrapper.setDropHandler(new DropHandler() {
+
+            @Override
+            public AcceptCriterion getAcceptCriterion() {
+                return AcceptAll.get();
+            }
+
+            @Override
+            public void drop(DragAndDropEvent event) {
+                Transferable transferable = event.getTransferable();
+                String consoleString = "<b>Drop batch number " + (++batchId)
+                        + "</b>";
+                if (transferable instanceof WrapperTransferable) {
+                    WrapperTransferable wTransferable = (WrapperTransferable) transferable;
+                    Html5File[] files = wTransferable.getFiles();
+
+                    if (files != null) {
+                        consoleString += "<br>" + files.length + " file(s):";
+                        for (Html5File file : files) {
+                            consoleString += "<br>" + file.getFileName();
+                            file.setStreamVariable(new StreamVariable() {
+
+                                @Override
+                                public void streamingStarted(
+                                        StreamingStartEvent event) {
+                                }
+
+                                @Override
+                                public void streamingFinished(
+                                        StreamingEndEvent event) {
+                                }
+
+                                @Override
+                                public void streamingFailed(
+                                        StreamingErrorEvent event) {
+                                }
+
+                                @Override
+                                public void onProgress(
+                                        StreamingProgressEvent event) {
+                                }
+
+                                @Override
+                                public boolean listenProgress() {
+                                    return false;
+                                }
+
+                                @Override
+                                public boolean isInterrupted() {
+                                    return false;
+                                }
+
+                                @Override
+                                public OutputStream getOutputStream() {
+                                    return new NullOutputStream();
+                                }
+                            });
+                        }
+                    } else {
+                        consoleString += "<br>No files detected...";
+                    }
+                    console.setValue(consoleString);
+                } else {
+                    console.setValue(consoleString
+                            + "<br>Something else than files were dragged");
+                }
+
+            }
+        });
+
+        addComponent(dndWrapper);
+        addComponent(console);
+    }
+
+    @Override
+    protected String getTestDescription() {
+        return "Starting to upload a new batch before the old one must not reuse receivers";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 12330;
+    }
+
+}