001
014
015 package com.liferay.portal.kernel.servlet;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
018 import com.liferay.portal.kernel.log.Log;
019 import com.liferay.portal.kernel.log.LogFactoryUtil;
020 import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
021 import com.liferay.portal.kernel.util.ArrayUtil;
022 import com.liferay.portal.kernel.util.FileUtil;
023 import com.liferay.portal.kernel.util.GetterUtil;
024 import com.liferay.portal.kernel.util.HttpUtil;
025 import com.liferay.portal.kernel.util.PropsUtil;
026 import com.liferay.portal.kernel.util.ServerDetector;
027 import com.liferay.portal.kernel.util.StreamUtil;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.util.StringUtil;
030 import com.liferay.portal.kernel.util.Validator;
031
032 import java.io.File;
033 import java.io.FileInputStream;
034 import java.io.IOException;
035 import java.io.InputStream;
036
037 import java.net.SocketException;
038
039 import java.nio.ByteBuffer;
040 import java.nio.channels.Channels;
041 import java.nio.channels.FileChannel;
042
043 import javax.servlet.ServletOutputStream;
044 import javax.servlet.http.HttpServletRequest;
045 import javax.servlet.http.HttpServletResponse;
046
047
051 public class ServletResponseUtil {
052
053 public static void sendFile(
054 HttpServletRequest request, HttpServletResponse response,
055 String fileName, byte[] bytes)
056 throws IOException {
057
058 sendFile(request, response, fileName, bytes, null);
059 }
060
061 public static void sendFile(
062 HttpServletRequest request, HttpServletResponse response,
063 String fileName, byte[] bytes, String contentType)
064 throws IOException {
065
066 setHeaders(request, response, fileName, contentType);
067
068 write(response, bytes);
069 }
070
071 public static void sendFile(
072 HttpServletRequest request, HttpServletResponse response,
073 String fileName, InputStream is)
074 throws IOException {
075
076 sendFile(request, response, fileName, is, null);
077 }
078
079 public static void sendFile(
080 HttpServletRequest request, HttpServletResponse response,
081 String fileName, InputStream is, long contentLength,
082 String contentType)
083 throws IOException {
084
085 setHeaders(request, response, fileName, contentType);
086
087 write(response, is, contentLength);
088 }
089
090 public static void sendFile(
091 HttpServletRequest request, HttpServletResponse response,
092 String fileName, InputStream is, String contentType)
093 throws IOException {
094
095 sendFile(request, response, fileName, is, 0, contentType);
096 }
097
098
101 public static void sendFile(
102 HttpServletResponse response, String fileName, byte[] bytes)
103 throws IOException {
104
105 sendFile(null, response, fileName, bytes);
106 }
107
108
111 public static void sendFile(
112 HttpServletResponse response, String fileName, byte[] bytes,
113 String contentType)
114 throws IOException {
115
116 sendFile(null, response, fileName, bytes, contentType);
117 }
118
119
122 public static void sendFile(
123 HttpServletResponse response, String fileName, InputStream is)
124 throws IOException {
125
126 sendFile(null, response, fileName, is);
127 }
128
129
132 public static void sendFile(
133 HttpServletResponse response, String fileName, InputStream is,
134 int contentLength, String contentType)
135 throws IOException {
136
137 sendFile(null, response, fileName, is, contentLength, contentType);
138 }
139
140
143 public static void sendFile(
144 HttpServletResponse response, String fileName, InputStream is,
145 String contentType)
146 throws IOException {
147
148 sendFile(null, response, fileName, is, contentType);
149 }
150
151 public static void write(HttpServletResponse response, byte[] bytes)
152 throws IOException {
153
154 write(response, bytes, 0, 0);
155 }
156
157 public static void write(
158 HttpServletResponse response, byte[] bytes, int offset,
159 int contentLength)
160 throws IOException {
161
162 try {
163
164
165
166 if (!response.isCommitted()) {
167
168
169
170 if (contentLength == 0) {
171 contentLength = bytes.length;
172 }
173
174 response.setContentLength(contentLength);
175
176 try {
177 response.flushBuffer();
178 }
179 catch (NullPointerException npe) {
180
181
182
183 if (!ServerDetector.isGlassfish()) {
184 throw npe;
185 }
186
187 if (_log.isDebugEnabled()) {
188 _log.debug(
189 "Ignoring NullPointerException because of " +
190 "GLASSFISH-17150");
191 }
192 }
193
194 if (response instanceof ByteBufferServletResponse) {
195 ByteBufferServletResponse byteBufferResponse =
196 (ByteBufferServletResponse)response;
197
198 byteBufferResponse.setByteBuffer(
199 ByteBuffer.wrap(bytes, offset, contentLength));
200 }
201 else {
202 ServletOutputStream servletOutputStream =
203 response.getOutputStream();
204
205 if ((contentLength == 0) && ServerDetector.isJetty()) {
206 }
207 else {
208 servletOutputStream.write(bytes, offset, contentLength);
209 }
210 }
211 }
212 }
213 catch (IOException ioe) {
214 if ((ioe instanceof SocketException) ||
215 isClientAbortException(ioe)) {
216
217 if (_log.isWarnEnabled()) {
218 _log.warn(ioe);
219 }
220 }
221 else {
222 throw ioe;
223 }
224 }
225 }
226
227 public static void write(HttpServletResponse response, byte[][] bytesArray)
228 throws IOException {
229
230 try {
231
232
233
234 if (!response.isCommitted()) {
235 int contentLength = 0;
236
237 for (byte[] bytes : bytesArray) {
238 contentLength += bytes.length;
239 }
240
241 response.setContentLength(contentLength);
242
243 response.flushBuffer();
244
245 ServletOutputStream servletOutputStream =
246 response.getOutputStream();
247
248 for (byte[] bytes : bytesArray) {
249 servletOutputStream.write(bytes);
250 }
251 }
252 }
253 catch (IOException ioe) {
254 if ((ioe instanceof SocketException) ||
255 isClientAbortException(ioe)) {
256
257 if (_log.isWarnEnabled()) {
258 _log.warn(ioe);
259 }
260 }
261 else {
262 throw ioe;
263 }
264 }
265 }
266
267 public static void write(
268 HttpServletResponse response, ByteBuffer byteBuffer)
269 throws IOException {
270
271 if (response instanceof ByteBufferServletResponse) {
272 ByteBufferServletResponse byteBufferResponse =
273 (ByteBufferServletResponse)response;
274
275 byteBufferResponse.setByteBuffer(byteBuffer);
276 }
277 else {
278 write(
279 response, byteBuffer.array(), byteBuffer.position(),
280 byteBuffer.limit());
281 }
282 }
283
284 public static void write(HttpServletResponse response, File file)
285 throws IOException {
286
287 if (response instanceof ByteBufferServletResponse) {
288 ByteBufferServletResponse byteBufferResponse =
289 (ByteBufferServletResponse)response;
290
291 ByteBuffer byteBuffer = ByteBuffer.wrap(FileUtil.getBytes(file));
292
293 byteBufferResponse.setByteBuffer(byteBuffer);
294 }
295 else if (response instanceof StringServletResponse) {
296 StringServletResponse stringResponse =
297 (StringServletResponse)response;
298
299 String s = FileUtil.read(file);
300
301 stringResponse.setString(s);
302 }
303 else {
304 FileInputStream fileInputStream = new FileInputStream(file);
305
306 FileChannel fileChannel = fileInputStream.getChannel();
307
308 try {
309 int contentLength = (int)fileChannel.size();
310
311 response.setContentLength(contentLength);
312
313 response.flushBuffer();
314
315 fileChannel.transferTo(
316 0, contentLength,
317 Channels.newChannel(response.getOutputStream()));
318 }
319 finally {
320 fileChannel.close();
321 }
322 }
323 }
324
325 public static void write(HttpServletResponse response, InputStream is)
326 throws IOException {
327
328 write(response, is, 0);
329 }
330
331 public static void write(
332 HttpServletResponse response, InputStream is, long contentLength)
333 throws IOException {
334
335 if (response.isCommitted()) {
336 return;
337 }
338
339 if (contentLength > 0) {
340 response.setHeader(
341 HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
342 }
343
344 response.flushBuffer();
345
346 StreamUtil.transfer(is, response.getOutputStream());
347 }
348
349 public static void write(HttpServletResponse response, String s)
350 throws IOException {
351
352 if (response instanceof StringServletResponse) {
353 StringServletResponse stringResponse =
354 (StringServletResponse)response;
355
356 stringResponse.setString(s);
357 }
358 else {
359 ByteBuffer byteBuffer = CharsetEncoderUtil.encode(
360 StringPool.UTF8, s);
361
362 write(response, byteBuffer);
363 }
364 }
365
366 public static void write(
367 HttpServletResponse response, StringServletResponse stringResponse)
368 throws IOException {
369
370 if (stringResponse.isCalledGetOutputStream()) {
371 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
372 stringResponse.getUnsyncByteArrayOutputStream();
373
374 ByteBuffer byteBuffer =
375 unsyncByteArrayOutputStream.unsafeGetByteBuffer();
376
377 write(response, byteBuffer);
378 }
379 else {
380 write(response, stringResponse.getString());
381 }
382 }
383
384 protected static boolean isClientAbortException(IOException ioe) {
385 Class<?> clazz = ioe.getClass();
386
387 String className = clazz.getName();
388
389 if (className.equals(_CLIENT_ABORT_EXCEPTION)) {
390 return true;
391 }
392 else {
393 return false;
394 }
395 }
396
397 protected static void setHeaders(
398 HttpServletRequest request, HttpServletResponse response,
399 String fileName, String contentType) {
400
401 if (_log.isDebugEnabled()) {
402 _log.debug("Sending file of type " + contentType);
403 }
404
405
406
407 if (Validator.isNotNull(contentType)) {
408 response.setContentType(contentType);
409 }
410
411 response.setHeader(
412 HttpHeaders.CACHE_CONTROL, HttpHeaders.CACHE_CONTROL_PUBLIC_VALUE);
413 response.setHeader(HttpHeaders.PRAGMA, HttpHeaders.PRAGMA_PUBLIC_VALUE);
414
415 if (Validator.isNotNull(fileName)) {
416 String contentDisposition =
417 "attachment; filename=\"" + fileName + "\"";
418
419
420
421
422 boolean ascii = true;
423
424 for (int i = 0; i < fileName.length(); i++) {
425 if (!Validator.isAscii(fileName.charAt(i))) {
426 ascii = false;
427
428 break;
429 }
430 }
431
432 try {
433 if (!ascii) {
434 String encodedFileName = HttpUtil.encodeURL(fileName, true);
435
436 if (BrowserSnifferUtil.isIe(request)) {
437 contentDisposition =
438 "attachment; filename=\"" + encodedFileName + "\"";
439 }
440 else {
441 contentDisposition =
442 "attachment; filename*=UTF-8''" + encodedFileName;
443 }
444 }
445 }
446 catch (Exception e) {
447 if (_log.isWarnEnabled()) {
448 _log.warn(e);
449 }
450 }
451
452 String extension = GetterUtil.getString(
453 FileUtil.getExtension(fileName)).toLowerCase();
454
455 String[] mimeTypesContentDispositionInline = null;
456
457 try {
458 mimeTypesContentDispositionInline = PropsUtil.getArray(
459 "mime.types.content.disposition.inline");
460 }
461 catch (Exception e) {
462 mimeTypesContentDispositionInline = new String[0];
463 }
464
465 if (ArrayUtil.contains(
466 mimeTypesContentDispositionInline, extension)) {
467
468 contentDisposition = StringUtil.replace(
469 contentDisposition, "attachment; ", "inline; ");
470 }
471
472 response.setHeader(
473 HttpHeaders.CONTENT_DISPOSITION, contentDisposition);
474 }
475 }
476
477 private static final String _CLIENT_ABORT_EXCEPTION =
478 "org.apache.catalina.connector.ClientAbortException";
479
480 private static Log _log = LogFactoryUtil.getLog(ServletResponseUtil.class);
481
482 }