1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.util.servlet;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.servlet.HttpHeaders;
20  import com.liferay.portal.kernel.util.ArrayUtil;
21  import com.liferay.portal.kernel.util.FileUtil;
22  import com.liferay.portal.kernel.util.GetterUtil;
23  import com.liferay.portal.kernel.util.PropsUtil;
24  import com.liferay.portal.kernel.util.StreamUtil;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.util.Validator;
28  
29  import java.io.IOException;
30  import java.io.InputStream;
31  import java.io.OutputStream;
32  
33  import javax.portlet.MimeResponse;
34  import javax.portlet.ResourceResponse;
35  
36  import org.apache.commons.codec.net.URLCodec;
37  import org.apache.commons.lang.CharUtils;
38  
39  /**
40   * <a href="PortletResponseUtil.java.html"><b><i>View Source</i></b></a>
41   *
42   * @author Brian Wing Shun Chan
43   */
44  public class PortletResponseUtil {
45  
46      public static void sendFile(
47              MimeResponse mimeResponse, String fileName, byte[] bytes)
48          throws IOException {
49  
50          sendFile(mimeResponse, fileName, bytes, null);
51      }
52  
53      public static void sendFile(
54              MimeResponse mimeResponse, String fileName, byte[] bytes,
55              String contentType)
56          throws IOException {
57  
58          setHeaders(mimeResponse, fileName, contentType);
59  
60          write(mimeResponse, bytes);
61      }
62  
63      public static void sendFile(
64              MimeResponse mimeResponse, String fileName, InputStream is)
65          throws IOException {
66  
67          sendFile(mimeResponse, fileName, is, null);
68      }
69  
70      public static void sendFile(
71              MimeResponse mimeResponse, String fileName, InputStream is,
72              String contentType)
73          throws IOException {
74  
75          sendFile(mimeResponse, fileName, is, 0, contentType);
76      }
77  
78      public static void sendFile(
79              MimeResponse mimeResponse, String fileName, InputStream is,
80              int contentLength, String contentType)
81          throws IOException {
82  
83          setHeaders(mimeResponse, fileName, contentType);
84  
85          write(mimeResponse, is, contentLength);
86      }
87  
88      public static void write(MimeResponse mimeResponse, String s)
89          throws IOException {
90  
91          write(mimeResponse, s.getBytes(StringPool.UTF8));
92      }
93  
94      public static void write(MimeResponse mimeResponse, byte[] bytes)
95          throws IOException {
96  
97          write(mimeResponse, bytes, 0);
98      }
99  
100     public static void write(
101             MimeResponse mimeResponse, byte[] bytes, int contentLength)
102         throws IOException {
103 
104         // LEP-3122
105 
106         if (!mimeResponse.isCommitted()) {
107 
108             // LEP-536
109 
110             if (contentLength == 0) {
111                 contentLength = bytes.length;
112             }
113 
114             if (mimeResponse instanceof ResourceResponse) {
115                 ResourceResponse resourceResponse =
116                     (ResourceResponse)mimeResponse;
117 
118                 resourceResponse.setContentLength(contentLength);
119             }
120 
121             OutputStream outputStream = mimeResponse.getPortletOutputStream();
122 
123             outputStream.write(bytes, 0, contentLength);
124         }
125     }
126 
127     public static void write(MimeResponse mimeResponse, InputStream is)
128         throws IOException {
129 
130         write(mimeResponse, is, 0);
131     }
132 
133     public static void write(
134             MimeResponse mimeResponse, InputStream is, int contentLength)
135         throws IOException {
136 
137         if (mimeResponse.isCommitted()) {
138             return;
139         }
140 
141         if (contentLength > 0) {
142             if (mimeResponse instanceof ResourceResponse) {
143                 ResourceResponse resourceResponse =
144                     (ResourceResponse)mimeResponse;
145 
146                 resourceResponse.setContentLength(contentLength);
147             }
148         }
149 
150         StreamUtil.transfer(is, mimeResponse.getPortletOutputStream());
151     }
152 
153     protected static void setHeaders(
154         MimeResponse mimeResponse, String fileName, String contentType) {
155 
156         if (_log.isDebugEnabled()) {
157             _log.debug("Sending file of type " + contentType);
158         }
159 
160         // LEP-2201
161 
162         if (Validator.isNotNull(contentType)) {
163             mimeResponse.setContentType(contentType);
164         }
165 
166         mimeResponse.setProperty(
167             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
168         mimeResponse.setProperty(
169             HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
170 
171         if (Validator.isNotNull(fileName)) {
172             String contentDisposition =
173                 "attachment; filename=\"" + fileName + "\"";
174 
175             // If necessary for non-ASCII characters, encode based on RFC 2184.
176             // However, not all browsers support RFC 2184. See LEP-3127.
177 
178             boolean ascii = true;
179 
180             for (int i = 0; i < fileName.length(); i++) {
181                 if (!CharUtils.isAscii(fileName.charAt(i))) {
182                     ascii = false;
183 
184                     break;
185                 }
186             }
187 
188             try {
189                 if (!ascii) {
190                     URLCodec codec = new URLCodec(StringPool.UTF8);
191 
192                     String encodedFileName =
193                         StringUtil.replace(codec.encode(fileName), "+", "%20");
194 
195                     contentDisposition =
196                         "attachment; filename*=UTF-8''" + encodedFileName;
197                 }
198             }
199             catch (Exception e) {
200                 if (_log.isWarnEnabled()) {
201                     _log.warn(e);
202                 }
203             }
204 
205             String extension = GetterUtil.getString(
206                 FileUtil.getExtension(fileName)).toLowerCase();
207 
208             String[] mimeTypesContentDispositionInline = null;
209 
210             try {
211                 mimeTypesContentDispositionInline = PropsUtil.getArray(
212                     "mime.types.content.disposition.inline");
213             }
214             catch (Exception e) {
215                 mimeTypesContentDispositionInline = new String[0];
216             }
217 
218             if (ArrayUtil.contains(
219                     mimeTypesContentDispositionInline, extension)) {
220 
221                 contentDisposition = StringUtil.replace(
222                     contentDisposition, "attachment; ", "inline; ");
223             }
224 
225             mimeResponse.setProperty(
226                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
227         }
228     }
229 
230     private static Log _log = LogFactoryUtil.getLog(PortletResponseUtil.class);
231 
232 }