ODSFilter.java

// license-header java merge-point
// Generated by andromda-jsf cartridge (utils\ODSFilter.java.vsl) DO NOT EDIT!
package org.andromda.presentation.jsf;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

/**
 * Exports the response as ODS file.
 *
 * @author Walter Mourao
 */
public class ODSFilter implements Filter
{
    /**
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    @Override
    public void init(FilterConfig config) throws ServletException
    {
        // Empty block
    }

    /**
     * Decorates a FileOutputStream.
     *
     * @author Walter Mourao
     */
    public class ODSOutputStream extends ServletOutputStream
    {
        private final FileOutputStream fos;
        /**
         * @param file
         * @throws FileNotFoundException
         */
        public ODSOutputStream(File file) throws FileNotFoundException
        {
            super();
            this.fos = new FileOutputStream(file);
        }

        /**
         * @see java.io.OutputStream#write(int)
         */
        @Override
        public void write(int b) throws IOException
        {
            this.fos.write(b);
        }
    }

    /**
     * Decorates a HttpServletResponse.
     *
     * @author Walter Mourao
     */
    public class ODSResponseWrapper extends HttpServletResponseWrapper
    {
        private final File tempFile;
        final ODSOutputStream oos;
        final PrintWriter pw;
        int status;

        /**
         * @param response
         */
        public ODSResponseWrapper(HttpServletResponse response)
        {
            super(response);
            try
            {
                this.tempFile=File.createTempFile("odsFilter_", "_tmp");
                this.oos=new ODSOutputStream(this.tempFile);
                this.pw=new PrintWriter(this.oos);
                this.status=200;
            }
            catch (Exception e)
            {
                throw new RuntimeException(e);
            }
        }

        /**
         * @return tempFile
         */
        public File getFile()
        {
            return this.tempFile;
        }

        /**
         * @see javax.servlet.ServletResponseWrapper#getOutputStream()
         */
        @Override
        public ServletOutputStream getOutputStream() throws IOException
        {
            return this.oos;
        }

        /**
         * @see javax.servlet.ServletResponseWrapper#getWriter()
         */
        @Override
        public PrintWriter getWriter() throws IOException
        {
            return this.pw;
        }

        /**
         * @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
         */
        @Override
        public void setStatus(int statusIn)
        {
            super.setStatus(statusIn);
            this.status=statusIn;
        }

        /**
         * @return status
         */
        public int getStatus()
        {
            return this.status;
        }

        /**
         * @see javax.servlet.http.HttpServletResponseWrapper#sendError(int, java.lang.String)
         */
        @Override
        public void sendError(int sc, String msg) throws IOException
        {
            super.sendError(sc, msg);
            this.status=sc;
        }

        /**
         * @see javax.servlet.http.HttpServletResponseWrapper#sendError(int)
         */
        @Override
        public void sendError(int sc) throws IOException
        {
            super.sendError(sc);
            this.status=sc;
        }

        /**
         *
         */
        public void deleteTempFile()
        {
            try
            {
                FileUtils.forceDelete(this.tempFile);
            }
            catch(IOException e)
            {
                //do nothing
            }
        }

        /**
         * @see Object#finalize()
         */
        @Override
        protected void finalize() throws Throwable {
            deleteTempFile();
            super.finalize();
        }
    }

    final private static String MANIFEST_CONTENTS=
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"+
        "<manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\">\n"+
            "<manifest:file-entry manifest:full-path=\"/\" manifest:media-type=\"application/vnd.oasis.opendocument.spreadsheet\" />\n"+
            "<manifest:file-entry manifest:full-path=\"META-INF/manifest.xml\" manifest:media-type=\"text/xml\" />\n"+
            "<manifest:file-entry manifest:full-path=\"content.xml\" manifest:media-type=\"text/xml\" />\n"+
            "<manifest:file-entry manifest:full-path=\"mimetype\" manifest:media-type=\"text/plain\" />\n"+
            "<manifest:file-entry manifest:full-path=\"styles.xml\" manifest:media-type=\"text/xml\" />\n"+
        "</manifest:manifest>";
    final private static String MIMETYPE_CONTENTS="application/vnd.oasis.opendocument.spreadsheet";
    final private static String STYLES_CONTENTS=
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"+
        "<office:document-styles xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\">\n"+
        "</office:document-styles>";

    /**
     * Add a string as a zip file entry.
     *
     * @param zos the destination
     * @param name the entry name
     * @param content the entry content
     * @throws IOException
     */
    private void addStringEntry(ZipOutputStream zos, String name, String content) throws IOException
    {
        zos.putNextEntry(new ZipEntry(name));
        IOUtils.copy(new StringReader(content), zos);
        zos.closeEntry();
    }

    /**
     * @param request
     * @param response
     * @param chain
     * @throws IOException
     * @throws ServletException
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException
    {

        final HttpServletResponse httpResponse=(HttpServletResponse)response;
        final ODSResponseWrapper responseWrapper=new ODSResponseWrapper(httpResponse);

        chain.doFilter(request, responseWrapper);
        if(responseWrapper.getStatus() == 200)
        {
            final HttpServletRequest httpRequest=(HttpServletRequest)request;
            final String fileName=FilenameUtils.getBaseName(StringUtils.substringBefore(httpRequest.getRequestURI(), "?"));

            httpResponse.reset();
            httpResponse.setContentType(MIMETYPE_CONTENTS);
            httpResponse.setHeader("Content-disposition", "attachment; filename=\""+fileName+".ods\"");

            responseWrapper.getWriter().close();
            responseWrapper.getOutputStream().flush();
            responseWrapper.getOutputStream().close();

            final FileInputStream fis=new FileInputStream(responseWrapper.getFile());
            final ZipOutputStream zos=new ZipOutputStream(httpResponse.getOutputStream());

            zos.putNextEntry(new ZipEntry("content.xml"));
            IOUtils.copy(fis, zos);
            zos.closeEntry();
            addStringEntry(zos,"mimetype",MIMETYPE_CONTENTS);
            zos.closeEntry();
            addStringEntry(zos,"styles.xml",STYLES_CONTENTS);
            zos.putNextEntry(new ZipEntry("META-INF/"));
            zos.closeEntry();
            addStringEntry(zos,"META-INF/manifest.xml",MANIFEST_CONTENTS);
            zos.close();

            responseWrapper.deleteTempFile();
        }
        else
        {
            IOUtils.copy(new FileInputStream(responseWrapper.getFile()),httpResponse.getOutputStream());
        }
    }

    /**
     * @see javax.servlet.Filter#destroy()
     */
    @Override
    public void destroy()
    {
        // Empty block
    }
}