Repository: wicket Updated Branches: refs/heads/master 1f805dd5a -> 1fc1e3d70
WICKET-6460 Rename AjaxDownload to AjaxDownloadBehavior Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/1fc1e3d7 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/1fc1e3d7 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/1fc1e3d7 Branch: refs/heads/master Commit: 1fc1e3d7040ed2f3e73e7067efd201a958a90b3e Parents: 1f805dd Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Mon Sep 4 22:26:30 2017 +0300 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Mon Sep 4 22:26:30 2017 +0300 ---------------------------------------------------------------------- .../examples/ajax/builtin/AjaxDownloadPage.java | 22 +- .../wicket/extensions/ajax/AjaxDownload.java | 384 ------------------ .../extensions/ajax/AjaxDownloadBehavior.java | 388 +++++++++++++++++++ 3 files changed, 399 insertions(+), 395 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/1fc1e3d7/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java ---------------------------------------------------------------------- diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java index 6d1aa3e..70a682d 100644 --- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java +++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/AjaxDownloadPage.java @@ -20,8 +20,8 @@ import java.util.concurrent.TimeUnit; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.AjaxLink; -import org.apache.wicket.extensions.ajax.AjaxDownload; -import org.apache.wicket.extensions.ajax.AjaxDownload.Location; +import org.apache.wicket.extensions.ajax.AjaxDownloadBehavior; +import org.apache.wicket.extensions.ajax.AjaxDownloadBehavior.Location; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.request.http.flow.AbortWithHttpErrorCodeException; import org.apache.wicket.request.resource.ContentDisposition; @@ -76,7 +76,7 @@ public class AjaxDownloadPage extends BasePage IResource resource = new ExampleResource("downloaded via ajax") .setContentDisposition(ContentDisposition.ATTACHMENT); - final AjaxDownload download = new AjaxDownload(resource) { + final AjaxDownloadBehavior download = new AjaxDownloadBehavior(resource) { @Override protected void onBeforeDownload(AjaxRequestTarget target) @@ -118,7 +118,7 @@ public class AjaxDownloadPage extends BasePage IResource resource = new ExampleResource("downloaded via ajax in iframe") .setContentDisposition(ContentDisposition.ATTACHMENT); - final AjaxDownload download = new AjaxDownload(resource) { + final AjaxDownloadBehavior download = new AjaxDownloadBehavior(resource) { @Override protected void onBeforeDownload(AjaxRequestTarget target) @@ -166,7 +166,7 @@ public class AjaxDownloadPage extends BasePage } }; - final AjaxDownload download = new AjaxDownload(reference) { + final AjaxDownloadBehavior download = new AjaxDownloadBehavior(reference) { @Override protected void onBeforeDownload(AjaxRequestTarget target) @@ -208,7 +208,7 @@ public class AjaxDownloadPage extends BasePage IResource resource = new ExampleResource("downloaded via ajax in a new browser window") .setContentDisposition(ContentDisposition.INLINE); - final AjaxDownload download = new AjaxDownload(resource) { + final AjaxDownloadBehavior download = new AjaxDownloadBehavior(resource) { @Override protected void onBeforeDownload(AjaxRequestTarget target) @@ -240,7 +240,7 @@ public class AjaxDownloadPage extends BasePage target.add(downloadingContainer); } }; - download.setLocation(AjaxDownload.Location.NewWindow); + download.setLocation(AjaxDownloadBehavior.Location.NewWindow); add(download); add(new AjaxLink<Void>("downloadInNewWindow") @@ -258,7 +258,7 @@ public class AjaxDownloadPage extends BasePage IResource resource = new ExampleResource("downloaded via ajax in same browser window") .setContentDisposition(ContentDisposition.ATTACHMENT); - final AjaxDownload download = new AjaxDownload(resource) { + final AjaxDownloadBehavior download = new AjaxDownloadBehavior(resource) { @Override protected void onBeforeDownload(AjaxRequestTarget target) @@ -290,7 +290,7 @@ public class AjaxDownloadPage extends BasePage target.add(downloadingContainer); } }; - download.setLocation(AjaxDownload.Location.SameWindow); + download.setLocation(AjaxDownloadBehavior.Location.SameWindow); add(download); add(new AjaxLink<Void>("downloadInSameWindow") @@ -314,7 +314,7 @@ public class AjaxDownloadPage extends BasePage @Override public void respond(Attributes attributes) { - AjaxDownload.markCompleted(attributes); + AjaxDownloadBehavior.markCompleted(attributes); super.respond(attributes); } @@ -370,4 +370,4 @@ public class AjaxDownloadPage extends BasePage }; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/wicket/blob/1fc1e3d7/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java ---------------------------------------------------------------------- diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java deleted file mode 100644 index 370b77a..0000000 --- a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownload.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.wicket.extensions.ajax; - -import java.util.Locale; - -import javax.annotation.Resource; -import javax.servlet.http.Cookie; - -import org.apache.wicket.Component; -import org.apache.wicket.IRequestListener; -import org.apache.wicket.WicketRuntimeException; -import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; -import org.apache.wicket.ajax.AjaxRequestTarget; -import org.apache.wicket.ajax.json.JSONFunction; -import org.apache.wicket.behavior.Behavior; -import org.apache.wicket.markup.head.IHeaderResponse; -import org.apache.wicket.markup.head.JavaScriptHeaderItem; -import org.apache.wicket.request.Response; -import org.apache.wicket.request.cycle.RequestCycle; -import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler; -import org.apache.wicket.request.http.WebResponse; -import org.apache.wicket.request.mapper.parameter.PageParameters; -import org.apache.wicket.request.resource.ContentDisposition; -import org.apache.wicket.request.resource.IResource; -import org.apache.wicket.request.resource.IResource.Attributes; -import org.apache.wicket.request.resource.ResourceReference; -import org.apache.wicket.resource.JQueryPluginResourceReference; -import org.apache.wicket.util.lang.Args; - -import com.github.openjson.JSONObject; - -/** - * Download resources via Ajax. - * <p> - * Usage: - * - * <pre> - * final AjaxDownload download = new AjaxDownload(resource); - * add(download); - * - * add(new AjaxButton("download") - * { - * @Override - * protected void onSubmit(AjaxRequestTarget target, Form<?> form) - * { - * download.initiate(target); - * } - * }); - * </pre> - * - * @author svenmeier - * @author Martin Grigorov - * @author Maxim Solodovnik - */ -public class AjaxDownload extends AbstractDefaultAjaxBehavior -{ - private static final long serialVersionUID = 1L; - - public enum Location { - /** - * The resource will be downloaded into a {@code blob}. - * <p> - * This is recommended for modern browsers. - */ - Blob, - - /** - * The resource will be downloaded via a temporary created iframe, the resource has to be a - * {@link ContentDisposition#ATTACHMENT}. - * <p> - * This is recommended when there are resources in the DOM which will be - * closed automatically on JavaScript <em>unload</em> event, like WebSockets. - * Supports both <em>success</em> and <em>failure</em> callbacks! - */ - IFrame, - - /** - * The resource will be downloaded by changing the location of the current DOM document, - * the resource has to be a {@link ContentDisposition#ATTACHMENT}. - * <p> - * Note: This will trigger JavaScript <em>unload</em> event on the page! - * Does not support {@link AjaxDownload#onDownloadFailed(AjaxRequestTarget)} callback, - * i.e. it is not possible to detect when the download has failed! - */ - SameWindow, - - /** - * The resource will be downloaded in a new browser window by using JavaScript <code>window.open()</code> API, - * the resource has to be a {@link ContentDisposition#INLINE}. - */ - NewWindow - } - - /** - * Name of parameter used to transfer the download identifier to the resource. - * - * @see #markCompleted(Attributes) - */ - private static final String RESOURCE_PARAMETER_NAME = "wicket-ajaxdownload"; - - private static final ResourceReference JS = new JQueryPluginResourceReference( - AjaxDownload.class, "wicket-ajaxdownload.js"); - - private final ResourceReference resourceReference; - - private final ResourceBehavior resourceBehavior; - - private PageParameters resourceParameters; - - private Location location = Location.Blob; - - /** - * Download of a {@link Resource}. - * - * @param resource - * resource to download - */ - public AjaxDownload(IResource resource) - { - Args.notNull(resource, "resource"); - this.resourceBehavior = new ResourceBehavior(resource); - this.resourceReference = null; - } - - /** - * Download of a {@link ResourceReference}. - * <p> - * The {@link IResource} returned by {@link ResourceReference#getResource()} must call - * {@link #markCompleted(Attributes)} when responding, otherwise the callback - * {@link #onDownloadSuccess(AjaxRequestTarget)} will not work. - * - * @param reference - * reference to resource to download - */ - public AjaxDownload(ResourceReference reference) - { - this(reference, null); - } - - /** - * Download of a {@link ResourceReference}. - * <p> - * The {@link IResource} returned by {@link ResourceReference#getResource()} must call - * {@link #markCompleted(Attributes)} when responding, otherwise the callback - * {@link #onDownloadSuccess(AjaxRequestTarget)} will not work. - * - * @param reference - * reference to resource to download - * @param resourceParameters - * parameters for the resource - */ - public AjaxDownload(ResourceReference reference, PageParameters resourceParameters) - { - this.resourceBehavior = null; - - this.resourceReference = Args.notNull(reference, "reference"); - this.resourceParameters = resourceParameters; - } - - @Override - protected void onBind() - { - super.onBind(); - - if (resourceBehavior != null) - { - getComponent().add(resourceBehavior); - } - } - - @Override - protected void onUnbind() - { - super.onUnbind(); - - if (resourceBehavior != null) - { - getComponent().remove(resourceBehavior); - } - } - - /** - * Call this method to initiate the download. - * - * @param target - * the initiating Ajax target - */ - public void initiate(AjaxRequestTarget target) - { - if (getComponent() == null) - { - throw new WicketRuntimeException("not bound to a component"); - } - - ((WebResponse)RequestCycle.get().getResponse()).clearCookie(cookie(getName())); - - CharSequence url; - if (resourceBehavior == null) - { - if (resourceReference.canBeRegistered()) - { - getComponent().getApplication().getResourceReferenceRegistry() - .registerResourceReference(resourceReference); - } - - PageParameters parameters = new PageParameters(); - if (resourceParameters != null) - { - parameters.mergeWith(resourceParameters); - } - parameters.set(RESOURCE_PARAMETER_NAME, getName()); - - url = getComponent().getRequestCycle() - .urlFor(new ResourceReferenceRequestHandler(resourceReference, parameters)); - } - else - { - url = resourceBehavior.getUrl(); - } - - JSONObject settings = new JSONObject(); - settings.put("attributes", new JSONFunction(renderAjaxAttributes(getComponent()))); - settings.put("name", getName()); - settings.put("downloadUrl", url); - settings.put("method", getLocation().name().toLowerCase(Locale.ENGLISH)); - - target.appendJavaScript(String.format("Wicket.AjaxDownload.initiate(%s);", settings)); - - onBeforeDownload(target); - } - - protected void onBeforeDownload(AjaxRequestTarget target) - { - } - - /** - * A callback executed when the download of the resource finished successfully. - * - * @param target The Ajax request handler - */ - protected void onDownloadSuccess(AjaxRequestTarget target) - { - } - - /** - * A callback executed when the download of the resource failed for some reason, - * e.g. an error at the server side. - * <p> - * Since the HTTP status code of the download is not available to Wicket, any HTML in the resource response - * will be interpreted as a failure HTTP status message. Thus is it not possible to download HTML resources - * via {@link AjaxDownload}. - * - * @param target The Ajax request handler - */ - protected void onDownloadFailed(AjaxRequestTarget target) - { - } - - /** - * A callback executed when the download of the resource finished successfully or with a failure. - * - * @param target The Ajax request handler - */ - protected void onDownloadCompleted(AjaxRequestTarget target) - { - } - - @Override - public void renderHead(Component component, IHeaderResponse response) - { - super.renderHead(component, response); - - response.render(JavaScriptHeaderItem.forReference(JS)); - } - - @Override - protected void respond(AjaxRequestTarget target) - { - String result = getComponent().getRequest().getRequestParameters().getParameterValue("result").toOptionalString(); - if ("success".equals(result)) { - onDownloadSuccess(target); - } else if ("failed".equals(result)) { - onDownloadFailed(target); - } - onDownloadCompleted(target); - } - - public Location getLocation() { - return location; - } - - public AjaxDownload setLocation(final Location location) { - this.location = Args.notNull(location, "location"); - return this; - } - - /** - * Identifying name of this behavior. - */ - private String getName() - { - return String.format("wicket-ajaxdownload-%s-%s", getComponent().getMarkupId(), - getComponent().getBehaviorId(this)); - } - - /** - * The behavior responding with the actual resource. - */ - private class ResourceBehavior extends Behavior implements IRequestListener - { - private final IResource resource; - - private ResourceBehavior(IResource resource) - { - this.resource = Args.notNull(resource, "resource"); - } - - @Override - public boolean rendersPage() - { - return false; - } - - @Override - public void onRequest() - { - final RequestCycle requestCycle = RequestCycle.get(); - final Response response = requestCycle.getResponse(); - ((WebResponse) response).addCookie(cookie(getName())); - - Attributes a = new Attributes(requestCycle.getRequest(), response, null); - - resource.respond(a); - } - - public CharSequence getUrl() - { - return getComponent().urlForListener(this, null); - } - } - - /** - * Mark a resource as complete. - * <p> - * Has to be called from {@link IResource#respond(Attributes)} when downloaded via - * {@link #AjaxDownload(IResource)}. - * - * @param attributes - * resource attributes - */ - public static void markCompleted(IResource.Attributes attributes) - { - String cookieName = attributes.getParameters().get(RESOURCE_PARAMETER_NAME).toString(); - - ((WebResponse)attributes.getResponse()).addCookie(cookie(cookieName)); - } - - private static Cookie cookie(String name) - { - Cookie cookie = new Cookie(name, "complete"); - - // has to be on root, otherwise JavaScript will not be able to access the - // cookie when it is set from a different path - which is the case when a - // ResourceReference is used - cookie.setPath("/"); - - return cookie; - } -} http://git-wip-us.apache.org/repos/asf/wicket/blob/1fc1e3d7/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownloadBehavior.java ---------------------------------------------------------------------- diff --git a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownloadBehavior.java b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownloadBehavior.java new file mode 100644 index 0000000..787c826 --- /dev/null +++ b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxDownloadBehavior.java @@ -0,0 +1,388 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.wicket.extensions.ajax; + +import java.util.Locale; + +import javax.annotation.Resource; +import javax.servlet.http.Cookie; + +import org.apache.wicket.Component; +import org.apache.wicket.IRequestListener; +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.ajax.json.JSONFunction; +import org.apache.wicket.behavior.Behavior; +import org.apache.wicket.markup.head.IHeaderResponse; +import org.apache.wicket.markup.head.JavaScriptHeaderItem; +import org.apache.wicket.request.Response; +import org.apache.wicket.request.cycle.RequestCycle; +import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler; +import org.apache.wicket.request.http.WebResponse; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.resource.ContentDisposition; +import org.apache.wicket.request.resource.IResource; +import org.apache.wicket.request.resource.IResource.Attributes; +import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.resource.JQueryPluginResourceReference; +import org.apache.wicket.util.lang.Args; + +import com.github.openjson.JSONObject; + +/** + * Download resources via Ajax. + * <p> + * Usage: + * + * <pre> + * final AjaxDownload download = new AjaxDownload(resource); + * add(download); + * + * add(new AjaxButton("download") + * { + * @Override + * protected void onSubmit(AjaxRequestTarget target, Form<?> form) + * { + * download.initiate(target); + * } + * }); + * </pre> + * + * <p>To set the name of the downloaded resource make use of + * {@link org.apache.wicket.request.resource.ResourceStreamResource#setFileName(String)} or + * {@link org.apache.wicket.request.resource.AbstractResource.ResourceResponse#setFileName(String)}</p> + * + * @author svenmeier + * @author Martin Grigorov + * @author Maxim Solodovnik + */ +public class AjaxDownloadBehavior extends AbstractDefaultAjaxBehavior +{ + private static final long serialVersionUID = 1L; + + public enum Location { + /** + * The resource will be downloaded into a {@code blob}. + * <p> + * This is recommended for modern browsers. + */ + Blob, + + /** + * The resource will be downloaded via a temporary created iframe, the resource has to be a + * {@link ContentDisposition#ATTACHMENT}. + * <p> + * This is recommended when there are resources in the DOM which will be + * closed automatically on JavaScript <em>unload</em> event, like WebSockets. + * Supports both <em>success</em> and <em>failure</em> callbacks! + */ + IFrame, + + /** + * The resource will be downloaded by changing the location of the current DOM document, + * the resource has to be a {@link ContentDisposition#ATTACHMENT}. + * <p> + * Note: This will trigger JavaScript <em>unload</em> event on the page! + * Does not support {@link AjaxDownloadBehavior#onDownloadFailed(AjaxRequestTarget)} callback, + * i.e. it is not possible to detect when the download has failed! + */ + SameWindow, + + /** + * The resource will be downloaded in a new browser window by using JavaScript <code>window.open()</code> API, + * the resource has to be a {@link ContentDisposition#INLINE}. + */ + NewWindow + } + + /** + * Name of parameter used to transfer the download identifier to the resource. + * + * @see #markCompleted(Attributes) + */ + private static final String RESOURCE_PARAMETER_NAME = "wicket-ajaxdownload"; + + private static final ResourceReference JS = new JQueryPluginResourceReference( + AjaxDownloadBehavior.class, "wicket-ajaxdownload.js"); + + private final ResourceReference resourceReference; + + private final ResourceBehavior resourceBehavior; + + private PageParameters resourceParameters; + + private Location location = Location.Blob; + + /** + * Download of a {@link Resource}. + * + * @param resource + * resource to download + */ + public AjaxDownloadBehavior(IResource resource) + { + Args.notNull(resource, "resource"); + this.resourceBehavior = new ResourceBehavior(resource); + this.resourceReference = null; + } + + /** + * Download of a {@link ResourceReference}. + * <p> + * The {@link IResource} returned by {@link ResourceReference#getResource()} must call + * {@link #markCompleted(Attributes)} when responding, otherwise the callback + * {@link #onDownloadSuccess(AjaxRequestTarget)} will not work. + * + * @param reference + * reference to resource to download + */ + public AjaxDownloadBehavior(ResourceReference reference) + { + this(reference, null); + } + + /** + * Download of a {@link ResourceReference}. + * <p> + * The {@link IResource} returned by {@link ResourceReference#getResource()} must call + * {@link #markCompleted(Attributes)} when responding, otherwise the callback + * {@link #onDownloadSuccess(AjaxRequestTarget)} will not work. + * + * @param reference + * reference to resource to download + * @param resourceParameters + * parameters for the resource + */ + public AjaxDownloadBehavior(ResourceReference reference, PageParameters resourceParameters) + { + this.resourceBehavior = null; + + this.resourceReference = Args.notNull(reference, "reference"); + this.resourceParameters = resourceParameters; + } + + @Override + protected void onBind() + { + super.onBind(); + + if (resourceBehavior != null) + { + getComponent().add(resourceBehavior); + } + } + + @Override + protected void onUnbind() + { + super.onUnbind(); + + if (resourceBehavior != null) + { + getComponent().remove(resourceBehavior); + } + } + + /** + * Call this method to initiate the download. + * + * @param target + * the initiating Ajax target + */ + public void initiate(AjaxRequestTarget target) + { + if (getComponent() == null) + { + throw new WicketRuntimeException("not bound to a component"); + } + + ((WebResponse)RequestCycle.get().getResponse()).clearCookie(cookie(getName())); + + CharSequence url; + if (resourceBehavior == null) + { + if (resourceReference.canBeRegistered()) + { + getComponent().getApplication().getResourceReferenceRegistry() + .registerResourceReference(resourceReference); + } + + PageParameters parameters = new PageParameters(); + if (resourceParameters != null) + { + parameters.mergeWith(resourceParameters); + } + parameters.set(RESOURCE_PARAMETER_NAME, getName()); + + url = getComponent().getRequestCycle() + .urlFor(new ResourceReferenceRequestHandler(resourceReference, parameters)); + } + else + { + url = resourceBehavior.getUrl(); + } + + JSONObject settings = new JSONObject(); + settings.put("attributes", new JSONFunction(renderAjaxAttributes(getComponent()))); + settings.put("name", getName()); + settings.put("downloadUrl", url); + settings.put("method", getLocation().name().toLowerCase(Locale.ENGLISH)); + + target.appendJavaScript(String.format("Wicket.AjaxDownload.initiate(%s);", settings)); + + onBeforeDownload(target); + } + + protected void onBeforeDownload(AjaxRequestTarget target) + { + } + + /** + * A callback executed when the download of the resource finished successfully. + * + * @param target The Ajax request handler + */ + protected void onDownloadSuccess(AjaxRequestTarget target) + { + } + + /** + * A callback executed when the download of the resource failed for some reason, + * e.g. an error at the server side. + * <p> + * Since the HTTP status code of the download is not available to Wicket, any HTML in the resource response + * will be interpreted as a failure HTTP status message. Thus is it not possible to download HTML resources + * via {@link AjaxDownloadBehavior}. + * + * @param target The Ajax request handler + */ + protected void onDownloadFailed(AjaxRequestTarget target) + { + } + + /** + * A callback executed when the download of the resource finished successfully or with a failure. + * + * @param target The Ajax request handler + */ + protected void onDownloadCompleted(AjaxRequestTarget target) + { + } + + @Override + public void renderHead(Component component, IHeaderResponse response) + { + super.renderHead(component, response); + + response.render(JavaScriptHeaderItem.forReference(JS)); + } + + @Override + protected void respond(AjaxRequestTarget target) + { + String result = getComponent().getRequest().getRequestParameters().getParameterValue("result").toOptionalString(); + if ("success".equals(result)) { + onDownloadSuccess(target); + } else if ("failed".equals(result)) { + onDownloadFailed(target); + } + onDownloadCompleted(target); + } + + public Location getLocation() { + return location; + } + + public AjaxDownloadBehavior setLocation(final Location location) { + this.location = Args.notNull(location, "location"); + return this; + } + + /** + * Identifying name of this behavior. + */ + private String getName() + { + return String.format("wicket-ajaxdownload-%s-%s", getComponent().getMarkupId(), + getComponent().getBehaviorId(this)); + } + + /** + * The behavior responding with the actual resource. + */ + private class ResourceBehavior extends Behavior implements IRequestListener + { + private final IResource resource; + + private ResourceBehavior(IResource resource) + { + this.resource = Args.notNull(resource, "resource"); + } + + @Override + public boolean rendersPage() + { + return false; + } + + @Override + public void onRequest() + { + final RequestCycle requestCycle = RequestCycle.get(); + final Response response = requestCycle.getResponse(); + ((WebResponse) response).addCookie(cookie(getName())); + + Attributes a = new Attributes(requestCycle.getRequest(), response, null); + + resource.respond(a); + } + + public CharSequence getUrl() + { + return getComponent().urlForListener(this, null); + } + } + + /** + * Mark a resource as complete. + * <p> + * Has to be called from {@link IResource#respond(Attributes)} when downloaded via + * {@link #AjaxDownloadBehavior(IResource)}. + * + * @param attributes + * resource attributes + */ + public static void markCompleted(IResource.Attributes attributes) + { + String cookieName = attributes.getParameters().get(RESOURCE_PARAMETER_NAME).toString(); + + ((WebResponse)attributes.getResponse()).addCookie(cookie(cookieName)); + } + + private static Cookie cookie(String name) + { + Cookie cookie = new Cookie(name, "complete"); + + // has to be on root, otherwise JavaScript will not be able to access the + // cookie when it is set from a different path - which is the case when a + // ResourceReference is used + cookie.setPath("/"); + + return cookie; + } +}
