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