Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixed issues with serializability

  • Loading branch information...
commit da73d8a89f2d02c4af46af635eb482a9185db3ee 1 parent 2bddde3
Burt Beckwith authored
View
109 src/java/grails/plugin/cache/SerializableByteArrayOutputStream.java
@@ -0,0 +1,109 @@
+/* Copyright 2012 SpringSource.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package grails.plugin.cache;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * A Serializable version of java.io.ByteArrayOutputStream.
+ *
+ * @author Burt Beckwith
+ */
+public class SerializableByteArrayOutputStream extends SerializableOutputStream {
+
+ private static final long serialVersionUID = 1;
+
+ protected byte[] buf;
+ protected int count;
+
+ public SerializableByteArrayOutputStream() {
+ this(32);
+ }
+
+ public SerializableByteArrayOutputStream(int size) {
+ if (size < 0) {
+ throw new IllegalArgumentException("Negative initial size: " + size);
+ }
+ buf = new byte[size];
+ }
+
+ @Override
+ public synchronized void write(int b) {
+ int newcount = count + 1;
+ if (newcount > buf.length) {
+ buf = copyOf(Math.max(buf.length << 1, newcount));
+ }
+ buf[count] = (byte)b;
+ count = newcount;
+ }
+
+ @Override
+ public synchronized void write(byte[] b, int off, int len) {
+ if ((off < 0) || (off > b.length) || (len < 0) ||
+ ((off + len) > b.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (len == 0) {
+ return;
+ }
+
+ int newcount = count + len;
+ if (newcount > buf.length) {
+ buf = copyOf(Math.max(buf.length << 1, newcount));
+ }
+ System.arraycopy(b, off, buf, count, len);
+ count = newcount;
+ }
+
+ public synchronized void writeTo(OutputStream out) throws IOException {
+ out.write(buf, 0, count);
+ }
+
+ public synchronized void reset() {
+ count = 0;
+ }
+
+ public synchronized byte[] toByteArray() {
+ return copyOf(count);
+ }
+
+ // ByteArrayOutputStream uses Arrays.copyOf which is only in Java 6, that's inlined here.
+ protected byte[] copyOf(int newLength) {
+ byte[] copy = new byte[newLength];
+ System.arraycopy(buf, 0, copy, 0, Math.min(buf.length, newLength));
+ return copy;
+ }
+
+ public synchronized int size() {
+ return count;
+ }
+
+ @Override
+ public synchronized String toString() {
+ return new String(buf, 0, count);
+ }
+
+ public synchronized String toString(String charsetName) throws UnsupportedEncodingException {
+ return new String(buf, 0, count, charsetName);
+ }
+
+ @Override
+ public void close() throws IOException {
+ // no-op
+ }
+}
View
28 src/java/grails/plugin/cache/SerializableOutputStream.java
@@ -0,0 +1,28 @@
+/* Copyright 2012 SpringSource.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package grails.plugin.cache;
+
+import java.io.OutputStream;
+import java.io.Serializable;
+
+/**
+ * Abstract base class for serializable OutputStream classes.
+ *
+ * @author Burt Beckwith
+ */
+@SuppressWarnings("serial")
+public abstract class SerializableOutputStream extends OutputStream implements Serializable {
+ // no methods
+}
View
11 src/java/grails/plugin/cache/web/GenericResponseWrapper.java
@@ -14,11 +14,11 @@
*/
package grails.plugin.cache.web;
+import grails.plugin.cache.SerializableOutputStream;
import grails.plugin.cache.web.Header.Type;
import grails.plugin.cache.web.filter.FilterServletOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Serializable;
@@ -34,7 +34,6 @@
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
-import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
@@ -54,8 +53,6 @@
private static final long serialVersionUID = 1;
- private final Logger log = LoggerFactory.getLogger(getClass());
-
private int statusCode = SC_OK;
private int contentLength;
private String contentType;
@@ -63,13 +60,13 @@
String.CASE_INSENSITIVE_ORDER);
private final List<Cookie> cookies = new ArrayList<Cookie>();
private ServletOutputStream out;
- private PrintWriter writer;
+ private transient PrintWriter writer;
private boolean disableFlushBuffer = true;
/**
* Creates a GenericResponseWrapper
*/
- public GenericResponseWrapper(final HttpServletResponse response, final OutputStream outputStream) {
+ public GenericResponseWrapper(final HttpServletResponse response, final SerializableOutputStream outputStream) {
super(response);
out = new FilterServletOutputStream(outputStream);
}
@@ -128,7 +125,7 @@ public void sendRedirect(String string) throws IOException {
@Override
public void setStatus(final int code, final String msg) {
statusCode = code;
- log.warn("Discarding message because this method is deprecated.");
+ LoggerFactory.getLogger(getClass()).warn("Discarding message because this method is deprecated.");
super.setStatus(code);
}
View
9 src/java/grails/plugin/cache/web/HttpDateFormatter.java
@@ -14,13 +14,13 @@
*/
package grails.plugin.cache.web;
+import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
-import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
@@ -52,9 +52,9 @@
* @author Greg Luck
* @author Burt Beckwith
*/
-public class HttpDateFormatter {
+public class HttpDateFormatter implements Serializable {
- protected final Logger log = LoggerFactory.getLogger(getClass());
+ private static final long serialVersionUID = 1;
protected final SimpleDateFormat httpDateFormat;
@@ -92,7 +92,8 @@ public synchronized Date parseDateFromHttpDate(String date) {
return httpDateFormat.parse(date);
}
catch (ParseException e) {
- log.debug("ParseException on date {}. 1/1/1970 will be returned", date);
+ LoggerFactory.getLogger(getClass()).debug(
+ "ParseException on date {}. 1/1/1970 will be returned", date);
return new Date(0);
}
}
View
53 src/java/grails/plugin/cache/web/PageInfo.java
@@ -34,11 +34,17 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import net.sf.cglib.proxy.Callback;
+
+import org.codehaus.groovy.grails.plugins.web.api.ControllersApi;
+import org.codehaus.groovy.grails.web.servlet.GrailsFlashScope;
import org.codehaus.groovy.grails.web.servlet.HttpHeaders;
-import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.aop.PointcutAdvisor;
+import org.springframework.aop.TargetSource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.FlashMap;
/**
* A Serializable representation of a {@link HttpServletResponse}.
@@ -59,12 +65,10 @@
protected static final int GZIP_MAGIC_NUMBER_BYTE_2 = -117;
protected static final long ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
- private final Logger log = LoggerFactory.getLogger(getClass());
-
private final HttpDateFormatter httpDateFormatter = new HttpDateFormatter();
private final List<Header<? extends Serializable>> responseHeaders = new ArrayList<Header<? extends Serializable>>();
private final List<SerializableCookie> serializableCookies = new ArrayList<SerializableCookie>();
- private Map<String, ? extends Serializable> requestAttributes;
+ private Map<String, Serializable> requestAttributes;
private String contentType;
private byte[] gzippedBody;
private byte[] ungzippedBody;
@@ -90,7 +94,7 @@
public PageInfo(final int statusCode, final String contentType, final byte[] body,
boolean storeGzipped, long timeToLiveSeconds, final Collection<Header<? extends Serializable>> headers,
@SuppressWarnings("unused") final Collection<Cookie> cookies,
- Map<String, ? extends Serializable> requestAttributes) throws AlreadyGzippedException {
+ Map<String, Serializable> requestAttributes) throws AlreadyGzippedException {
if (headers != null) {
responseHeaders.addAll(headers);
@@ -101,7 +105,8 @@ public PageInfo(final int statusCode, final String contentType, final byte[] bod
this.contentType = contentType;
this.storeGzipped = storeGzipped;
this.statusCode = statusCode;
- this.requestAttributes = requestAttributes;
+ setCacheableRequestAttributes(requestAttributes);
+
// bug 2630970
// extractCookies(cookies);
@@ -122,7 +127,7 @@ public PageInfo(final int statusCode, final String contentType, final byte[] bod
}
}
catch (IOException e) {
- log.error("Error ungzipping gzipped body", e);
+ LoggerFactory.getLogger(getClass()).error("Error ungzipping gzipped body", e);
}
}
@@ -306,7 +311,7 @@ public long getTimeToLiveSeconds() {
return timeToLiveSeconds;
}
- public Map<String, ? extends Serializable> getRequestAttributes() {
+ public Map<String, Serializable> getRequestAttributes() {
return Collections.unmodifiableMap(requestAttributes);
}
@@ -388,4 +393,36 @@ public boolean isMatch(HttpServletRequest request) {
}
return directives;
}
+
+ private void setCacheableRequestAttributes(Map<String, Serializable> attributes) {
+ requestAttributes = new HashMap<String, Serializable>();
+
+ for (Map.Entry<String, Serializable> entry : attributes.entrySet()) {
+ Serializable value = entry.getValue();
+
+ if (value instanceof GrailsFlashScope) {
+ continue;
+ }
+ if (value instanceof FlashMap) {
+ continue;
+ }
+ if (value instanceof HttpServletResponse) {
+ continue;
+ }
+ if (value instanceof ControllersApi) {
+ continue;
+ }
+ if (value instanceof PointcutAdvisor || value instanceof PointcutAdvisor[]) {
+ continue;
+ }
+ if (value instanceof Callback || value instanceof Callback[]) {
+ continue;
+ }
+ if (value instanceof TargetSource) {
+ continue;
+ }
+
+ requestAttributes.put(entry.getKey(), value);
+ }
+ }
}
View
12 src/java/grails/plugin/cache/web/filter/FilterServletOutputStream.java
@@ -14,8 +14,10 @@
*/
package grails.plugin.cache.web.filter;
+import grails.plugin.cache.SerializableOutputStream;
+
import java.io.IOException;
-import java.io.OutputStream;
+import java.io.Serializable;
import javax.servlet.ServletOutputStream;
@@ -27,11 +29,13 @@
* @author Greg Luck
* @author Burt Beckwith
*/
-public class FilterServletOutputStream extends ServletOutputStream {
+public class FilterServletOutputStream extends ServletOutputStream implements Serializable {
+
+ private static final long serialVersionUID = 1;
- protected OutputStream stream;
+ protected SerializableOutputStream stream;
- public FilterServletOutputStream(final OutputStream stream) {
+ public FilterServletOutputStream(final SerializableOutputStream stream) {
this.stream = stream;
}
View
8 src/java/grails/plugin/cache/web/filter/PageFragmentCachingFilter.java
@@ -14,6 +14,7 @@
*/
package grails.plugin.cache.web.filter;
+import grails.plugin.cache.SerializableByteArrayOutputStream;
import grails.plugin.cache.Timer;
import grails.plugin.cache.web.ContentCacheParameters;
import grails.plugin.cache.web.GenericResponseWrapper;
@@ -21,7 +22,6 @@
import grails.plugin.cache.web.PageInfo;
import grails.plugin.cache.web.SerializableCookie;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
@@ -313,7 +313,7 @@ private void releaseCacheLocks(Map<String, Collection<CacheOperationContext>> op
private PageInfo buildPage(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
// Invoke the next entity in the chain
- ByteArrayOutputStream out = new ByteArrayOutputStream();
+ SerializableByteArrayOutputStream out = new SerializableByteArrayOutputStream();
GenericResponseWrapper wrapper = new GenericResponseWrapper(response, out);
Map<String, Serializable> cacheableRequestAttributes = new HashMap<String, Serializable>();
@@ -786,8 +786,8 @@ public void afterPropertiesSet() throws ServletException {
final boolean updateRequired;
final ValueWrapper valueWrapper;
- CacheStatus(Map<CacheOperationContext, Object> cUpdates, boolean updateRequired, ValueWrapper valueWrapper) {
- this.updates = cUpdates;
+ CacheStatus(Map<CacheOperationContext, Object> updates, boolean updateRequired, ValueWrapper valueWrapper) {
+ this.updates = updates;
this.updateRequired = updateRequired;
this.valueWrapper = valueWrapper;
}
Please sign in to comment.
Something went wrong with that request. Please try again.