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.io.unsync.UnsyncByteArrayOutputStream;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  import com.liferay.portal.kernel.servlet.BrowserSnifferUtil;
21  import com.liferay.portal.kernel.servlet.HttpHeaders;
22  import com.liferay.portal.kernel.servlet.StringServletResponse;
23  import com.liferay.portal.kernel.util.ArrayUtil;
24  import com.liferay.portal.kernel.util.FileUtil;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.HttpUtil;
27  import com.liferay.portal.kernel.util.PropsUtil;
28  import com.liferay.portal.kernel.util.StreamUtil;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Validator;
32  
33  import java.io.IOException;
34  import java.io.InputStream;
35  
36  import java.net.SocketException;
37  
38  import javax.servlet.ServletOutputStream;
39  import javax.servlet.http.HttpServletRequest;
40  import javax.servlet.http.HttpServletResponse;
41  
42  /**
43   * <a href="ServletResponseUtil.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Brian Wing Shun Chan
46   * @author Shuyang Zhou
47   */
48  public class ServletResponseUtil {
49  
50      public static void sendFile(
51              HttpServletRequest request, HttpServletResponse response,
52              String fileName, byte[] bytes)
53          throws IOException {
54  
55          sendFile(request, response, fileName, bytes, null);
56      }
57  
58      public static void sendFile(
59              HttpServletRequest request, HttpServletResponse response,
60              String fileName, byte[] bytes, String contentType)
61          throws IOException {
62  
63          setHeaders(request, response, fileName, contentType);
64  
65          write(response, bytes);
66      }
67  
68      public static void sendFile(
69              HttpServletRequest request, HttpServletResponse response,
70              String fileName, InputStream is)
71          throws IOException {
72  
73          sendFile(request, response, fileName, is, null);
74      }
75  
76      public static void sendFile(
77              HttpServletRequest request, HttpServletResponse response,
78              String fileName, InputStream is, int contentLength,
79              String contentType)
80          throws IOException {
81  
82          setHeaders(request, response, fileName, contentType);
83  
84          write(response, is, contentLength);
85      }
86  
87      public static void sendFile(
88              HttpServletRequest request, HttpServletResponse response,
89              String fileName, InputStream is, String contentType)
90          throws IOException {
91  
92          sendFile(request, response, fileName, is, 0, contentType);
93      }
94  
95      /**
96       * @deprecated
97       */
98      public static void sendFile(
99              HttpServletResponse response, String fileName, byte[] bytes)
100         throws IOException {
101 
102         sendFile(null, response, fileName, bytes);
103     }
104 
105     /**
106      * @deprecated
107      */
108     public static void sendFile(
109             HttpServletResponse response, String fileName, byte[] bytes,
110             String contentType)
111         throws IOException {
112 
113         sendFile(null, response, fileName, bytes, contentType);
114     }
115 
116     /**
117      * @deprecated
118      */
119     public static void sendFile(
120             HttpServletResponse response, String fileName, InputStream is)
121         throws IOException {
122 
123         sendFile(null, response, fileName, is);
124     }
125 
126     /**
127      * @deprecated
128      */
129     public static void sendFile(
130             HttpServletResponse response, String fileName, InputStream is,
131             int contentLength, String contentType)
132         throws IOException {
133 
134         sendFile(null, response, fileName, is, contentLength, contentType);
135     }
136 
137     /**
138      * @deprecated
139      */
140     public static void sendFile(
141             HttpServletResponse response, String fileName, InputStream is,
142             String contentType)
143         throws IOException {
144 
145         sendFile(null, response, fileName, is, contentType);
146     }
147 
148     public static void write(HttpServletResponse response, byte[] bytes)
149         throws IOException {
150 
151         write(response, bytes, 0);
152     }
153 
154     public static void write(
155             HttpServletResponse response, byte[] bytes, int contentLength)
156         throws IOException {
157 
158         try {
159 
160             // LEP-3122
161 
162             if (!response.isCommitted()) {
163 
164                 // LEP-536
165 
166                 if (contentLength == 0) {
167                     contentLength = bytes.length;
168                 }
169 
170                 response.setContentLength(contentLength);
171 
172                 ServletOutputStream servletOutputStream =
173                     response.getOutputStream();
174 
175                 servletOutputStream.write(bytes, 0, contentLength);
176             }
177         }
178         catch (IOException ioe) {
179             if (ioe instanceof SocketException ||
180                 ioe.getClass().getName().equals(_CLIENT_ABORT_EXCEPTION)) {
181 
182                 if (_log.isWarnEnabled()) {
183                     _log.warn(ioe);
184                 }
185             }
186             else {
187                 throw ioe;
188             }
189         }
190     }
191 
192     public static void write(HttpServletResponse response, InputStream is)
193         throws IOException {
194 
195         write(response, is, 0);
196     }
197 
198     public static void write(
199             HttpServletResponse response, InputStream is, int contentLength)
200         throws IOException {
201 
202         if (response.isCommitted()) {
203             return;
204         }
205 
206         if (contentLength > 0) {
207             response.setContentLength(contentLength);
208         }
209 
210         StreamUtil.transfer(is, response.getOutputStream());
211     }
212 
213     public static void write(HttpServletResponse response, String s)
214         throws IOException {
215 
216         write(response, s.getBytes(StringPool.UTF8));
217     }
218 
219     public static void write(
220             HttpServletResponse response, StringServletResponse stringResponse)
221         throws IOException {
222 
223         if (stringResponse.isCalledGetOutputStream()) {
224             UnsyncByteArrayOutputStream unsyncByteArrayInputStream =
225                 stringResponse.getUnsyncByteArrayOutputStream();
226 
227             write(
228                 response, unsyncByteArrayInputStream.unsafeGetByteArray(),
229                 unsyncByteArrayInputStream.size());
230         }
231         else {
232             write(response, stringResponse.getString());
233         }
234     }
235 
236     protected static void setHeaders(
237         HttpServletRequest request, HttpServletResponse response,
238         String fileName, String contentType) {
239 
240         if (_log.isDebugEnabled()) {
241             _log.debug("Sending file of type " + contentType);
242         }
243 
244         // LEP-2201
245 
246         if (Validator.isNotNull(contentType)) {
247             response.setContentType(contentType);
248         }
249 
250         response.setHeader(
251             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
252         response.setHeader(HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
253 
254         if (Validator.isNotNull(fileName)) {
255             String contentDisposition =
256                 "attachment; filename=\"" + fileName + "\"";
257 
258             // If necessary for non-ASCII characters, encode based on RFC 2184.
259             // However, not all browsers support RFC 2184. See LEP-3127.
260 
261             boolean ascii = true;
262 
263             for (int i = 0; i < fileName.length(); i++) {
264                 if (!Validator.isAscii(fileName.charAt(i))) {
265                     ascii = false;
266 
267                     break;
268                 }
269             }
270 
271             try {
272                 if (!ascii) {
273                     String encodedFileName = HttpUtil.encodeURL(fileName, true);
274 
275                     if (BrowserSnifferUtil.isIe(request)) {
276                         contentDisposition =
277                             "attachment; filename=\"" + encodedFileName + "\"";
278                     }
279                     else {
280                         contentDisposition =
281                             "attachment; filename*=UTF-8''" + encodedFileName;
282                     }
283                 }
284             }
285             catch (Exception e) {
286                 if (_log.isWarnEnabled()) {
287                     _log.warn(e);
288                 }
289             }
290 
291             String extension = GetterUtil.getString(
292                 FileUtil.getExtension(fileName)).toLowerCase();
293 
294             String[] mimeTypesContentDispositionInline = null;
295 
296             try {
297                 mimeTypesContentDispositionInline = PropsUtil.getArray(
298                     "mime.types.content.disposition.inline");
299             }
300             catch (Exception e) {
301                 mimeTypesContentDispositionInline = new String[0];
302             }
303 
304             if (ArrayUtil.contains(
305                     mimeTypesContentDispositionInline, extension)) {
306 
307                 contentDisposition = StringUtil.replace(
308                     contentDisposition, "attachment; ", "inline; ");
309             }
310 
311             response.setHeader(
312                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
313         }
314     }
315 
316     private static Log _log = LogFactoryUtil.getLog(ServletResponseUtil.class);
317 
318     private static final String _CLIENT_ABORT_EXCEPTION =
319         "org.apache.catalina.connector.ClientAbortException";
320 
321 }