Author: martinc
Date: Fri Oct 29 19:50:56 2004
New Revision: 56011

Added:
   struts/trunk/src/share/org/apache/struts/actions/DownloadAction.java
Log:
New abstract action that provides the nuts and bolts for downloading files from a 
Struts application.

Added: struts/trunk/src/share/org/apache/struts/actions/DownloadAction.java
==============================================================================
--- (empty file)
+++ struts/trunk/src/share/org/apache/struts/actions/DownloadAction.java        Fri 
Oct 29 19:50:56 2004
@@ -0,0 +1,273 @@
+/*

+ * $Id$

+ *

+ * Copyright 2004 The Apache Software Foundation.

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+

+package org.apache.struts.actions;

+

+import java.io.BufferedInputStream;

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.IOException;

+import java.io.InputStream;

+import java.io.OutputStream;

+

+import javax.servlet.ServletContext;

+import javax.servlet.http.HttpServletRequest;

+import javax.servlet.http.HttpServletResponse;

+

+import org.apache.struts.action.Action;

+import org.apache.struts.action.ActionForm;

+import org.apache.struts.action.ActionForward;

+import org.apache.struts.action.ActionMapping;

+

+

+/**

+ * This is an abstract base class that minimizes the amount of special coding

+ * that needs to be written to download a file. All that is required to use

+ * this class is to extend it and implement the <code>getStreamInfo()</code>

+ * method so that it returns the relevant information for the file (or other

+ * stream) to be downloaded. Optionally, the <code>getBufferSize()</code>

+ * method may be overridden to customize the size of the buffer used to

+ * transfer the file.

+ *

+ * @since Struts 1.2.6

+ */

