1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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.ArrayUtil;
29  import com.liferay.portal.kernel.util.FileUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.PropsUtil;
32  import com.liferay.portal.kernel.util.StreamUtil;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.StringUtil;
35  import com.liferay.portal.kernel.util.Validator;
36  
37  import java.io.IOException;
38  import java.io.InputStream;
39  import java.io.OutputStream;
40  
41  import java.net.SocketException;
42  
43  import javax.servlet.ServletOutputStream;
44  import javax.servlet.http.HttpServletResponse;
45  
46  import org.apache.commons.codec.net.URLCodec;
47  import org.apache.commons.lang.CharUtils;
48  
49  /**
50   * <a href="ServletResponseUtil.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Brian Wing Shun Chan
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              HttpServletResponse response, String fileName, byte[] bytes)
81          throws IOException {
82  
83          sendFile(response, fileName, bytes, null);
84      }
85  
86      public static void sendFile(
87              HttpServletResponse response, String fileName, byte[] bytes,
88              String contentType)
89          throws IOException {
90  
91          setHeaders(response, fileName, contentType);
92  
93          write(response, bytes);
94      }
95  
96      public static void sendFile(
97              HttpServletResponse response, String fileName, InputStream is)
98          throws IOException {
99  
100         sendFile(response, fileName, is, null);
101     }
102 
103     public static void sendFile(
104             HttpServletResponse response, String fileName, InputStream is,
105             String contentType)
106         throws IOException {
107 
108         sendFile(response, fileName, is, 0, contentType);
109     }
110 
111     public static void sendFile(
112             HttpServletResponse response, String fileName, InputStream is,
113             int contentLength, String contentType)
114         throws IOException {
115 
116         setHeaders(response, fileName, contentType);
117 
118         write(response, is, contentLength);
119     }
120 
121     public static void write(HttpServletResponse response, String s)
122         throws IOException {
123 
124         write(response, s.getBytes(StringPool.UTF8));
125     }
126 
127     public static void write(HttpServletResponse response, byte[] bytes)
128         throws IOException {
129 
130         write(response, bytes, 0);
131     }
132 
133     public static void write(
134             HttpServletResponse response, byte[] bytes, int contentLength)
135         throws IOException {
136 
137         try {
138 
139             // LEP-3122
140 
141             if (!response.isCommitted()) {
142 
143                 // LEP-536
144 
145                 if (contentLength == 0) {
146                     contentLength = bytes.length;
147                 }
148 
149                 response.setContentLength(contentLength);
150 
151                 ServletOutputStream servletOutputStream =
152                     response.getOutputStream();
153 
154                 servletOutputStream.write(bytes, 0, contentLength);
155             }
156         }
157         catch (IOException ioe) {
158             if (ioe instanceof SocketException ||
159                 ioe.getClass().getName().equals(_CLIENT_ABORT_EXCEPTION)) {
160 
161                 if (_log.isWarnEnabled()) {
162                     _log.warn(ioe);
163                 }
164             }
165             else {
166                 throw ioe;
167             }
168         }
169     }
170 
171     public static void write(HttpServletResponse response, InputStream is)
172         throws IOException {
173 
174         write(response, is, 0);
175     }
176 
177     public static void write(
178             HttpServletResponse response, InputStream is, int contentLength)
179         throws IOException {
180 
181         if (response.isCommitted()) {
182             return;
183         }
184 
185         if (contentLength > 0) {
186             response.setContentLength(contentLength);
187         }
188 
189         StreamUtil.transfer(is, response.getOutputStream());
190     }
191 
192     protected static void setHeaders(
193         HttpServletResponse response, String fileName, String contentType) {
194 
195         if (_log.isDebugEnabled()) {
196             _log.debug("Sending file of type " + contentType);
197         }
198 
199         // LEP-2201
200 
201         if (Validator.isNotNull(contentType)) {
202             response.setContentType(contentType);
203         }
204 
205         response.setHeader(
206             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
207         response.setHeader(HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
208 
209         if (Validator.isNotNull(fileName)) {
210             String contentDisposition =
211                 "attachment; filename=\"" + fileName + "\"";
212 
213             // If necessary for non-ASCII characters, encode based on RFC 2184.
214             // However, not all browsers support RFC 2184. See LEP-3127.
215 
216             boolean ascii = true;
217 
218             for (int i = 0; i < fileName.length(); i++) {
219                 if (!CharUtils.isAscii(fileName.charAt(i))) {
220                     ascii = false;
221 
222                     break;
223                 }
224             }
225 
226             try {
227                 if (!ascii) {
228                     URLCodec codec = new URLCodec(StringPool.UTF8);
229 
230                     String encodedFileName =
231                         StringUtil.replace(codec.encode(fileName), "+", "%20");
232 
233                     contentDisposition =
234                         "attachment; filename*=UTF-8''" + encodedFileName;
235                 }
236             }
237             catch (Exception e) {
238                 if (_log.isWarnEnabled()) {
239                     _log.warn(e);
240                 }
241             }
242 
243             String extension = GetterUtil.getString(
244                 FileUtil.getExtension(fileName)).toLowerCase();
245 
246             String[] mimeTypesContentDispositionInline = null;
247 
248             try {
249                 mimeTypesContentDispositionInline = PropsUtil.getArray(
250                     "mime.types.content.disposition.inline");
251             }
252             catch (Exception e) {
253                 mimeTypesContentDispositionInline = new String[0];
254             }
255 
256             if (ArrayUtil.contains(
257                     mimeTypesContentDispositionInline, extension)) {
258 
259                 contentDisposition = StringUtil.replace(
260                     contentDisposition, "attachment; ", "inline; ");
261             }
262 
263             response.setHeader(
264                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
265         }
266     }
267 
268     private static final String _CLIENT_ABORT_EXCEPTION =
269         "org.apache.catalina.connector.ClientAbortException";
270 
271     private static Log _log = LogFactoryUtil.getLog(ServletResponseUtil.class);
272 
273 }