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