/* * @(#)DownloadResponse.java 1.8 07/03/15 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. */ package jnlp.sample.servlet; import java.io.*; import java.util.*; import java.net.URL; import java.net.URLConnection; import javax.servlet.http.HttpServletResponse; /** * A class used to encapsulate a file response, and * factory methods to create some common types. */ abstract public class DownloadResponse { private static final String HEADER_LASTMOD = "Last-Modified"; private static final String HEADER_JNLP_VERSION = "x-java-jnlp-version-id"; private static final String JNLP_ERROR_MIMETYPE = "application/x-java-jnlp-error"; public static final int STS_00_OK = 0; public static final int ERR_10_NO_RESOURCE = 10; public static final int ERR_11_NO_VERSION = 11; public static final int ERR_20_UNSUP_OS = 20; public static final int ERR_21_UNSUP_ARCH = 21; public static final int ERR_22_UNSUP_LOCALE = 22; public static final int ERR_23_UNSUP_JRE = 23; public static final int ERR_99_UNKNOWN = 99; // HTTP Compression RFC 2616 : Standard headers public static final String CONTENT_ENCODING = "content-encoding"; // HTTP Compression RFC 2616 : Standard header for HTTP/Pack200 Compression public static final String GZIP_ENCODING = "gzip"; public static final String PACK200_GZIP_ENCODING = "pack200-gzip"; public DownloadResponse() { /* do nothing */ } public String toString() { return getClass().getName(); } /** Post information to an HttpResponse */ abstract void sendRespond(HttpServletResponse response) throws IOException; /** Factory methods for error responses */ static DownloadResponse getNotFoundResponse() { return new NotFoundResponse(); } static DownloadResponse getNoContentResponse() { return new NotFoundResponse(); } static DownloadResponse getJnlpErrorResponse(int jnlpErrorCode) { return new JnlpErrorResponse(jnlpErrorCode); } /** Factory method for file download responses */ static DownloadResponse getNotModifiedResponse() { return new NotModifiedResponse(); } static DownloadResponse getHeadRequestResponse(String mimeType, String versionId, long lastModified, int contentLength) { return new HeadRequestResponse(mimeType, versionId, lastModified, contentLength); } static DownloadResponse getFileDownloadResponse(byte[] content, String mimeType, long timestamp, String versionId) { return new ByteArrayFileDownloadResponse(content, mimeType, versionId, timestamp); } static DownloadResponse getFileDownloadResponse(URL resource, String mimeType, long timestamp, String versionId) { return new ResourceFileDownloadResponse(resource, mimeType, versionId, timestamp); } static DownloadResponse getFileDownloadResponse(File file, String mimeType, long timestamp, String versionId) { return new DiskFileDownloadResponse(file, mimeType, versionId, timestamp); } // // Private classes implementing the various types // static private class NotModifiedResponse extends DownloadResponse { public void sendRespond(HttpServletResponse response) throws IOException { response.sendError(HttpServletResponse.SC_NOT_MODIFIED); } } static private class NotFoundResponse extends DownloadResponse { public void sendRespond(HttpServletResponse response) throws IOException { response.sendError(HttpServletResponse.SC_NOT_FOUND); } } static private class NoContentResponse extends DownloadResponse { public void sendRespond(HttpServletResponse response) throws IOException { response.sendError(HttpServletResponse.SC_NO_CONTENT); } } static private class HeadRequestResponse extends DownloadResponse { private String _mimeType; private String _versionId; private long _lastModified; private int _contentLength; HeadRequestResponse(String mimeType, String versionId, long lastModified, int contentLength) { _mimeType = mimeType; _versionId = versionId; _lastModified = lastModified; _contentLength = contentLength; } /** Post information to an HttpResponse */ public void sendRespond(HttpServletResponse response) throws IOException { // Set header information response.setContentType(_mimeType); response.setContentLength(_contentLength); if (_versionId != null) { response.setHeader(HEADER_JNLP_VERSION, _versionId); } if (_lastModified != 0) { response.setDateHeader(HEADER_LASTMOD, _lastModified); } response.sendError(HttpServletResponse.SC_OK); } } static public class JnlpErrorResponse extends DownloadResponse { private String _message; public JnlpErrorResponse(int jnlpErrorCode) { String msg = Integer.toString(jnlpErrorCode); String dsc = "No description"; try { dsc = JnlpDownloadServlet.getResourceBundle().getString("servlet.jnlp.err." + msg); } catch (MissingResourceException mre) { /* ignore */} _message = msg + " " + dsc; } public void sendRespond(HttpServletResponse response) throws IOException { response.setContentType(JNLP_ERROR_MIMETYPE); PrintWriter pw = response.getWriter(); pw.println(_message); }; public String toString() { return super.toString() + "[" + _message + "]"; } } static private abstract class FileDownloadResponse extends DownloadResponse { private String _mimeType; private String _versionId; private long _lastModified; private String _fileName; FileDownloadResponse(String mimeType, String versionId, long lastModified) { _mimeType = mimeType; _versionId = versionId; _lastModified = lastModified; _fileName = null; } FileDownloadResponse(String mimeType, String versionId, long lastModified, String fileName) { _mimeType = mimeType; _versionId = versionId; _lastModified = lastModified; _fileName = fileName; } /** Information about response */ String getMimeType() { return _mimeType; } String getVersionId() { return _versionId; } long getLastModified() { return _lastModified; } abstract int getContentLength() throws IOException; abstract InputStream getContent() throws IOException; /** Post information to an HttpResponse */ public void sendRespond(HttpServletResponse response) throws IOException { // Set header information response.setContentType(getMimeType()); response.setContentLength(getContentLength()); if (getVersionId() != null) response.setHeader(HEADER_JNLP_VERSION, getVersionId()); if (getLastModified() != 0) response.setDateHeader(HEADER_LASTMOD, getLastModified()); if (_fileName != null) { if (_fileName.endsWith(".pack.gz")) { response.setHeader(CONTENT_ENCODING, PACK200_GZIP_ENCODING ); } else if (_fileName.endsWith(".gz")) { response.setHeader(CONTENT_ENCODING, GZIP_ENCODING ); } else { response.setHeader(CONTENT_ENCODING, null); } } // Send contents InputStream in = getContent(); OutputStream out = response.getOutputStream(); try { byte[] bytes = new byte[32 * 1024]; int read; while ((read = in.read(bytes)) != -1) { out.write(bytes, 0, read); } } finally { if (in != null) in.close(); } } protected String getArgString() { long length = 0; try { length = getContentLength(); } catch(IOException ioe) { /* ignore */ } return "Mimetype=" + getMimeType() + " VersionId=" + getVersionId() + " Timestamp=" + new Date(getLastModified()) + " Length=" + length; } } static private class ByteArrayFileDownloadResponse extends FileDownloadResponse { private byte[] _content; ByteArrayFileDownloadResponse(byte[] content, String mimeType, String versionId, long lastModified) { super(mimeType, versionId, lastModified); _content = content; } int getContentLength() { return _content.length; } InputStream getContent() { return new ByteArrayInputStream(_content); } public String toString() { return super.toString() + "[ " + getArgString() + "]"; } } static private class ResourceFileDownloadResponse extends FileDownloadResponse { URL _url; ResourceFileDownloadResponse(URL url, String mimeType, String versionId, long lastModified) { super(mimeType, versionId, lastModified, url.toString()); _url= url; } int getContentLength() throws IOException { return _url.openConnection().getContentLength(); } InputStream getContent() throws IOException { return _url.openConnection().getInputStream(); } public String toString() { return super.toString() + "[ " + getArgString() + "]"; } } static private class DiskFileDownloadResponse extends FileDownloadResponse { private File _file; DiskFileDownloadResponse(File file, String mimeType, String versionId, long lastModified) { super(mimeType, versionId, lastModified, file.getName()); _file = file; } int getContentLength() throws IOException { return (int)_file.length(); } InputStream getContent() throws IOException { return new BufferedInputStream(new FileInputStream(_file)); } public String toString() { return super.toString() + "[ " + getArgString() + "]"; } } }