1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions 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.FileUtil;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.StringPool;
31  import com.liferay.portal.kernel.util.StringUtil;
32  import com.liferay.portal.kernel.util.Validator;
33  
34  import java.io.BufferedOutputStream;
35  import java.io.IOException;
36  import java.io.InputStream;
37  import java.io.OutputStream;
38  
39  import javax.portlet.ResourceResponse;
40  
41  import org.apache.commons.codec.net.URLCodec;
42  import org.apache.commons.lang.CharUtils;
43  
44  /**
45   * <a href="PortletResponseUtil.java.html"><b><i>View Source</i></b></a>
46   *
47   * @author Brian Wing Shun Chan
48   *
49   */
50  public class PortletResponseUtil {
51  
52      public static void sendFile(
53              ResourceResponse resourceResponse, String fileName, byte[] bytes)
54          throws IOException {
55  
56          sendFile(resourceResponse, fileName, bytes, null);
57      }
58  
59      public static void sendFile(
60              ResourceResponse resourceResponse, String fileName, byte[] bytes,
61              String contentType)
62          throws IOException {
63  
64          setHeaders(resourceResponse, fileName, contentType);
65  
66          write(resourceResponse, bytes);
67      }
68  
69      public static void sendFile(
70              ResourceResponse resourceResponse, String fileName, InputStream is)
71          throws IOException {
72  
73          sendFile(resourceResponse, fileName, is, null);
74      }
75  
76      public static void sendFile(
77              ResourceResponse resourceResponse, String fileName, InputStream is,
78              String contentType)
79          throws IOException {
80  
81          sendFile(resourceResponse, fileName, is, 0, contentType);
82      }
83  
84      public static void sendFile(
85              ResourceResponse resourceResponse, String fileName, InputStream is,
86              int contentLength, String contentType)
87          throws IOException {
88  
89          setHeaders(resourceResponse, fileName, contentType);
90  
91          write(resourceResponse, is, contentLength);
92      }
93  
94      public static void write(ResourceResponse resourceResponse, String s)
95          throws IOException {
96  
97          write(resourceResponse, s.getBytes(StringPool.UTF8));
98      }
99  
100     public static void write(ResourceResponse resourceResponse, byte[] bytes)
101         throws IOException {
102 
103         write(resourceResponse, bytes, 0);
104     }
105 
106     public static void write(
107             ResourceResponse resourceResponse, byte[] bytes, int contentLength)
108         throws IOException {
109 
110         OutputStream os = null;
111 
112         try {
113 
114             // LEP-3122
115 
116             if (!resourceResponse.isCommitted()) {
117 
118                 // LEP-536
119 
120                 if (contentLength == 0) {
121                     contentLength = bytes.length;
122                 }
123 
124                 resourceResponse.setContentLength(contentLength);
125 
126                 os = new BufferedOutputStream(
127                     resourceResponse.getPortletOutputStream());
128 
129                 os.write(bytes, 0, contentLength);
130             }
131         }
132         finally {
133             ServletResponseUtil.cleanUp(os);
134         }
135     }
136 
137     public static void write(ResourceResponse resourceResponse, InputStream is)
138         throws IOException {
139 
140         write(resourceResponse, is, 0);
141     }
142 
143     public static void write(
144             ResourceResponse resourceResponse, InputStream is,
145             int contentLength)
146         throws IOException {
147 
148         OutputStream os = null;
149 
150         try {
151             if (!resourceResponse.isCommitted()) {
152                 if (contentLength > 0) {
153                     resourceResponse.setContentLength(contentLength);
154                 }
155 
156                 os = new BufferedOutputStream(
157                     resourceResponse.getPortletOutputStream());
158 
159                 int c = is.read();
160 
161                 while (c != -1) {
162                     os.write(c);
163 
164                     c = is.read();
165                 }
166             }
167         }
168         finally {
169             ServletResponseUtil.cleanUp(os, is);
170         }
171     }
172 
173     protected static void setHeaders(
174         ResourceResponse resourceResponse, String fileName,
175         String contentType) {
176 
177         if (_log.isDebugEnabled()) {
178             _log.debug("Sending file of type " + contentType);
179         }
180 
181         // LEP-2201
182 
183         if (Validator.isNotNull(contentType)) {
184             resourceResponse.setContentType(contentType);
185         }
186 
187         resourceResponse.setProperty(
188             HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
189         resourceResponse.setProperty(
190             HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
191 
192         if (Validator.isNotNull(fileName)) {
193             String contentDisposition =
194                 "attachment; filename=\"" + fileName + "\"";
195 
196             // If necessary for non-ASCII characters, encode based on RFC 2184.
197             // However, not all browsers support RFC 2184. See LEP-3127.
198 
199             boolean ascii = true;
200 
201             for (int i = 0; i < fileName.length(); i++) {
202                 if (!CharUtils.isAscii(fileName.charAt(i))) {
203                     ascii = false;
204 
205                     break;
206                 }
207             }
208 
209             try {
210                 if (!ascii) {
211                     URLCodec codec = new URLCodec(StringPool.UTF8);
212 
213                     String encodedFileName =
214                         StringUtil.replace(codec.encode(fileName), "+", "%20");
215 
216                     contentDisposition =
217                         "attachment; filename*=UTF-8''" + encodedFileName;
218                 }
219             }
220             catch (Exception e) {
221                 if (_log.isWarnEnabled()) {
222                     _log.warn(e);
223                 }
224             }
225 
226             String extension = GetterUtil.getString(
227                 FileUtil.getExtension(fileName));
228 
229             if (extension.equals("pdf")) {
230                 contentDisposition = StringUtil.replace(
231                     contentDisposition, "attachment; ", "inline; ");
232             }
233 
234             resourceResponse.setProperty(
235                 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
236         }
237     }
238 
239     private static Log _log = LogFactoryUtil.getLog(PortletResponseUtil.class);
240 
241 }