diff options
-rw-r--r-- | server/src/com/vaadin/ui/DragAndDropWrapper.java | 27 | ||||
-rw-r--r-- | uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropBatchUpload.java | 132 |
2 files changed, 155 insertions, 4 deletions
diff --git a/server/src/com/vaadin/ui/DragAndDropWrapper.java b/server/src/com/vaadin/ui/DragAndDropWrapper.java index 6c6aa3c3f4..5d6825c868 100644 --- a/server/src/com/vaadin/ui/DragAndDropWrapper.java +++ b/server/src/com/vaadin/ui/DragAndDropWrapper.java @@ -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 index 0000000000..adb5cd9e3a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/DragAndDropBatchUpload.java @@ -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; + } + +} |