1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
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.File;
34  import java.io.FileInputStream;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.OutputStream;
38  
39  import java.net.SocketException;
40  
41  import java.nio.channels.Channels;
42  import java.nio.channels.FileChannel;
43  
44  import javax.servlet.ServletOutputStream;
45  import javax.servlet.http.HttpServletRequest;
46  import javax.servlet.http.HttpServletResponse;
47  
48  /**
49   * <a href="ServletResponseUtil.java.html"><b><i>View Source</i></b></a>
50   *
51   * @author Brian Wing Shun Chan
52   * @author Shuyang Zhou
53   */
54  public class ServletResponseUtil {
55  
56      /**
57       * @deprecated {@link StreamUtil#cleanUp(InputStream)}
58       */
59      public static void cleanUp(InputStream inputStream) {
60          StreamUtil.cleanUp(inputStream);
61      }
62  
63      /**
64       * @deprecated {@link StreamUtil#cleanUp(OutputStream)}
65       */
66      public static void cleanUp(OutputStream outputStream) {
67          StreamUtil.cleanUp(outputStream);
68      }
69  
70      /**
71       * @deprecated {@link StreamUtil#cleanUp(InputStream, OutputStream)}
72       */
73      public static void cleanUp(
74          OutputStream outputStream, InputStream inputStream) {
75  
76          StreamUtil.cleanUp(inputStream, outputStream);
77      }
78  
79      public static void sendFile(
80              HttpServletRequest request, HttpServletResponse response,
81              String fileName, byte[] bytes)
82          throws IOException {
83  
84          sendFile(request, response, fileName, bytes, null);
85      }
86  
87      public static void sendFile(
88              HttpServletRequest request, HttpServletResponse response,
89              String fileName, byte[] bytes, String contentType)
90          throws IOException {
91  
92          setHeaders(request, response, fileName, contentType);
93  
94          write(response, bytes);
95      }
96  
97      public static void sendFile(
98              HttpServletRequest request, HttpServletResponse response,
99              String fileName, InputStream is)
100         throws IOException {
101 
102         sendFile(request, response, fileName, is, null);
103     }
104 
105     public static void sendFile(
106             HttpServletRequest request, HttpServletResponse response,
107             String fileName, InputStream is, int contentLength,
108             String contentType)
109         throws IOException {
110 
111         setHeaders(request, response, fileName, contentType);
112 
113         write(response, is, contentLength);
114     }
115 
116     public static void sendFile(
117             HttpServletRequest request, HttpServletResponse response,
118             String fileName, InputStream is, String contentType)
119         throws IOException {
120 
121         sendFile(request, response, fileName, is, 0, contentType);
122     }
123 
124     /**
125      * @deprecated
126      */
127     public static void sendFile(
128             HttpServletResponse response, String fileName, byte[] bytes)
129         throws IOException {
130 
131         sendFile(null, response, fileName, bytes);
132     }
133 
134     /**
135      * @deprecated
136      */
137     public static void sendFile(
138             HttpServletResponse response, String fileName, byte[] bytes,
139             String contentType)
140         throws IOException {
141 
142         sendFile(null, response, fileName, bytes, contentType);
143     }
144 
145     /**
146      * @deprecated
147      */
148     public static void sendFile(
149             HttpServletResponse response, String fileName, InputStream is)
150         throws IOException {
151 
152         sendFile(null, response, fileName, is);
153     }
154 
155     /**
156      * @deprecated
157      */
158     public static void sendFile(
159             HttpServletResponse response, String fileName, InputStream is,
160             int contentLength, String contentType)
161         throws IOException {
162 
163         sendFile(null, response, fileName, is, contentLength, contentType);
164     }
165 
166     /**
167      * @deprecated
168      */
169     public static void sendFile(
170             HttpServletResponse response, String fileName, InputStream is,
171             String contentType)
172         throws IOException {
173 
174         sendFile(null, response, fileName, is, contentType);
175     }
176 
177     public static void write(HttpServletResponse response, byte[] bytes)
178         throws IOException {
179 
180         write(response, bytes, 0);
181     }
182 
183     public static void write(
184             HttpServletResponse response, byte[] bytes, int contentLength)
185         throws IOException {
186 
187         try {
188 
189             // LEP-3122
190 
191             if (!response.isCommitted()) {
192 
193                 // LEP-536
194 
195                 if (contentLength == 0) {
196                     contentLength = bytes.length;
197                 }
198 
199                 response.setContentLength(contentLength);
200 
201                 ServletOutputStream servletOutputStream =
202                     response.getOutputStream();
203 
204                 servletOutputStream.write(bytes, 0, contentLength);
205             }
206         }
207         catch (IOException ioe) {
208             if (ioe instanceof SocketException ||
209                 ioe.getClass().getName().equals(_CLIENT_ABORT_EXCEPTION)) {
210 
211                 if (_log.isWarnEnabled()) {
212                     _log.warn(ioe);
213                 }
214             }
215             else {
216                 throw ioe;
217             }
218         }
219     }
220 
221     public static void write(HttpServletResponse response, byte[][] bytesArray)
222         throws IOException {
223 
224         try {
225 
226             // LEP-3122
227 
228             if (!response.isCommitted()) {
229                 int contentLength = 0;
230 
231                 for (byte[] bytes : bytesArray) {
232                     contentLength += bytes.length;
233                 }
234 
235                 response.setContentLength(contentLength);
236 
237                 ServletOutputStream servletOutputStream =
238                     response.getOutputStream();
239 
240                 for (byte[] bytes : bytesArray) {
241                     servletOutputStream.write(bytes);
242                 }
243             }
244         }
245         catch (IOException ioe) {
246             if (ioe instanceof SocketException ||
247                 ioe.getClass().getName().equals(_CLIENT_ABORT_EXCEPTION)) {
248 
249                 if (_log.isWarnEnabled()) {
250                     _log.warn(ioe);
251                 }
252             }
253             else {
254                 throw ioe;
255             }
256         }
257     }
258 
259     public static void write(HttpServletResponse response, File file)
260         throws IOException {
261 
262         FileInputStream fileInputStream = new FileInputStream(file);
263 
264         FileChannel fileChannel = fileInputStream.getChannel();
265 
266         try {
267             int contentLength = (int)fileChannel.size();
268 
269             response.setContentLength(contentLength);
270 
271             fileChannel.transferTo(
272                 0, contentLength,
273                 Channels.newChannel(response.getOutputStream()));
274         }
275         finally {
276             fileChannel.close();
277         }
278     }
279 
280     public static void write(HttpServletResponse response, InputStream is)
281         throws IOException {
282 
283         write(response, is, 0);
284     }
285 
286     public static void write(
287             HttpServletResponse response, InputStream is, int contentLength)
288         throws IOException {
289 
290         if (response.isCommitted()) {
291             return;
292         }
293 
294         if (contentLength > 0) {
295             response.setContentLength(contentLength);
296         }
297 
298         StreamUtil.transfer(is, response.getOutputStream());
299     }
300 
301     public static void write(HttpServletResponse response, String s)
302         throws IOException {
303 
304         write(response, s.getBytes(StringPool.UTF8));
305     }
306 
307     public static void write(
308             HttpServletResponse response, StringServletResponse stringResponse)
309         throws IOException {
310 
311         if (stringResponse.isCalledGetOutputStream()) {
312             UnsyncByteArrayOutputStream unsyncByteArrayInputStream =
313                 stringResponse.getUnsyncByteArrayOutputStream();
314 
315             write(
316                 response, unsyncByteArrayInputStream.unsafeGetByteArray(),
317                 unsyncByteArrayInputStream.size());
318         }
319         else {
320             write(response, stringResponse.getString());
321         }
322     }
323 
324     protected static void setHeaders(
325         HttpServletRequest request, HttpServletResponse response,
326         String fileName, String contentType) {
327 
328         if (_log.isDebugEnabled()) {
329             _log.debug("Sending file of type " + contentType);
330         }
331 
332         // LEP-2201
333 
334         if (Validator.isNotNull(contentType)) {
335             response.setContentType(contentType);
336         }
337 
338         response.setHeader(
339             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
340         response.setHeader(HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
341 
342         if (Validator.isNotNull(fileName)) {
343             String contentDisposition =
344                 "attachment; filename=\"" + fileName + "\"";
345 
346             // If necessary for non-ASCII characters, encode based on RFC 2184.
347             // However, not all browsers support RFC 2184. See LEP-3127.
348 
349             boolean ascii = true;
350 
351             for (int i = 0; i < fileName.length(); i++) {
352                 if (!Validator.isAscii(fileName.charAt(i))) {
353                     ascii = false;
354 
355                     break;
356                 }
357             }
358 
359             try {
360                 if (!ascii) {
361                     String encodedFileName = HttpUtil.encodeURL(fileName, true);
362 
363                     if (BrowserSnifferUtil.isIe(request)) {
364                         contentDisposition =
365                             "attachment; filename=\"" + encodedFileName + "\"";
366                     }
367                     else {
368                         contentDisposition =
369                             "attachment; filename*=UTF-8''" + encodedFileName;
370                     }
371                 }
372             }
373             catch (Exception e) {
374                 if (_log.isWarnEnabled()) {
375                     _log.warn(e);
376                 }
377             }
378 
379             String extension = GetterUtil.getString(
380                 FileUtil.getExtension(fileName)).toLowerCase();
381 
382             String[] mimeTypesContentDispositionInline = null;
383 
384             try {
385                 mimeTypesContentDispositionInline = PropsUtil.getArray(
386                     "mime.types.content.disposition.inline");
387             }
388             catch (Exception e) {
389                 mimeTypesContentDispositionInline = new String[0];
390             }
391 
392             if (ArrayUtil.contains(
393                     mimeTypesContentDispositionInline, extension)) {
394 
395                 contentDisposition = StringUtil.replace(
396                     contentDisposition, "attachment; ", "inline; ");
397             }
398 
399             response.setHeader(
400                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
401         }
402     }
403 
404     private static final String _CLIENT_ABORT_EXCEPTION =
405         "org.apache.catalina.connector.ClientAbortException";
406 
407     private static Log _log = LogFactoryUtil.getLog(ServletResponseUtil.class);
408 
409 }