1
17 package org.apache.coyote.http11.filters;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.nio.ByteBuffer;
22 import java.util.zip.GZIPOutputStream;
23
24 import org.apache.coyote.Response;
25 import org.apache.coyote.http11.HttpOutputBuffer;
26 import org.apache.coyote.http11.OutputFilter;
27 import org.apache.juli.logging.Log;
28 import org.apache.juli.logging.LogFactory;
29
30
35 public class GzipOutputFilter implements OutputFilter {
36
37 protected static final Log log = LogFactory.getLog(GzipOutputFilter.class);
38
39
40
41
42
45 protected HttpOutputBuffer buffer;
46
47
48
51 protected GZIPOutputStream compressionStream = null;
52
53
54
57 protected final OutputStream fakeOutputStream = new FakeOutputStream();
58
59
60
61
62 @Override
63 public int doWrite(ByteBuffer chunk) throws IOException {
64 if (compressionStream == null) {
65 compressionStream = new GZIPOutputStream(fakeOutputStream, true);
66 }
67 int len = chunk.remaining();
68 if (chunk.hasArray()) {
69 compressionStream.write(chunk.array(), chunk.arrayOffset() + chunk.position(), len);
70 } else {
71 byte[] bytes = new byte[len];
72 chunk.put(bytes);
73 compressionStream.write(bytes, 0, len);
74 }
75 return len;
76 }
77
78
79 @Override
80 public long getBytesWritten() {
81 return buffer.getBytesWritten();
82 }
83
84
85
86
87
90 @Override
91 public void flush() throws IOException {
92 if (compressionStream != null) {
93 try {
94 if (log.isDebugEnabled()) {
95 log.debug("Flushing the compression stream!");
96 }
97 compressionStream.flush();
98 } catch (IOException e) {
99 if (log.isDebugEnabled()) {
100 log.debug("Ignored exception while flushing gzip filter", e);
101 }
102 }
103 }
104 buffer.flush();
105 }
106
107
108 @Override
109 public void setResponse(Response response) {
110
111 }
112
113
114 @Override
115 public void setBuffer(HttpOutputBuffer buffer) {
116 this.buffer = buffer;
117 }
118
119
120 @Override
121 public void end() throws IOException {
122 if (compressionStream == null) {
123 compressionStream = new GZIPOutputStream(fakeOutputStream, true);
124 }
125 compressionStream.finish();
126 compressionStream.close();
127 buffer.end();
128 }
129
130
131
134 @Override
135 public void recycle() {
136
137 compressionStream = null;
138 }
139
140
141
142
143
144 protected class FakeOutputStream
145 extends OutputStream {
146 protected final ByteBuffer outputChunk = ByteBuffer.allocate(1);
147 @Override
148 public void write(int b)
149 throws IOException {
150
151
152 outputChunk.put(0, (byte) (b & 0xff));
153 buffer.doWrite(outputChunk);
154 }
155 @Override
156 public void write(byte[] b, int off, int len)
157 throws IOException {
158 buffer.doWrite(ByteBuffer.wrap(b, off, len));
159 }
160 @Override
161 public void flush() throws IOException {}
162 @Override
163 public void close() throws IOException {}
164 }
165
166
167 }
168