Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.router.RouteConfiguration;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.streams.DownloadHandler;
import com.vaadin.testbench.unit.UIUnitTest;
import com.vaadin.testbench.unit.ViewPackages;

Expand Down Expand Up @@ -110,9 +111,8 @@ void anchorDownload_writesResourceToOutputStream() {

@Test
void anchorDownload_disabled_throws() {
StreamResource resource = new StreamResource("filename",
() -> new ByteArrayInputStream(
"Hello world".getBytes(StandardCharsets.UTF_8)));
DownloadHandler resource = event -> event.getOutputStream()
.write("Hello world".getBytes(StandardCharsets.UTF_8));

Anchor anchor = new Anchor(resource, "Download");
anchor.setEnabled(false);
Expand All @@ -123,6 +123,34 @@ void anchorDownload_disabled_throws() {
() -> test(anchor).download(outputStream));
}

@Test
void anchorClick_downloadHandler_throws() {
DownloadHandler resource = event -> event.getOutputStream()
.write("Hello world".getBytes(StandardCharsets.UTF_8));
Anchor anchor = new Anchor(resource, "Home");
UI.getCurrent().add(anchor);

final IllegalStateException exception = assertThrows(
IllegalStateException.class, () -> test(anchor).click());

Assertions.assertEquals("Anchor target seems to be a resource",
exception.getMessage());
}

@Test
void anchorDownload_downloadHandler_writesResourceToOutputStream() {
DownloadHandler resource = event -> event.getOutputStream()
.write("Hello world".getBytes(StandardCharsets.UTF_8));
Anchor anchor = new Anchor(resource, "Download");
UI.getCurrent().add(anchor);

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
test(anchor).download(outputStream);

Assertions.assertEquals("Hello world",
outputStream.toString(StandardCharsets.UTF_8));
}

@Test
void anchorDownload_noStreamRegistration_throws() {
Anchor anchor = new Anchor("anchor", "Download");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.net.URI;
import java.net.URISyntaxException;
Expand All @@ -23,7 +24,11 @@
import com.vaadin.flow.server.AbstractStreamResource;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.StreamResourceRegistry;
import com.vaadin.flow.server.VaadinRequest;
import com.vaadin.flow.server.VaadinResponse;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.streams.DownloadEvent;
import com.vaadin.flow.server.streams.DownloadHandler;
import com.vaadin.testbench.unit.Tests;

@Tests(Anchor.class)
Expand Down Expand Up @@ -137,16 +142,53 @@ public void download(OutputStream outputStream) {
// Ignore, throws below if resource is empty
}

if (maybeResource.isEmpty() || !(maybeResource
.get() instanceof StreamResource streamResource)) {
throw new IllegalStateException(
"Anchor target does not seem to be a resource");
}
AbstractStreamResource resource = maybeResource
.filter(res -> res instanceof StreamResource
|| (res instanceof StreamResourceRegistry.ElementStreamResource el
&& el.getElementRequestHandler() instanceof DownloadHandler))
.orElseThrow(() -> new IllegalStateException(
"Anchor target does not seem to be a resource"));
if (resource instanceof StreamResource cast) {
try {
cast.getWriter().accept(outputStream, session);
} catch (IOException e) {
throw new RuntimeException("Download failed", e);
}
} else {
StreamResourceRegistry.ElementStreamResource elementResource = (StreamResourceRegistry.ElementStreamResource) resource;
DownloadHandler handler = (DownloadHandler) elementResource
.getElementRequestHandler();
var event = new DownloadEvent(VaadinRequest.getCurrent(),
VaadinResponse.getCurrent(), session,
elementResource.getOwner()) {
private boolean outputStreamCalled;
private boolean writerCalled;

try {
streamResource.getWriter().accept(outputStream, session);
} catch (IOException e) {
throw new RuntimeException("Download failed", e);
@Override
public OutputStream getOutputStream() {
if (writerCalled) {
throw new IllegalStateException(
"Cannot execute getOutputStream() after getWriter() has been called");
}
outputStreamCalled = true;
return outputStream;
}

@Override
public PrintWriter getWriter() {
if (outputStreamCalled) {
throw new IllegalStateException(
"Cannot execute getWriter() after getOutputStream() has been called");
}
writerCalled = true;
return new PrintWriter(outputStream);
}
};
try {
handler.handleDownloadRequest(event);
} catch (IOException e) {
throw new RuntimeException("Download failed", e);
}
}
}
}
Loading