1   /**
2    * Copyright (c) 2000-2007 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.servlet.HttpHeaders;
26  import com.liferay.portal.kernel.util.ServerDetector;
27  import com.liferay.portal.kernel.util.StringUtil;
28  import com.liferay.portal.kernel.util.Validator;
29  
30  import java.io.BufferedOutputStream;
31  import java.io.IOException;
32  import java.io.InputStream;
33  import java.io.OutputStream;
34  
35  import javax.servlet.http.HttpServletResponse;
36  
37  import org.apache.commons.codec.net.URLCodec;
38  import org.apache.commons.lang.CharUtils;
39  import org.apache.commons.logging.Log;
40  import org.apache.commons.logging.LogFactory;
41  
42  /**
43   * <a href="ServletResponseUtil.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Brian Wing Shun Chan
46   *
47   */
48  public class ServletResponseUtil {
49  
50      public static final String DEFAULT_CONTENT_TYPE =
51          "application/octet-stream";
52  
53      public static void cleanUp(InputStream is) {
54          try {
55              if (is != null) {
56                  is.close();
57              }
58          }
59          catch (Exception e) {
60              if (_log.isWarnEnabled()) {
61                  _log.warn(e);
62              }
63          }
64      }
65  
66      public static void cleanUp(OutputStream os) {
67          try {
68              if (os != null) {
69                  os.flush();
70              }
71          }
72          catch (Exception e) {
73              if (_log.isWarnEnabled()) {
74                  _log.warn(e);
75              }
76          }
77  
78          try {
79              if (os != null) {
80                  os.close();
81              }
82          }
83          catch (Exception e) {
84              if (_log.isWarnEnabled()) {
85                  _log.warn(e);
86              }
87          }
88      }
89  
90      public static void cleanUp(OutputStream os, InputStream is) {
91          cleanUp(os);
92          cleanUp(is);
93      }
94  
95      public static void sendFile(
96              HttpServletResponse res, String fileName, byte[] byteArray)
97          throws IOException {
98  
99          sendFile(res, fileName, byteArray, null);
100     }
101 
102     public static void sendFile(
103             HttpServletResponse res, String fileName, byte[] byteArray,
104             String contentType)
105         throws IOException {
106 
107         setHeaders(res, fileName, contentType);
108 
109         write(res, byteArray);
110     }
111 
112     public static void sendFile(
113             HttpServletResponse res, String fileName, InputStream is)
114         throws IOException {
115 
116         sendFile(res, fileName, is, null);
117     }
118 
119     public static void sendFile(
120             HttpServletResponse res, String fileName, InputStream is,
121             String contentType)
122         throws IOException {
123 
124         setHeaders(res, fileName, contentType);
125 
126         write(res, is);
127     }
128 
129     public static void write(HttpServletResponse res, String s)
130         throws IOException {
131 
132         write(res, s.getBytes("UTF-8"));
133     }
134 
135     public static void write(HttpServletResponse res, byte[] byteArray)
136         throws IOException {
137 
138         write(res, byteArray, 0);
139     }
140 
141     public static void write(
142             HttpServletResponse res, byte[] byteArray, int contentLength)
143         throws IOException {
144 
145         OutputStream os = null;
146 
147         try {
148 
149             // LEP-3122
150 
151             if (!res.isCommitted() || ServerDetector.isPramati()) {
152 
153                 // LEP-536
154 
155                 if (contentLength == 0) {
156                     contentLength = byteArray.length;
157                 }
158 
159                 res.setContentLength(contentLength);
160 
161                 os = new BufferedOutputStream(res.getOutputStream());
162 
163                 os.write(byteArray, 0, contentLength);
164             }
165         }
166         finally {
167             cleanUp(os);
168         }
169     }
170 
171     public static void write(HttpServletResponse res, InputStream is)
172         throws IOException {
173 
174         OutputStream os = null;
175 
176         try {
177             if (!res.isCommitted()) {
178                 os = new BufferedOutputStream(res.getOutputStream());
179 
180                 int c = is.read();
181 
182                 while (c != -1) {
183                     os.write(c);
184 
185                     c = is.read();
186                 }
187             }
188         }
189         finally {
190             cleanUp(os, is);
191         }
192     }
193 
194     protected static void setHeaders(
195             HttpServletResponse res, String fileName, String contentType)
196         throws IOException {
197 
198         if (_log.isDebugEnabled()) {
199             _log.debug("Sending file of type " + contentType);
200         }
201 
202         // LEP-2201
203 
204         if (Validator.isNotNull(contentType)) {
205             res.setContentType(contentType);
206         }
207 
208         res.setHeader(HttpHeaders.CACHE_CONTROL, HttpHeaders.PUBLIC);
209         res.setHeader(HttpHeaders.PRAGMA, HttpHeaders.PUBLIC);
210 
211         if (Validator.isNotNull(fileName)) {
212             String contentDisposition =
213                 "attachment; filename=\"" + fileName + "\"";
214 
215             // If necessary for non-ASCII characters, encode based on RFC 2184.
216             // However, not all browsers support RFC 2184. See LEP-3127.
217 
218             boolean ascii = true;
219 
220             for (int i = 0; i < fileName.length(); i++) {
221                 if (!CharUtils.isAscii(fileName.charAt(i))) {
222                     ascii = false;
223 
224                     break;
225                 }
226             }
227 
228             try {
229                 if (!ascii) {
230                     URLCodec codec = new URLCodec("UTF-8");
231 
232                     String encodedFileName =
233                         StringUtil.replace(codec.encode(fileName), "+", "%20");
234 
235                     contentDisposition =
236                         "attachment; filename*=UTF-8''" + encodedFileName;
237                 }
238             }
239             catch (Exception e) {
240                 if (_log.isWarnEnabled()) {
241                     _log.warn(e);
242                 }
243             }
244 
245             res.setHeader(HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
246         }
247     }
248 
249     private static Log _log = LogFactory.getLog(ServletResponseUtil.class);
250 
251 }