001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.servlet.filters.gzip;
016    
017    import com.liferay.portal.kernel.io.WriterOutputStream;
018    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.servlet.HttpHeaders;
022    
023    import java.io.IOException;
024    import java.io.OutputStream;
025    
026    import java.util.zip.GZIPOutputStream;
027    
028    import javax.servlet.ServletOutputStream;
029    import javax.servlet.http.HttpServletResponse;
030    
031    /**
032     * @author Jayson Falkner
033     * @author Brian Wing Shun Chan
034     * @author Shuyang Zhou
035     */
036    public class GZipStream extends ServletOutputStream {
037    
038            public GZipStream(HttpServletResponse response) throws IOException {
039                    super();
040    
041                    _response = response;
042                    _unsyncByteArrayOutputStream = new UnsyncByteArrayOutputStream();
043                    _gzipOutputStream = new GZIPOutputStream(_unsyncByteArrayOutputStream);
044            }
045    
046            public void close() throws IOException {
047                    if (_closed) {
048                            throw new IOException();
049                    }
050    
051                    _gzipOutputStream.finish();
052    
053                    int contentLength = _unsyncByteArrayOutputStream.size();
054    
055                    _response.setContentLength(contentLength);
056                    _response.addHeader(HttpHeaders.CONTENT_ENCODING, _GZIP);
057    
058                    try {
059                            flushOutToOutputStream();
060                    }
061                    catch (IllegalStateException ise) {
062                            flushOutToWriter();
063                    }
064    
065                    _closed = true;
066            }
067    
068            public boolean closed() {
069                    return _closed;
070            }
071    
072            public void flush() throws IOException {
073                    if (_closed) {
074                            throw new IOException();
075                    }
076    
077                    _gzipOutputStream.flush();
078            }
079    
080            public void reset() {
081            }
082    
083            public void write(byte b[]) throws IOException {
084                    write(b, 0, b.length);
085            }
086    
087            public void write(byte b[], int off, int len) throws IOException {
088                    if (_closed) {
089                            throw new IOException();
090                    }
091    
092                    // LEP-649
093    
094                    //_checkBufferSize(len);
095    
096                    try {
097                            _gzipOutputStream.write(b, off, len);
098                    }
099                    catch (IOException ioe) {
100                            _log.warn(ioe.getMessage());
101                    }
102            }
103    
104            public void write(int b) throws IOException {
105                    if (_closed) {
106                            throw new IOException();
107                    }
108    
109                    // LEP-649
110    
111                    //_checkBufferSize(1);
112    
113                    _gzipOutputStream.write((byte)b);
114            }
115    
116            private void flushOutToOutputStream() throws IOException {
117                    OutputStream outputStream = _response.getOutputStream();
118    
119                    outputStream.write(
120                            _unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
121                            _unsyncByteArrayOutputStream.size());
122    
123                    outputStream.flush();
124                    outputStream.close();
125            }
126    
127            private void flushOutToWriter() throws IOException {
128                    WriterOutputStream writerOutputStream = new WriterOutputStream(
129                            _response.getWriter());
130    
131                    writerOutputStream.write(
132                            _unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
133                            _unsyncByteArrayOutputStream.size());
134    
135                    writerOutputStream.flush();
136                    writerOutputStream.close();
137            }
138    
139            private static final String _GZIP = "gzip";
140    
141            private static Log _log = LogFactoryUtil.getLog(GZipStream.class);
142    
143            private boolean _closed;
144            private GZIPOutputStream _gzipOutputStream;
145            private HttpServletResponse _response;
146            private UnsyncByteArrayOutputStream _unsyncByteArrayOutputStream;
147    
148    }