001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.servlet;
034:
035: import com.flexive.shared.EJBLookup;
036: import com.flexive.shared.FxSharedUtils;
037: import com.flexive.shared.content.FxContent;
038: import com.flexive.shared.content.FxPK;
039: import com.flexive.shared.exceptions.FxApplicationException;
040: import com.flexive.shared.value.BinaryDescriptor;
041:
042: import javax.servlet.*;
043: import javax.servlet.http.HttpServletRequest;
044: import javax.servlet.http.HttpServletResponse;
045: import java.io.IOException;
046: import java.io.UnsupportedEncodingException;
047: import java.net.URLDecoder;
048: import java.net.URLEncoder;
049:
050: /**
051: * <p>Provides streaming downloads for all binary objects ({@link com.flexive.shared.value.FxBinary FxBinary}).
052: * The requested value is identified by its XPath.</p>
053: * <p>Link format:</p>
054: * <pre>/download/pk{n.m}/xpath/filename.ext</pre>
055: *
056: * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
057: * @version $Rev: 1 $
058: */
059: public class DownloadServlet implements Servlet {
060: private final static String BASEURL = "/download/";
061: private ServletConfig servletConfig;
062:
063: public void init(ServletConfig servletConfig)
064: throws ServletException {
065: this .servletConfig = servletConfig;
066: }
067:
068: public ServletConfig getServletConfig() {
069: return servletConfig;
070: }
071:
072: public String getServletInfo() {
073: return this .getClass().getName();
074: }
075:
076: public void destroy() {
077: // nothing to do
078: }
079:
080: public void service(ServletRequest servletRequest,
081: ServletResponse servletResponse) throws ServletException,
082: IOException {
083: HttpServletRequest request = (HttpServletRequest) servletRequest;
084: HttpServletResponse response = (HttpServletResponse) servletResponse;
085: final String uri = URLDecoder.decode(request.getRequestURI()
086: .substring(
087: request.getContextPath().length()
088: + BASEURL.length()), "UTF-8");
089: // get PK
090: if (!uri.startsWith("pk")) {
091: FxServletUtils.sendErrorMessage(response,
092: "Invalid download getResult: " + uri);
093: return;
094: }
095: final FxPK pk;
096: try {
097: pk = FxPK.fromString(uri.substring(2, uri.indexOf('/')));
098: } catch (IllegalArgumentException e) {
099: FxServletUtils.sendErrorMessage(response,
100: "Invalid primary key in getResult: " + uri);
101: return;
102: }
103: // load content
104: final FxContent content;
105: try {
106: content = EJBLookup.getContentEngine().load(pk);
107: } catch (FxApplicationException e) {
108: FxServletUtils.sendErrorMessage(response,
109: "Failed to load content: " + e.getMessage());
110: return;
111: }
112: // extract xpath
113: final String xpath;
114: try {
115: xpath = FxSharedUtils.decodeXPath(uri.substring(uri
116: .indexOf('/') + 1, uri.lastIndexOf('/')));
117: } catch (IndexOutOfBoundsException e) {
118: FxServletUtils.sendErrorMessage(response,
119: "Invalid xpath/filename in getResult: " + uri);
120: return;
121: }
122: // get binary descriptor
123: final BinaryDescriptor descriptor;
124: try {
125: descriptor = (BinaryDescriptor) content.getValue(xpath)
126: .getBestTranslation();
127: } catch (Exception e) {
128: FxServletUtils.sendErrorMessage(response,
129: "Failed to load binary value: " + e.getMessage());
130: return;
131: }
132: // stream content
133: try {
134: response.setContentType(descriptor.getMimeType());
135: response.setContentLength((int) descriptor.getSize());
136: response.setHeader("Content-Disposition",
137: "attachment; filename=\"" + descriptor.getName()
138: + "\";");
139: descriptor.download(response.getOutputStream());
140: } catch (Exception e) {
141: FxServletUtils.sendErrorMessage(response,
142: "Download failed: " + e.getMessage());
143: //noinspection UnnecessaryReturnStatement
144: return;
145: } finally {
146: response.getOutputStream().close();
147: }
148: }
149:
150: /**
151: * Returns a link (absolute to the server context) to download the binary stored under
152: * the given XPath for the given object. <code>fileName</code> is the filename visible to
153: * the browser, the actual name of the downloaded file is determined by the stored filename.
154: *
155: * @param pk the object pk
156: * @param xpath the XPath of the binary property to be downloaded
157: * @param fileName the filename visible to the browser
158: * @return a link (absolute to the server context) to download the given binary
159: */
160: public static String getLink(FxPK pk, String xpath, String fileName) {
161: try {
162: return BASEURL
163: + "pk"
164: + pk
165: + "/"
166: + URLEncoder.encode(FxSharedUtils
167: .escapeXPath(xpath), "UTF-8") + "/"
168: + fileName;
169: } catch (UnsupportedEncodingException e) {
170: // shouldn't happen with UTF-8
171: throw new IllegalArgumentException(e);
172: }
173: }
174: }
|