From: Artur Signell Date: Wed, 30 Sep 2015 14:05:24 +0000 (+0300) Subject: Properly cleanup stream variables if DragAndDropWrapper is detached (#14882) X-Git-Tag: 7.6.0.alpha7~31 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=743095d97bbd632e0493fca29ba2308b17b86716;p=vaadin-framework.git Properly cleanup stream variables if DragAndDropWrapper is detached (#14882) If DragAndDropWrapper is removed from the UI for whatever reason before cleanup happens, the UI can no longer be found through it. If we do not do cleanup, we leave a reference hanging forever in ConnectorTracker. Change-Id: I9fc3da5d616276a7810ddc4a18cbebf8621635fe --- diff --git a/server/src/com/vaadin/server/communication/FileUploadHandler.java b/server/src/com/vaadin/server/communication/FileUploadHandler.java index 532c7fe95b..b9eaff3bd1 100644 --- a/server/src/com/vaadin/server/communication/FileUploadHandler.java +++ b/server/src/com/vaadin/server/communication/FileUploadHandler.java @@ -450,10 +450,13 @@ public class FileUploadHandler implements RequestHandler { session.unlock(); } try { + // Store ui reference so we can do cleanup even if connector is + // detached in some event handler + UI ui = connector.getUI(); boolean forgetVariable = streamToReceiver(session, inputStream, streamVariable, filename, mimeType, contentLength); if (forgetVariable) { - cleanStreamVariable(session, connector, variableName); + cleanStreamVariable(session, ui, connector, variableName); } } catch (Exception e) { session.lock(); @@ -684,15 +687,13 @@ public class FileUploadHandler implements RequestHandler { out.close(); } - private void cleanStreamVariable(VaadinSession session, + private void cleanStreamVariable(VaadinSession session, final UI ui, final ClientConnector owner, final String variableName) { session.accessSynchronously(new Runnable() { @Override public void run() { - owner.getUI() - .getConnectorTracker() - .cleanStreamVariable(owner.getConnectorId(), - variableName); + ui.getConnectorTracker().cleanStreamVariable( + owner.getConnectorId(), variableName); } }); } diff --git a/uitest/src/com/vaadin/tests/components/draganddropwrapper/SingleUseDragAndDropUpload.java b/uitest/src/com/vaadin/tests/components/draganddropwrapper/SingleUseDragAndDropUpload.java new file mode 100644 index 0000000000..7c7e17a5a6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/draganddropwrapper/SingleUseDragAndDropUpload.java @@ -0,0 +1,125 @@ +/* + * Copyright 2000-2014 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.annotations.Theme; +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.FontAwesome; +import com.vaadin.server.StreamVariable; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.tests.components.AbstractTestUIWithLog; +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; + +@Theme("valo") +public class SingleUseDragAndDropUpload extends AbstractTestUIWithLog { + + @Override + protected void setup(VaadinRequest request) { + Label upload = new Label(FontAwesome.UPLOAD.getHtml(), ContentMode.HTML); + upload.setSizeUndefined(); + upload.setStyleName("upload"); + getPage() + .getStyles() + .add(".upload{ font-size: 36px; border: 1px solid black; padding:15px;}"); + + final DragAndDropWrapper dnd = new DragAndDropWrapper(upload); + dnd.setSizeUndefined(); + addComponent(dnd); + dnd.setDropHandler(new DropHandler() { + + @Override + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + + @Override + public void drop(DragAndDropEvent event) { + Transferable transferable = event.getTransferable(); + log("Drop occured"); + if (transferable instanceof WrapperTransferable) { + WrapperTransferable wTransferable = (WrapperTransferable) transferable; + Html5File[] files = wTransferable.getFiles(); + + if (files != null) { + for (Html5File file : files) { + log("Uploading file " + file.getFileName()); + file.setStreamVariable(new StreamVariable() { + + @Override + public void streamingStarted( + StreamingStartEvent event) { + log("Streaming started"); + } + + @Override + public void streamingFinished( + StreamingEndEvent event) { + log("Streaming finished"); + removeComponent(dnd); + log("DragAndDropWrapper removed"); + } + + @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(); + } + }); + } + } + } + } + }); + addComponent(new Button("Poll for changes")); + } + + @Override + protected String getTestDescription() { + return "Drag a file to the upload icon and ensure there is no exceptions logged in the console"; + } +}