org.sakaiproject.metaobj.shared.control.servlet.FileDownloadServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.metaobj.shared.control.servlet.FileDownloadServlet.java

Source

/**********************************************************************************
 * $URL: https://source.sakaiproject.org/svn/metaobj/trunk/metaobj-util/tool-lib/src/java/org/sakaiproject/metaobj/shared/control/servlet/FileDownloadServlet.java $
 * $Id: FileDownloadServlet.java 105079 2012-02-24 23:08:11Z ottenhoff@longsight.com $
 ***********************************************************************************
 *
 * Copyright (c) 2005, 2006, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.metaobj.shared.control.servlet;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.metaobj.shared.DownloadableManager;

public class FileDownloadServlet extends HttpServlet {
    protected final Log logger = LogFactory.getLog(getClass());

    public final static String REPOSITORY_PREFIX = "repository";
    private static final String MANAGER_NAME = "manager";

    /**
     * Called by the server (via the <code>service</code> method) to
     * allow a servlet to handle a GET request.
     * <p/>
     * <p>Overriding this method to support a GET request also
     * automatically supports an HTTP HEAD request. A HEAD
     * request is a GET request that returns no body in the
     * response, only the request header fields.
     * <p/>
     * <p>When overriding this method, read the request data,
     * write the response headers, get the response's writer or
     * output stream object, and finally, write the response data.
     * It's best to include content type and encoding. When using
     * a <code>PrintWriter</code> object to return the response,
     * set the content type before accessing the
     * <code>PrintWriter</code> object.
     * <p/>
     * <p>The servlet container must write the headers before
     * committing the response, because in HTTP the headers must be sent
     * before the response body.
     * <p/>
     * <p>Where possible, set the Content-Length header (with the
     * {@link javax.servlet.ServletResponse#setContentLength} method),
     * to allow the servlet container to use a persistent connection
     * to return its response to the client, improving performance.
     * The content length is automatically set if the entire response fits
     * inside the response buffer.
     * <p/>
     * <p>When using HTTP 1.1 chunked encoding (which means that the response
     * has a Transfer-Encoding header), do not set the Content-Length header.
     * <p/>
     * <p>The GET method should be safe, that is, without
     * any side effects for which users are held responsible.
     * For example, most form queries have no side effects.
     * If a client request is intended to change stored data,
     * the request should use some other HTTP method.
     * <p/>
     * <p>The GET method should also be idempotent, meaning
     * that it can be safely repeated. Sometimes making a
     * method safe also makes it idempotent. For example,
     * repeating queries is both safe and idempotent, but
     * buying a product online or modifying data is neither
     * safe nor idempotent.
     * <p/>
     * <p>If the request is incorrectly formatted, <code>doGet</code>
     * returns an HTTP "Bad Request" message.
     *
     * @param request  an {@link javax.servlet.http.HttpServletRequest} object that
     *                 contains the request the client has made
     *                 of the servlet
     * @param response an {@link javax.servlet.http.HttpServletResponse} object that
     *                 contains the response the servlet sends
     *                 to the client
     * @throws java.io.IOException            if an input or output error is
     *                                        detected when the servlet handles
     *                                        the GET request
     * @throws javax.servlet.ServletException if the request for the GET
     *                                        could not be handled
     * @see javax.servlet.ServletResponse#setContentType
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        java.util.Enumeration tokenizer = new StringTokenizer(request.getRequestURI(), "/");

        if (!tokenizer.hasMoreElements()) {
            throw new ServletException("Incorrect format url.");
        }
        String base = (String) tokenizer.nextElement(); // burn off the first element of the path

        while (!base.equalsIgnoreCase(REPOSITORY_PREFIX)) {
            if (!tokenizer.hasMoreElements()) {
                throw new ServletException("Incorrect format url.");
            }
            base = (String) tokenizer.nextElement();
        }

        Hashtable params = HttpUtils.parseQueryString(getNextToken(tokenizer));

        DownloadableManager manager = getDownloadableManager(((String[]) params.get(MANAGER_NAME))[0]);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String filename = manager.packageForDownload(params, bos);

        response.setHeader("Content-Type", "application/octet-stream");
        response.setHeader("Content-Disposition", "attachment"
                + ((filename != null && !filename.equals("")) ? ";filename=\"" + filename + "\"" : ""));
        response.setHeader("Content-Length", Integer.toString(bos.size()));

        copyStream(new ByteArrayInputStream(bos.toByteArray()), response.getOutputStream());

    }

    private void copyStream(InputStream in, OutputStream out) throws IOException {
        byte data[] = new byte[1024 * 10];

        BufferedInputStream origin = new BufferedInputStream(in, data.length);

        int count;
        while ((count = origin.read(data, 0, data.length)) != -1) {
            out.write(data, 0, count);
        }
        in.close();
        out.flush();
    }

    protected DownloadableManager getDownloadableManager(String name) {
        return (DownloadableManager) ComponentManager.get(name);
    }

    protected String getNextToken(Enumeration tokenizer) throws ServletException {
        if (!tokenizer.hasMoreElements()) {
            throw new ServletException("Incorrect format url.");
        }
        return (String) tokenizer.nextElement();
    }

}