1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.util.servlet;
24  
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.servlet.HttpHeaders;
28  import com.liferay.portal.kernel.util.FileUtil;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.ServerDetector;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Validator;
34  
35  import java.io.BufferedOutputStream;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.io.OutputStream;
39  
40  import java.net.SocketException;
41  
42  import javax.servlet.http.HttpServletResponse;
43  
44  import org.apache.commons.codec.net.URLCodec;
45  import org.apache.commons.lang.CharUtils;
46  
47  /**
48   * <a href="ServletResponseUtil.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Brian Wing Shun Chan
51   *
52   */
53  public class ServletResponseUtil {
54  
55      public static void cleanUp(InputStream is) {
56          try {
57              if (is != null) {
58                  is.close();
59              }
60          }
61          catch (Exception e) {
62              if (_log.isWarnEnabled()) {
63                  _log.warn(e);
64              }
65          }
66      }
67  
68      public static void cleanUp(OutputStream os) {
69          try {
70              if (os != null) {
71                  os.flush();
72              }
73          }
74          catch (Exception e) {
75              if (_log.isWarnEnabled()) {
76                  _log.warn(e);
77              }
78          }
79  
80          try {
81              if (os != null) {
82                  os.close();
83              }
84          }
85          catch (Exception e) {
86              if (_log.isWarnEnabled()) {
87                  _log.warn(e);
88              }
89          }
90      }
91  
92      public static void cleanUp(OutputStream os, InputStream is) {
93          cleanUp(os);
94          cleanUp(is);
95      }
96  
97      public static void sendFile(
98              HttpServletResponse response, String fileName, byte[] bytes)
99          throws IOException {
100 
101         sendFile(response, fileName, bytes, null);
102     }
103 
104     public static void sendFile(
105             HttpServletResponse response, String fileName, byte[] bytes,
106             String contentType)
107         throws IOException {
108 
109         setHeaders(response, fileName, contentType);
110 
111         write(response, bytes);
112     }
113 
114     public static void sendFile(
115             HttpServletResponse response, String fileName, InputStream is)
116         throws IOException {
117 
118         sendFile(response, fileName, is, null);
119     }
120 
121     public static void sendFile(
122             HttpServletResponse response, String fileName, InputStream is,
123             String contentType)
124         throws IOException {
125 
126         sendFile(response, fileName, is, 0, contentType);
127     }
128 
129     public static void sendFile(
130             HttpServletResponse response, String fileName, InputStream is,
131             int contentLength, String contentType)
132         throws IOException {
133 
134         setHeaders(response, fileName, contentType);
135 
136         write(response, is, contentLength);
137     }
138 
139     public static void write(HttpServletResponse response, String s)
140         throws IOException {
141 
142         write(response, s.getBytes(StringPool.UTF8));
143     }
144 
145     public static void write(HttpServletResponse response, byte[] bytes)
146         throws IOException {
147 
148         write(response, bytes, 0);
149     }
150 
151     public static void write(
152             HttpServletResponse response, byte[] bytes, int contentLength)
153         throws IOException {
154 
155         OutputStream os = null;
156 
157         try {
158 
159             // LEP-3122
160 
161             if (!response.isCommitted() || ServerDetector.isPramati()) {
162 
163                 // LEP-536
164 
165                 if (contentLength == 0) {
166                     contentLength = bytes.length;
167                 }
168 
169                 response.setContentLength(contentLength);
170 
171                 os = new BufferedOutputStream(response.getOutputStream());
172 
173                 os.write(bytes, 0, contentLength);
174             }
175         }
176         catch (IOException ioe) {
177             if (ioe instanceof SocketException ||
178                 ioe.getClass().getName().equals(_CLIENT_ABORT_EXCEPTION)) {
179 
180                 if (_log.isWarnEnabled()) {
181                     _log.warn(ioe);
182                 }
183             }
184             else {
185                 throw ioe;
186             }
187         }
188         finally {
189             cleanUp(os);
190         }
191     }
192 
193     public static void write(HttpServletResponse response, InputStream is)
194         throws IOException {
195 
196         write(response, is, 0);
197     }
198 
199     public static void write(
200             HttpServletResponse response, InputStream is, int contentLength)
201         throws IOException {
202 
203         OutputStream os = null;
204 
205         try {
206             if (!response.isCommitted()) {
207                 if (contentLength > 0) {
208                     response.setContentLength(contentLength);
209                 }
210 
211                 os = new BufferedOutputStream(response.getOutputStream());
212 
213                 int c = is.read();
214 
215                 while (c != -1) {
216                     os.write(c);
217 
218                     c = is.read();
219                 }
220             }
221         }
222         finally {
223             cleanUp(os, is);
224         }
225     }
226 
227     protected static void setHeaders(
228         HttpServletResponse response, String fileName, String contentType) {
229 
230         if (_log.isDebugEnabled()) {
231             _log.debug("Sending file of type " + contentType);
232         }
233 
234         // LEP-2201
235 
236         if (Validator.isNotNull(contentType)) {
237             response.setContentType(contentType);
238         }
239 
240         response.setHeader(
241             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
242         response.setHeader(HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
243 
244         if (Validator.isNotNull(fileName)) {
245             String contentDisposition =
246                 "attachment; filename=\"" + fileName + "\"";
247 
248             // If necessary for non-ASCII characters, encode based on RFC 2184.
249             // However, not all browsers support RFC 2184. See LEP-3127.
250 
251             boolean ascii = true;
252 
253             for (int i = 0; i < fileName.length(); i++) {
254                 if (!CharUtils.isAscii(fileName.charAt(i))) {
255                     ascii = false;
256 
257                     break;
258                 }
259             }
260 
261             try {
262                 if (!ascii) {
263                     URLCodec codec = new URLCodec(StringPool.UTF8);
264 
265                     String encodedFileName =
266                         StringUtil.replace(codec.encode(fileName), "+", "%20");
267 
268                     contentDisposition =
269                         "attachment; filename*=UTF-8''" + encodedFileName;
270                 }
271             }
272             catch (Exception e) {
273                 if (_log.isWarnEnabled()) {
274                     _log.warn(e);
275                 }
276             }
277 
278             String extension = GetterUtil.getString(
279                 FileUtil.getExtension(fileName));
280 
281             if (extension.equals("pdf")) {
282                 contentDisposition = StringUtil.replace(
283                     contentDisposition, "attachment; ", "inline; ");
284             }
285 
286             response.setHeader(
287                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
288         }
289     }
290 
291     private static final String _CLIENT_ABORT_EXCEPTION =
292         "org.apache.catalina.connector.ClientAbortException";
293 
294     private static Log _log = LogFactoryUtil.getLog(ServletResponseUtil.class);
295 
296 }