+public abstract class DownloadAction extends Action {

+

+    /**

+     * If the <code>getBufferSize()</code> method is not overridden, this is

+     * the buffer size that will be used to transfer the data to the servlet

+     * output stream.

+     */

+    protected static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

+

+    /**

+     * Returns the information on the file, or other stream, to be downloaded

+     * by this action. This method must be implemented by an extending class.

+     *

+     * @param mapping  The ActionMapping used to select this instance.

+     * @param form     The optional ActionForm bean for this request (if any).

+     * @param request  The HTTP request we are processing.

+     * @param response The HTTP response we are creating.

+     *

+     * @return The information for the file to be downloaded.

+     *

+     * @throws Exception if an exception occurs.

+     */

+    protected abstract StreamInfo getStreamInfo(ActionMapping mapping,

+            ActionForm form, HttpServletRequest request,

+            HttpServletResponse response)

+            throws Exception;

+

+    /**

+     * Returns the size of the buffer to be used in transferring the data to

+     * the servlet output stream. This method may be overridden by an extending

+     * class in order to customize the buffer size.

+     *

+     * @return The size of the transfer buffer, in bytes.

+     */

+    protected int getBufferSize() {

+        return DEFAULT_BUFFER_SIZE;

+    }

+

+    /**

+     * Process the specified HTTP request, and create the corresponding HTTP

+     * response (or forward to another web component that will create it).

+     * Return an <code>ActionForward</code> instance describing where and how

+     * control should be forwarded, or <code>null</code> if the response has

+     * already been completed.

+     *

+     * @param mapping  The ActionMapping used to select this instance.

+     * @param form     The optional ActionForm bean for this request (if any).

+     * @param request  The HTTP request we are processing.

+     * @param response The HTTP response we are creating.

+     *

+     * @throws Exception if an exception occurs.

+     */

+    public ActionForward execute(ActionMapping mapping, ActionForm form,

+            HttpServletRequest request, HttpServletResponse response)

+            throws Exception {

+

+        StreamInfo info = getStreamInfo(mapping, form, request, response);

+        String contentType = info.getContentType();

+        InputStream stream = info.getInputStream();

+

+        try {

+            response.setContentType(contentType);

+            copy(stream, response.getOutputStream());

+        } finally {

+            if (stream != null) {

+                stream.close();

+            }

+        }

+

+        // Tell Struts that we are done with the response.

+        return null;

+    }

+

+    /**

+     * Copy bytes from an <code>InputStream</code> to an

+     * <code>OutputStream</code>.

+     *

+     * @param input  The <code>InputStream</code> to read from.

+     * @param output The <code>OutputStream</code> to write to.

+     *

+     * @return the number of bytes copied

+     *

+     * @throws IOException In case of an I/O problem

+     */

+    public static int copy(InputStream input, OutputStream output)

+            throws IOException {

+        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

+        int count = 0;

+        int n = 0;

+        while (-1 != (n = input.read(buffer))) {

+            output.write(buffer, 0, n);

+            count += n;

+        }

+        return count;

+    }

+

+    /**

+     * The information on a file, or other stream, to be downloaded by the

+     * <code>DownloadAction</code>.

+     */

+    public static interface StreamInfo {

+

+        /**

+         * Returns the content type of the stream to be downloaded.

+         *

+         * @return The content type of the stream.

+         */

+        public abstract String getContentType();

+

+        /**

+         * Returns an input stream on the content to be downloaded. This stream

+         * will be closed by the <code>DownloadAction</code>.

+         *

+         * @return The input stream for the content to be downloaded.

+         */

+        public abstract InputStream getInputStream() throws IOException;

+    }

+

+    /**

+     * A concrete implementation of the <code>StreamInfo</code> interface which

+     * simplifies the downloading of a file from the disk.

+     */

+    public static class FileStreamInfo implements StreamInfo {

+

+        /**

+         * The content type for this stream.

+         */

+        private String contentType;

+

+        /**

+         * The file to be downloaded.

+         */

+        private File file;

+

+        /**

+         * Constructs an instance of this class, based on the supplied

+         * parameters.

+         *

+         * @param contentType The content type of the file.

+         * @param file        The file to be downloaded.

+         */

+        public FileStreamInfo(String contentType, File file) {

+            this.contentType = contentType;

+            this.file = file;

+        }

+

+        /**

+         * Returns the content type of the stream to be downloaded.

+         *

+         * @return The content type of the stream.

+         */

+        public String getContentType() {

+            return this.contentType;

+        }

+

+        /**

+         * Returns an input stream on the file to be downloaded. This stream

+         * will be closed by the <code>DownloadAction</code>.

+         *

+         * @return The input stream for the file to be downloaded.

+         */

+        public InputStream getInputStream() throws IOException {

+            FileInputStream fis = new FileInputStream(file);

+            BufferedInputStream bis = new BufferedInputStream(fis);

+            return bis;

+        }

+    }

+

+    /**

+     * A concrete implementation of the <code>StreamInfo</code> interface which

+     * simplifies the downloading of a web application resource.

+     */

+    public static class ResourceStreamInfo implements StreamInfo {

+

+        /**

+         * The content type for this stream.

+         */

+        private String contentType;

+

+        /**

+         * The servlet context for the resource to be downloaded.

+         */

+        private ServletContext context;

+

+        /**

+         * The path to the resource to be downloaded.

+         */

+        private String path;

+

+        /**

+         * Constructs an instance of this class, based on the supplied

+         * parameters.

+         *

+         * @param contentType The content type of the file.

+         * @param context     The servlet context for the resource.

+         * @param path        The path to the resource to be downloaded.

+         */

+        public ResourceStreamInfo(String contentType, ServletContext context,

+                String path) {

+            this.contentType = contentType;

+            this.context = context;

+            this.path = path;

+        }

+

+        /**

+         * Returns the content type of the stream to be downloaded.

+         *

+         * @return The content type of the stream.

+         */

+        public String getContentType() {

+            return this.contentType;

+        }

+

+        /**

+         * Returns an input stream on the resource to be downloaded. This stream

+         * will be closed by the <code>DownloadAction</code>.

+         *

+         * @return The input stream for the resource to be downloaded.

+         */

+        public InputStream getInputStream() throws IOException {

+            return context.getResourceAsStream(path);

+        }

+    }

+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to