001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.kernel.servlet;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
020    import com.liferay.portal.kernel.util.ArrayUtil;
021    import com.liferay.portal.kernel.util.ContentTypes;
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.MimeTypesUtil;
026    import com.liferay.portal.kernel.util.PropsKeys;
027    import com.liferay.portal.kernel.util.PropsUtil;
028    import com.liferay.portal.kernel.util.RandomAccessInputStream;
029    import com.liferay.portal.kernel.util.ServerDetector;
030    import com.liferay.portal.kernel.util.StreamUtil;
031    import com.liferay.portal.kernel.util.StringBundler;
032    import com.liferay.portal.kernel.util.StringPool;
033    import com.liferay.portal.kernel.util.StringUtil;
034    import com.liferay.portal.kernel.util.Validator;
035    
036    import java.io.ByteArrayInputStream;
037    import java.io.File;
038    import java.io.FileInputStream;
039    import java.io.IOException;
040    import java.io.InputStream;
041    import java.io.OutputStream;
042    
043    import java.net.SocketException;
044    
045    import java.nio.ByteBuffer;
046    import java.nio.CharBuffer;
047    import java.nio.channels.Channels;
048    import java.nio.channels.FileChannel;
049    
050    import java.util.ArrayList;
051    import java.util.Collections;
052    import java.util.List;
053    
054    import javax.servlet.ServletOutputStream;
055    import javax.servlet.http.HttpServletRequest;
056    import javax.servlet.http.HttpServletResponse;
057    
058    /**
059     * @author Brian Wing Shun Chan
060     * @author Shuyang Zhou
061     */
062    public class ServletResponseUtil {
063    
064            public static List<Range> getRanges(
065                            HttpServletRequest request, HttpServletResponse response,
066                            long length)
067                    throws IOException {
068    
069                    String rangeString = request.getHeader(HttpHeaders.RANGE);
070    
071                    if (Validator.isNull(rangeString)) {
072                            return Collections.emptyList();
073                    }
074    
075                    if (!rangeString.matches(_RANGE_REGEX)) {
076                            throw new IOException(
077                                    "Range header does not match regular expression " +
078                                    rangeString);
079                    }
080    
081                    List<Range> ranges = new ArrayList<Range>();
082    
083                    String[] rangeFields = StringUtil.split(rangeString.substring(6));
084    
085                    if (rangeFields.length > _MAX_RANGE_FIELDS) {
086                            StringBundler sb = new StringBundler(8);
087    
088                            sb.append("Request range ");
089                            sb.append(rangeString);
090                            sb.append(" with ");
091                            sb.append(rangeFields.length);
092                            sb.append(" range fields has exceeded maximum allowance as ");
093                            sb.append("specified by the property \"");
094                            sb.append(PropsKeys.WEB_SERVER_SERVLET_MAX_RANGE_FIELDS);
095                            sb.append("\"");
096    
097                            throw new IOException(sb.toString());
098                    }
099    
100                    for (String rangeField : rangeFields) {
101                            int index = rangeField.indexOf(StringPool.DASH);
102    
103                            long start = GetterUtil.getLong(rangeField.substring(0, index), -1);
104                            long end = GetterUtil.getLong(
105                                    rangeField.substring(index + 1, rangeField.length()), -1);
106    
107                            if (start == -1) {
108                                    start = length - end;
109                                    end = length - 1;
110                            }
111                            else if ((end == -1) || (end > (length - 1))) {
112                                    end = length - 1;
113                            }
114    
115                            if (start > end) {
116                                    throw new IOException(
117                                            "Range start " + start + " is greater than end " + end);
118                            }
119    
120                            Range range = new Range(start, end, length);
121    
122                            ranges.add(range);
123                    }
124    
125                    return ranges;
126            }
127    
128            public static boolean isClientAbortException(IOException ioe) {
129                    Class<?> clazz = ioe.getClass();
130    
131                    String className = clazz.getName();
132    
133                    if (className.equals(_CLIENT_ABORT_EXCEPTION)) {
134                            return true;
135                    }
136                    else {
137                            return false;
138                    }
139            }
140    
141            public static void sendFile(
142                            HttpServletRequest request, HttpServletResponse response,
143                            String fileName, byte[] bytes)
144                    throws IOException {
145    
146                    sendFile(request, response, fileName, bytes, null);
147            }
148    
149            public static void sendFile(
150                            HttpServletRequest request, HttpServletResponse response,
151                            String fileName, byte[] bytes, String contentType)
152                    throws IOException {
153    
154                    sendFile(request, response, fileName, bytes, contentType, null);
155            }
156    
157            public static void sendFile(
158                            HttpServletRequest request, HttpServletResponse response,
159                            String fileName, byte[] bytes, String contentType,
160                            String contentDispositionType)
161                    throws IOException {
162    
163                    setHeaders(
164                            request, response, fileName, contentType, contentDispositionType);
165    
166                    write(response, bytes);
167            }
168    
169            public static void sendFile(
170                            HttpServletRequest request, HttpServletResponse response,
171                            String fileName, InputStream inputStream)
172                    throws IOException {
173    
174                    sendFile(request, response, fileName, inputStream, null);
175            }
176    
177            public static void sendFile(
178                            HttpServletRequest request, HttpServletResponse response,
179                            String fileName, InputStream inputStream, long contentLength,
180                            String contentType)
181                    throws IOException {
182    
183                    sendFile(
184                            request, response, fileName, inputStream, contentLength,
185                            contentType, null);
186            }
187    
188            public static void sendFile(
189                            HttpServletRequest request, HttpServletResponse response,
190                            String fileName, InputStream inputStream, long contentLength,
191                            String contentType, String contentDispositionType)
192                    throws IOException {
193    
194                    setHeaders(
195                            request, response, fileName, contentType, contentDispositionType);
196    
197                    write(response, inputStream, contentLength);
198            }
199    
200            public static void sendFile(
201                            HttpServletRequest request, HttpServletResponse response,
202                            String fileName, InputStream inputStream, String contentType)
203                    throws IOException {
204    
205                    sendFile(request, response, fileName, inputStream, 0, contentType);
206            }
207    
208            /**
209             * @deprecated As of 6.1.0
210             */
211            public static void sendFile(
212                            HttpServletResponse response, String fileName, byte[] bytes)
213                    throws IOException {
214    
215                    sendFile(null, response, fileName, bytes);
216            }
217    
218            /**
219             * @deprecated As of 6.1.0
220             */
221            public static void sendFile(
222                            HttpServletResponse response, String fileName, byte[] bytes,
223                            String contentType)
224                    throws IOException {
225    
226                    sendFile(null, response, fileName, bytes, contentType);
227            }
228    
229            /**
230             * @deprecated As of 6.1.0
231             */
232            public static void sendFile(
233                            HttpServletResponse response, String fileName,
234                            InputStream inputStream)
235                    throws IOException {
236    
237                    sendFile(null, response, fileName, inputStream);
238            }
239    
240            /**
241             * @deprecated As of 6.1.0
242             */
243            public static void sendFile(
244                            HttpServletResponse response, String fileName,
245                            InputStream inputStream, int contentLength, String contentType)
246                    throws IOException {
247    
248                    sendFile(
249                            null, response, fileName, inputStream, contentLength, contentType);
250            }
251    
252            /**
253             * @deprecated As of 6.1.0
254             */
255            public static void sendFile(
256                            HttpServletResponse response, String fileName,
257                            InputStream inputStream, String contentType)
258                    throws IOException {
259    
260                    sendFile(null, response, fileName, inputStream, contentType);
261            }
262    
263            public static void sendFileWithRangeHeader(
264                            HttpServletRequest request, HttpServletResponse response,
265                            String fileName, InputStream inputStream, long contentLength,
266                            String contentType)
267                    throws IOException {
268    
269                    if (_log.isDebugEnabled()) {
270                            _log.debug("Accepting ranges for the file " + fileName);
271                    }
272    
273                    response.setHeader(
274                            HttpHeaders.ACCEPT_RANGES, HttpHeaders.ACCEPT_RANGES_BYTES_VALUE);
275    
276                    List<Range> ranges = null;
277    
278                    try {
279                            ranges = getRanges(request, response, contentLength);
280                    }
281                    catch (IOException ioe) {
282                            if (_log.isErrorEnabled()) {
283                                    _log.error(ioe);
284                            }
285    
286                            response.setHeader(
287                                    HttpHeaders.CONTENT_RANGE, "bytes */" + contentLength);
288    
289                            response.sendError(
290                                    HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
291    
292                            return;
293                    }
294    
295                    if ((ranges == null) || ranges.isEmpty()) {
296                            sendFile(
297                                    request, response, fileName, inputStream, contentLength,
298                                    contentType);
299                    }
300                    else {
301                            if (_log.isDebugEnabled()) {
302                                    _log.debug(
303                                            "Request has range header " +
304                                                    request.getHeader(HttpHeaders.RANGE));
305                            }
306    
307                            write(
308                                    request, response, fileName, ranges, inputStream, contentLength,
309                                    contentType);
310                    }
311            }
312    
313            public static void write(
314                            HttpServletRequest request, HttpServletResponse response,
315                            String fileName, List<Range> ranges, InputStream inputStream,
316                            long fullLength, String contentType)
317                    throws IOException {
318    
319                    OutputStream outputStream = null;
320    
321                    try {
322                            outputStream = response.getOutputStream();
323    
324                            Range fullRange = new Range(0, fullLength - 1, fullLength);
325    
326                            Range firstRange = null;
327    
328                            if (!ranges.isEmpty()) {
329                                    firstRange = ranges.get(0);
330                            }
331    
332                            if ((firstRange == null) || firstRange.equals(fullRange)) {
333                                    if (_log.isDebugEnabled()) {
334                                            _log.debug("Writing full range");
335                                    }
336    
337                                    response.setContentType(contentType);
338    
339                                    setHeaders(
340                                            request, response, fileName, contentType, null, fullRange);
341    
342                                    copyRange(
343                                            inputStream, outputStream, fullRange.getStart(),
344                                            fullRange.getLength());
345                            }
346                            else if (ranges.size() == 1) {
347                                    if (_log.isDebugEnabled()) {
348                                            _log.debug("Attempting to write a single range");
349                                    }
350    
351                                    Range range = ranges.get(0);
352    
353                                    response.setContentType(contentType);
354    
355                                    setHeaders(
356                                            request, response, fileName, contentType, null, range);
357    
358                                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
359    
360                                    copyRange(
361                                            inputStream, outputStream, range.getStart(),
362                                            range.getLength());
363                            }
364                            else if (ranges.size() > 1 ) {
365                                    if (_log.isDebugEnabled()) {
366                                            _log.debug("Attempting to write multiple ranges");
367                                    }
368    
369                                    ServletOutputStream servletOutputStream =
370                                            (ServletOutputStream)outputStream;
371    
372                                    String boundary =
373                                            "liferay-multipart-boundary-" + System.currentTimeMillis();
374    
375                                    String multipartContentType =
376                                            "multipart/byteranges; boundary=" + boundary;
377    
378                                    response.setContentType(multipartContentType);
379    
380                                    setHeaders(
381                                            request, response, fileName, multipartContentType, null);
382    
383                                    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
384    
385                                    for (int i = 0; i < ranges.size(); i++) {
386                                            Range range = ranges.get(i);
387    
388                                            servletOutputStream.println();
389                                            servletOutputStream.println(
390                                                    StringPool.DOUBLE_DASH + boundary);
391                                            servletOutputStream.println(
392                                                    HttpHeaders.CONTENT_TYPE + ": " + contentType);
393                                            servletOutputStream.println(
394                                                    HttpHeaders.CONTENT_RANGE + ": " +
395                                                            range.getContentRange());
396                                            servletOutputStream.println();
397    
398                                            inputStream = copyRange(
399                                                    inputStream, outputStream, range.getStart(),
400                                                    range.getLength());
401                                    }
402    
403                                    servletOutputStream.println();
404                                    servletOutputStream.println(
405                                            StringPool.DOUBLE_DASH + boundary + StringPool.DOUBLE_DASH);
406                            }
407                    }
408                    finally {
409                            try {
410                                    inputStream.close();
411                            }
412                            catch (IOException ioe) {
413                            }
414                    }
415            }
416    
417            public static void write(
418                            HttpServletResponse response,
419                            BufferCacheServletResponse bufferCacheServletResponse)
420                    throws IOException {
421    
422                    if (bufferCacheServletResponse.isByteMode()) {
423                            write(response, bufferCacheServletResponse.getByteBuffer());
424                    }
425                    else if (bufferCacheServletResponse.isCharMode()) {
426                            write(response, bufferCacheServletResponse.getCharBuffer());
427                    }
428            }
429    
430            public static void write(HttpServletResponse response, byte[] bytes)
431                    throws IOException {
432    
433                    write(response, bytes, 0, 0);
434            }
435    
436            public static void write(
437                            HttpServletResponse response, byte[] bytes, int offset,
438                            int contentLength)
439                    throws IOException {
440    
441                    try {
442    
443                            // LEP-3122
444    
445                            if (!response.isCommitted()) {
446    
447                                    // LEP-536
448    
449                                    if (contentLength == 0) {
450                                            contentLength = bytes.length;
451                                    }
452    
453                                    response.setContentLength(contentLength);
454    
455                                    response.flushBuffer();
456    
457                                    if (response instanceof BufferCacheServletResponse) {
458                                            BufferCacheServletResponse bufferCacheServletResponse =
459                                                    (BufferCacheServletResponse)response;
460    
461                                            bufferCacheServletResponse.setByteBuffer(
462                                                    ByteBuffer.wrap(bytes, offset, contentLength));
463                                    }
464                                    else {
465                                            ServletOutputStream servletOutputStream =
466                                                    response.getOutputStream();
467    
468                                            if ((contentLength == 0) && ServerDetector.isJetty()) {
469                                            }
470                                            else {
471                                                    servletOutputStream.write(bytes, offset, contentLength);
472                                            }
473                                    }
474                            }
475                    }
476                    catch (IOException ioe) {
477                            if ((ioe instanceof SocketException) ||
478                                    isClientAbortException(ioe)) {
479    
480                                    if (_log.isWarnEnabled()) {
481                                            _log.warn(ioe);
482                                    }
483                            }
484                            else {
485                                    throw ioe;
486                            }
487                    }
488            }
489    
490            public static void write(HttpServletResponse response, byte[][] bytesArray)
491                    throws IOException {
492    
493                    try {
494    
495                            // LEP-3122
496    
497                            if (!response.isCommitted()) {
498                                    long contentLength = 0;
499    
500                                    for (byte[] bytes : bytesArray) {
501                                            contentLength += bytes.length;
502                                    }
503    
504                                    setContentLength(response, contentLength);
505    
506                                    response.flushBuffer();
507    
508                                    ServletOutputStream servletOutputStream =
509                                            response.getOutputStream();
510    
511                                    for (byte[] bytes : bytesArray) {
512                                            servletOutputStream.write(bytes);
513                                    }
514                            }
515                    }
516                    catch (IOException ioe) {
517                            if ((ioe instanceof SocketException) ||
518                                    isClientAbortException(ioe)) {
519    
520                                    if (_log.isWarnEnabled()) {
521                                            _log.warn(ioe);
522                                    }
523                            }
524                            else {
525                                    throw ioe;
526                            }
527                    }
528            }
529    
530            public static void write(
531                            HttpServletResponse response, ByteBuffer byteBuffer)
532                    throws IOException {
533    
534                    if (response instanceof BufferCacheServletResponse) {
535                            BufferCacheServletResponse bufferCacheServletResponse =
536                                    (BufferCacheServletResponse)response;
537    
538                            bufferCacheServletResponse.setByteBuffer(byteBuffer);
539                    }
540                    else {
541                            write(
542                                    response, byteBuffer.array(),
543                                    byteBuffer.arrayOffset() + byteBuffer.position(),
544                                    byteBuffer.arrayOffset() + byteBuffer.limit());
545                    }
546            }
547    
548            public static void write(
549                            HttpServletResponse response, CharBuffer charBuffer)
550                    throws IOException {
551    
552                    if (response instanceof BufferCacheServletResponse) {
553                            BufferCacheServletResponse bufferCacheServletResponse =
554                                    (BufferCacheServletResponse)response;
555    
556                            bufferCacheServletResponse.setCharBuffer(charBuffer);
557                    }
558                    else {
559                            ByteBuffer byteBuffer = CharsetEncoderUtil.encode(
560                                    StringPool.UTF8, charBuffer);
561    
562                            write(response, byteBuffer);
563                    }
564            }
565    
566            public static void write(HttpServletResponse response, File file)
567                    throws IOException {
568    
569                    if (response instanceof BufferCacheServletResponse) {
570                            BufferCacheServletResponse bufferCacheServletResponse =
571                                    (BufferCacheServletResponse)response;
572    
573                            ByteBuffer byteBuffer = ByteBuffer.wrap(FileUtil.getBytes(file));
574    
575                            bufferCacheServletResponse.setByteBuffer(byteBuffer);
576                    }
577                    else {
578                            FileInputStream fileInputStream = new FileInputStream(file);
579    
580                            FileChannel fileChannel = fileInputStream.getChannel();
581    
582                            try {
583                                    long contentLength = fileChannel.size();
584    
585                                    setContentLength(response, contentLength);
586    
587                                    response.flushBuffer();
588    
589                                    fileChannel.transferTo(
590                                            0, contentLength,
591                                            Channels.newChannel(response.getOutputStream()));
592                            }
593                            finally {
594                                    fileChannel.close();
595                            }
596                    }
597            }
598    
599            public static void write(
600                            HttpServletResponse response, InputStream inputStream)
601                    throws IOException {
602    
603                    write(response, inputStream, 0);
604            }
605    
606            public static void write(
607                            HttpServletResponse response, InputStream inputStream,
608                            long contentLength)
609                    throws IOException {
610    
611                    OutputStream outputStream = null;
612    
613                    try {
614                            if (response.isCommitted()) {
615                                    return;
616                            }
617    
618                            if (contentLength > 0) {
619                                    setContentLength(response, contentLength);
620                            }
621    
622                            response.flushBuffer();
623    
624                            StreamUtil.transfer(inputStream, response.getOutputStream(), false);
625                    }
626                    finally {
627                            StreamUtil.cleanUp(inputStream, outputStream);
628                    }
629            }
630    
631            public static void write(HttpServletResponse response, String s)
632                    throws IOException {
633    
634                    if (response instanceof BufferCacheServletResponse) {
635                            BufferCacheServletResponse bufferCacheServletResponse =
636                                    (BufferCacheServletResponse)response;
637    
638                            bufferCacheServletResponse.setString(s);
639                    }
640                    else {
641                            ByteBuffer byteBuffer = CharsetEncoderUtil.encode(
642                                    StringPool.UTF8, s);
643    
644                            write(response, byteBuffer);
645                    }
646            }
647    
648            protected static InputStream copyRange(
649                            InputStream inputStream, OutputStream outputStream, long start,
650                            long length)
651                    throws IOException {
652    
653                    if (inputStream instanceof FileInputStream) {
654                            FileInputStream fileInputStream = (FileInputStream)inputStream;
655    
656                            FileChannel fileChannel = fileInputStream.getChannel();
657    
658                            fileChannel.transferTo(
659                                    start, length, Channels.newChannel(outputStream));
660    
661                            return fileInputStream;
662                    }
663                    else if (inputStream instanceof ByteArrayInputStream) {
664                            ByteArrayInputStream byteArrayInputStream =
665                                    (ByteArrayInputStream)inputStream;
666    
667                            byteArrayInputStream.reset();
668                            byteArrayInputStream.skip(start);
669    
670                            StreamUtil.transfer(byteArrayInputStream, outputStream, length);
671    
672                            return byteArrayInputStream;
673                    }
674                    else if (inputStream instanceof RandomAccessInputStream) {
675                            RandomAccessInputStream randomAccessInputStream =
676                                    (RandomAccessInputStream)inputStream;
677    
678                            randomAccessInputStream.seek(start);
679    
680                            StreamUtil.transfer(
681                                    randomAccessInputStream, outputStream, StreamUtil.BUFFER_SIZE,
682                                    false, length);
683    
684                            return randomAccessInputStream;
685                    }
686    
687                    return copyRange(
688                            new RandomAccessInputStream(inputStream), outputStream, start,
689                            length);
690            }
691    
692            protected static void setContentLength(
693                    HttpServletResponse response, long contentLength) {
694    
695                    response.setHeader(
696                            HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
697            }
698    
699            protected static void setHeaders(
700                    HttpServletRequest request, HttpServletResponse response,
701                    String fileName, String contentType, String contentDispositionType) {
702    
703                    if (_log.isDebugEnabled()) {
704                            _log.debug("Sending file of type " + contentType);
705                    }
706    
707                    // LEP-2201
708    
709                    if (Validator.isNotNull(contentType)) {
710                            if (contentType.equals(ContentTypes.IMAGE_X_MS_BMP) &&
711                                    BrowserSnifferUtil.isIe(request)) {
712    
713                                    contentType = ContentTypes.IMAGE_BMP;
714                            }
715    
716                            response.setContentType(contentType);
717                    }
718    
719                    if (!response.containsHeader(HttpHeaders.CACHE_CONTROL)) {
720                            response.setHeader(
721                                    HttpHeaders.CACHE_CONTROL,
722                                    HttpHeaders.CACHE_CONTROL_PRIVATE_VALUE);
723                    }
724    
725                    if (Validator.isNull(fileName)) {
726                            return;
727                    }
728    
729                    String contentDispositionFileName = "filename=\"" + fileName + "\"";
730    
731                    // If necessary for non-ASCII characters, encode based on RFC 2184.
732                    // However, not all browsers support RFC 2184. See LEP-3127.
733    
734                    boolean ascii = true;
735    
736                    for (int i = 0; i < fileName.length(); i++) {
737                            if (!Validator.isAscii(fileName.charAt(i))) {
738                                    ascii = false;
739    
740                                    break;
741                            }
742                    }
743    
744                    if (!ascii) {
745                            String encodedFileName = HttpUtil.encodeURL(fileName, true);
746    
747                            if (BrowserSnifferUtil.isIe(request)) {
748                                    contentDispositionFileName =
749                                            "filename=\"" + encodedFileName + "\"";
750                            }
751                            else {
752                                    contentDispositionFileName =
753                                            "filename*=UTF-8''" + encodedFileName;
754                            }
755                    }
756    
757                    if (Validator.isNull(contentDispositionType)) {
758                            String extension = GetterUtil.getString(
759                                    FileUtil.getExtension(fileName));
760    
761                            extension = StringUtil.toLowerCase(extension);
762    
763                            String[] mimeTypesContentDispositionInline = null;
764    
765                            try {
766                                    mimeTypesContentDispositionInline = PropsUtil.getArray(
767                                            PropsKeys.MIME_TYPES_CONTENT_DISPOSITION_INLINE);
768                            }
769                            catch (Exception e) {
770                                    mimeTypesContentDispositionInline = new String[0];
771                            }
772    
773                            if (ArrayUtil.contains(
774                                            mimeTypesContentDispositionInline, extension)) {
775    
776                                    contentDispositionType = HttpHeaders.CONTENT_DISPOSITION_INLINE;
777    
778                                    contentType = MimeTypesUtil.getContentType(fileName);
779    
780                                    response.setContentType(contentType);
781                            }
782                            else {
783                                    contentDispositionType =
784                                            HttpHeaders.CONTENT_DISPOSITION_ATTACHMENT;
785                            }
786                    }
787    
788                    StringBundler sb = new StringBundler(4);
789    
790                    sb.append(contentDispositionType);
791                    sb.append(StringPool.SEMICOLON);
792                    sb.append(StringPool.SPACE);
793                    sb.append(contentDispositionFileName);
794    
795                    if (_log.isDebugEnabled()) {
796                            _log.debug("Setting content disposition header " + sb.toString());
797                    }
798    
799                    response.setHeader(HttpHeaders.CONTENT_DISPOSITION, sb.toString());
800            }
801    
802            protected static void setHeaders(
803                    HttpServletRequest request, HttpServletResponse response,
804                    String fileName, String contentType, String contentDispositionType,
805                    Range range) {
806    
807                    setHeaders(
808                            request, response, fileName, contentType, contentDispositionType);
809    
810                    if (range != null) {
811                            response.setHeader(
812                                    HttpHeaders.CONTENT_RANGE, range.getContentRange());
813    
814                            response.setHeader(
815                                    HttpHeaders.CONTENT_LENGTH, String.valueOf(range.getLength()));
816                    }
817            }
818    
819            private static final String _CLIENT_ABORT_EXCEPTION =
820                    "org.apache.catalina.connector.ClientAbortException";
821    
822            private static final int _MAX_RANGE_FIELDS = GetterUtil.getInteger(
823                    PropsUtil.get(PropsKeys.WEB_SERVER_SERVLET_MAX_RANGE_FIELDS));
824    
825            private static final String _RANGE_REGEX =
826                    "^bytes=\\d*-\\d*(,\\s?\\d*-\\d*)*$";
827    
828            private static Log _log = LogFactoryUtil.getLog(ServletResponseUtil.class);
829    
830    }