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