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")
- * {
- *     &#64;Override
- *     protected void onSubmit(AjaxRequestTarget target, Form&lt;?> 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")
+ * {
+ *     &#64;Override
+ *     protected void onSubmit(AjaxRequestTarget target, Form&lt;?> 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;
+       }
+}

Reply via email to