You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by so...@apache.org on 2017/09/22 17:23:04 UTC
[27/50] [abbrv] wicket git commit: WICKET-6460 Rename AjaxDownload to
AjaxDownloadBehavior
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/WICKET-6105-java.time
Commit: 1fc1e3d7040ed2f3e73e7067efd201a958a90b3e
Parents: 1f805dd
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Mon Sep 4 22:26:30 2017 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
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;
+ }
+}