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