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