Clover coverage report - Coverage timestamp: Sa Jul 7 2007 09:11:40 CEST FRAMES NO FRAMES |
file stats: | LOC: | 237 |  | Methods: | 17
| NCLOC: | 122 |  | Classes: | 1
Source file | Conditionals | Statements | Methods | TOTAL
ResponseContent.java | 0% | 0% | 0% | 0% |

1 |  | /*
2 |  | * Copyright (c) 2002-2003 by OpenSymphony
3 |  | * All rights reserved.
4 |  | */
5 |  | package com.opensymphony.oscache.web.filter;
6 |  |
7 |  | import java.io.*;
8 |  |
9 |  | import java.util.Locale;
10 |  | import java.util.zip.GZIPInputStream;
11 |  |
12 |  | import javax.servlet.ServletResponse;
13 |  | import javax.servlet.http.HttpServletResponse;
14 |  |
15 |  | /**
16 |  | * Holds the servlet response in a byte array so that it can be held
17 |  | * in the cache (and, since this class is serializable, optionally
18 |  | * persisted to disk).
19 |  | *
20 |  | * @version $Revision: 362 $
21 |  | * @author <a href="mailto:sergek@lokitech.com">Serge Knystautas</a>
22 |  | */
23 |  | public class ResponseContent implements Serializable {
24 |  | private transient ByteArrayOutputStream bout = new ByteArrayOutputStream(1000);
25 |  | private Locale locale = null;
26 |  | private String contentEncoding = null;
27 |  | private String contentType = null;
28 |  | private byte[] content = null;
29 |  | private long expires = Long.MAX_VALUE;
30 |  | private long lastModified = -1;
31 |  | private long maxAge = -60;
32 |  |
33 | 0 | public String getContentType() {
34 | 0 | return contentType;
35 |  | }
36 |  |
37 |  | /**
38 |  | * Set the content type. We capture this so that when we serve this
39 |  | * data from cache, we can set the correct content type on the response.
40 |  | */
41 | 0 | public void setContentType(String value) {
42 | 0 | contentType = value;
43 |  | }
44 |  |
45 | 0 | public long getLastModified() {
46 | 0 | return lastModified;
47 |  | }
48 |  |
49 | 0 | public void setLastModified(long value) {
50 | 0 | lastModified = value;
51 |  | }
52 |  |
53 | 0 | public String getContentEncoding() {
54 | 0 | return contentEncoding;
55 |  | }
56 |  |
57 | 0 | public void setContentEncoding(String contentEncoding) {
58 | 0 | this.contentEncoding = contentEncoding;
59 |  | }
60 |  |
61 |  | /**
62 |  | * Set the Locale. We capture this so that when we serve this data from
63 |  | * cache, we can set the correct locale on the response.
64 |  | */
65 | 0 | public void setLocale(Locale value) {
66 | 0 | locale = value;
67 |  | }
68 |  |
69 |  | /**
70 |  | * @return the expires date and time in miliseconds when the content will be stale
71 |  | */
72 | 0 | public long getExpires() {
73 | 0 | return expires;
74 |  | }
75 |  |
76 |  | /**
77 |  | * Sets the expires date and time in miliseconds.
78 |  | * @param value time in miliseconds when the content will expire
79 |  | */
80 | 0 | public void setExpires(long value) {
81 | 0 | expires = value;
82 |  | }
83 |  |
84 |  | /**
85 |  | * Returns the max age of the content in miliseconds. If expires header and cache control are
86 |  | * enabled both, both will be equal.
87 |  | * @return the max age of the content in miliseconds, if -1 max-age is disabled
88 |  | */
89 | 0 | public long getMaxAge() {
90 | 0 | return maxAge;
91 |  | }
92 |  |
93 |  | /**
94 |  | * Sets the max age date and time in miliseconds. If the parameter is -1, the max-age parameter
95 |  | * won't be set by default in the Cache-Control header.
96 |  | * @param value sets the intial
97 |  | */
98 | 0 | public void setMaxAge(long value) {
99 | 0 | maxAge = value;
100 |  | }
101 |  |
102 |  | /**
103 |  | * Get an output stream. This is used by the {@link SplitServletOutputStream}
104 |  | * to capture the original (uncached) response into a byte array.
105 |  | * @return the original (uncached) response, returns null if response is already committed.
106 |  | */
107 | 0 | public OutputStream getOutputStream() {
108 | 0 | return bout;
109 |  | }
110 |  |
111 |  | /**
112 |  | * Gets the size of this cached content.
113 |  | *
114 |  | * @return The size of the content, in bytes. If no content
115 |  | * exists, this method returns <code>-1</code>.
116 |  | */
117 | 0 | public int getSize() {
118 | 0 | return (content != null) ? content.length : (-1);
119 |  | }
120 |  |
121 |  | /**
122 |  | * Called once the response has been written in its entirety. This
123 |  | * method commits the response output stream by converting the output
124 |  | * stream into a byte array.
125 |  | */
126 | 0 | public void commit() {
127 | 0 | if (bout != null) {
128 | 0 | content = bout.toByteArray();
129 | 0 | bout = null;
130 |  | }
131 |  | }
132 |  |
133 |  | /**
134 |  | * Writes this cached data out to the supplied <code>ServletResponse</code>.
135 |  | *
136 |  | * @param response The servlet response to output the cached content to.
137 |  | * @throws IOException
138 |  | */
139 | 0 | public void writeTo(ServletResponse response) throws IOException {
140 | 0 | writeTo(response, false, false);
141 |  | }
142 |  |
143 |  | /**
144 |  | * Writes this cached data out to the supplied <code>ServletResponse</code>.
145 |  | *
146 |  | * @param response The servlet response to output the cached content to.
147 |  | * @param fragment is true if this content a fragment or part of a page
148 |  | * @param acceptsGZip is true if client browser supports gzip compression
149 |  | * @throws IOException
150 |  | */
151 | 0 | public void writeTo(ServletResponse response, boolean fragment, boolean acceptsGZip) throws IOException {
152 |  | //Send the content type and data to this response
153 | 0 | if (contentType != null) {
154 | 0 | response.setContentType(contentType);
155 |  | }
156 |  |
157 | 0 | if (fragment) {
158 |  | // Don't support gzip compression if the content is a fragment of a page
159 | 0 | acceptsGZip = false;
160 |  | } else {
161 |  | // add special headers for a complete page
162 | 0 | if (response instanceof HttpServletResponse) {
163 | 0 | HttpServletResponse httpResponse = (HttpServletResponse) response;
164 |  |
165 |  | // add the last modified header
166 | 0 | if (lastModified != -1) {
167 | 0 | httpResponse.setDateHeader(CacheFilter.HEADER_LAST_MODIFIED, lastModified);
168 |  | }
169 |  |
170 |  | // add the expires header
171 | 0 | if (expires != Long.MAX_VALUE) {
172 | 0 | httpResponse.setDateHeader(CacheFilter.HEADER_EXPIRES, expires);
173 |  | }
174 |  |
175 |  | // add the cache-control header for max-age
176 | 0 | if (maxAge == CacheFilter.MAX_AGE_NO_INIT || maxAge == CacheFilter.MAX_AGE_TIME) {
177 |  | // do nothing
178 | 0 | } else if (maxAge > 0) { // set max-age based on life time
179 | 0 | long currentMaxAge = maxAge / 1000 - System.currentTimeMillis() / 1000;
180 | 0 | if (currentMaxAge < 0) {
181 | 0 | currentMaxAge = 0;
182 |  | }
183 | 0 | httpResponse.addHeader(CacheFilter.HEADER_CACHE_CONTROL, "max-age=" + currentMaxAge);
184 |  | } else {
185 | 0 | httpResponse.addHeader(CacheFilter.HEADER_CACHE_CONTROL, "max-age=" + (-maxAge));
186 |  | }
187 |  |
188 |  | }
189 |  | }
190 |  |
191 | 0 | if (locale != null) {
192 | 0 | response.setLocale(locale);
193 |  | }
194 |  |
195 | 0 | OutputStream out = new BufferedOutputStream(response.getOutputStream());
196 |  |
197 | 0 | if (isContentGZiped()) {
198 | 0 | if (acceptsGZip) {
199 | 0 | ((HttpServletResponse) response).addHeader(CacheFilter.HEADER_CONTENT_ENCODING, "gzip");
200 | 0 | response.setContentLength(content.length);
201 | 0 | out.write(content);
202 |  | } else {
203 |  | // client doesn't support, so we have to uncompress it
204 | 0 | ByteArrayInputStream bais = new ByteArrayInputStream(content);
205 | 0 | GZIPInputStream zis = new GZIPInputStream(bais);
206 |  |
207 | 0 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
208 | 0 | int numBytesRead = 0;
209 | 0 | byte[] tempBytes = new byte[4196];
210 |  |
211 | 0 | while ((numBytesRead = zis.read(tempBytes, 0, tempBytes.length)) != -1) {
212 | 0 | baos.write(tempBytes, 0, numBytesRead);
213 |  | }
214 |  |
215 | 0 | byte[] result = baos.toByteArray();
216 |  |
217 | 0 | response.setContentLength(result.length);
218 | 0 | out.write(result);
219 |  | }
220 |  | } else {
221 |  | // the content isn't compressed
222 |  | // regardless if the client browser supports gzip we will just return the content
223 | 0 | response.setContentLength(content.length);
224 | 0 | out.write(content);
225 |  | }
226 | 0 | out.flush();
227 |  | }
228 |  |
229 |  |
230 |  | /**
231 |  | * @return true if the content is GZIP compressed
232 |  | */
233 | 0 | public boolean isContentGZiped() {
234 | 0 | return "gzip".equals(contentEncoding);
235 |  | }
236 |  |
237 |  | }