1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.http.impl.client.cache;
28
29 import static org.junit.Assert.assertFalse;
30 import static org.junit.Assert.assertTrue;
31
32 import java.io.ByteArrayInputStream;
33 import java.io.ByteArrayOutputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.io.ObjectOutputStream;
37 import java.nio.charset.Charset;
38 import java.util.Arrays;
39 import java.util.Date;
40 import java.util.HashMap;
41 import java.util.Map;
42
43 import org.apache.commons.codec.binary.Base64;
44 import org.apache.http.Header;
45 import org.apache.http.ProtocolVersion;
46 import org.apache.http.StatusLine;
47 import org.apache.http.client.cache.HeaderConstants;
48 import org.apache.http.client.cache.HttpCacheEntry;
49 import org.apache.http.client.cache.HttpCacheEntrySerializationException;
50 import org.apache.http.client.cache.HttpCacheEntrySerializer;
51 import org.apache.http.client.cache.Resource;
52 import org.apache.http.message.BasicHeader;
53 import org.apache.http.message.BasicStatusLine;
54 import org.junit.Before;
55 import org.junit.Test;
56
57 import com.sun.rowset.JdbcRowSetImpl;
58
59 public class TestHttpCacheEntrySerializers {
60
61 private static final Charset UTF8 = Charset.forName("UTF-8");
62
63 private HttpCacheEntrySerializer impl;
64
65 @Before
66 public void setUp() {
67 impl = new DefaultHttpCacheEntrySerializer();
68 }
69
70 @Test
71 public void canSerializeEntriesWithVariantMaps() throws Exception {
72 readWriteVerify(makeCacheEntryWithVariantMap());
73 }
74
75 @Test
76 public void isAllowedClassNameStringTrue() {
77 assertIsAllowedClassNameTrue(String.class.getName());
78 }
79
80 @Test
81 public void isAllowedClassNameStringArrayTrue() {
82 assertIsAllowedClassNameTrue("[L" + String.class.getName());
83 }
84
85 @Test
86 public void isAllowedClassNameStringArrayArrayTrue() {
87 assertIsAllowedClassNameTrue("[[L" + String.class.getName());
88 }
89
90 @Test
91 public void isAllowedClassNameDataTrue() {
92 assertIsAllowedClassNameTrue(Date.class.getName());
93 }
94
95 @Test
96 public void isAllowedClassNameStatusLineTrue() {
97 assertIsAllowedClassNameTrue(StatusLine.class.getName());
98 }
99
100 @Test
101 public void isAllowedClassNameResourceTrue() {
102 assertIsAllowedClassNameTrue(Resource.class.getName());
103 }
104
105 @Test
106 public void isAllowedClassNameByteArrayTrue() {
107 assertIsAllowedClassNameTrue("[B");
108 }
109
110 @Test
111 public void isAllowedClassNameByteArrayArrayTrue() {
112 assertIsAllowedClassNameTrue("[[B");
113 }
114
115 @Test
116 public void isAllowedClassNameCharArrayTrue() {
117 assertIsAllowedClassNameTrue("[C");
118 }
119
120 @Test
121 public void isAllowedClassNameCharArrayArrayTrue() {
122 assertIsAllowedClassNameTrue("[[C");
123 }
124
125 @Test
126 public void isAllowedClassNameDoubleArrayTrue() {
127 assertIsAllowedClassNameTrue("[D");
128 }
129
130 @Test
131 public void isAllowedClassNameDoubleArrayArrayTrue() {
132 assertIsAllowedClassNameTrue("[[D");
133 }
134
135 @Test
136 public void isAllowedClassNameFloatArrayTrue() {
137 assertIsAllowedClassNameTrue("[F");
138 }
139
140 @Test
141 public void isAllowedClassNameFloatArrayArrayTrue() {
142 assertIsAllowedClassNameTrue("[[F");
143 }
144
145 @Test
146 public void isAllowedClassNameIntArrayTrue() {
147 assertIsAllowedClassNameTrue("[I");
148 }
149
150 @Test
151 public void isAllowedClassNameIntArrayArrayTrue() {
152 assertIsAllowedClassNameTrue("[[I");
153 }
154
155 @Test
156 public void isAllowedClassNameLongArrayTrue() {
157 assertIsAllowedClassNameTrue("[J");
158 }
159
160 @Test
161 public void isAllowedClassNameLongArrayArrayTrue() {
162 assertIsAllowedClassNameTrue("[[J");
163 }
164
165 @Test
166 public void isAllowedClassNameShortArrayTrue() {
167 assertIsAllowedClassNameTrue("[S");
168 }
169
170 @Test
171 public void isAllowedClassNameShortArrayArrayTrue() {
172 assertIsAllowedClassNameTrue("[[S");
173 }
174
175 @Test
176 public void isAllowedClassNameCollectionsInvokerTransformerFalse() {
177 assertIsAllowedClassNameFalse("org.apache.commons.collections.functors.InvokerTransformer");
178 }
179
180 @Test
181 public void isAllowedClassNameCollections4InvokerTransformerFalse() {
182 assertIsAllowedClassNameFalse("org.apache.commons.collections4.functors.InvokerTransformer");
183 }
184
185 @Test
186 public void isAllowedClassNameCollectionsInstantiateTransformerFalse() {
187 assertIsAllowedClassNameFalse("org.apache.commons.collections.functors.InstantiateTransformer");
188 }
189
190 @Test
191 public void isAllowedClassNameCollections4InstantiateTransformerFalse() {
192 assertIsAllowedClassNameFalse("org.apache.commons.collections4.functors.InstantiateTransformer");
193 }
194
195 @Test
196 public void isAllowedClassNameGroovyConvertedClosureFalse() {
197 assertIsAllowedClassNameFalse("org.codehaus.groovy.runtime.ConvertedClosure");
198 }
199
200 @Test
201 public void isAllowedClassNameGroovyMethodClosureFalse() {
202 assertIsAllowedClassNameFalse("org.codehaus.groovy.runtime.MethodClosure");
203 }
204
205 @Test
206 public void isAllowedClassNameSpringObjectFactoryFalse() {
207 assertIsAllowedClassNameFalse("org.springframework.beans.factory.ObjectFactory");
208 }
209
210 @Test
211 public void isAllowedClassNameCalanTemplatesImplFalse() {
212 assertIsAllowedClassNameFalse("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
213 }
214
215 @Test
216 public void isAllowedClassNameCalanTemplatesImplArrayFalse() {
217 assertIsAllowedClassNameFalse("[Lcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
218 }
219
220 @Test
221 public void isAllowedClassNameJavaRmiRegistryFalse() {
222 assertIsAllowedClassNameFalse("java.rmi.registry.Registry");
223 }
224
225 @Test
226 public void isAllowedClassNameJavaRmiServerRemoteObjectInvocationHandlerFalse() {
227 assertIsAllowedClassNameFalse("java.rmi.server.RemoteObjectInvocationHandler");
228 }
229
230 @Test
231 public void isAllowedClassNameJavaxXmlTransformTemplatesFalse() {
232 assertIsAllowedClassNameFalse("javax.xml.transform.Templates");
233 }
234
235 @Test
236 public void isAllowedClassNameJavaxManagementMBeanServerInvocationHandlerFalse() {
237 assertIsAllowedClassNameFalse("javax.management.MBeanServerInvocationHandler");
238 }
239
240 private static void assertIsAllowedClassNameTrue(final String className) {
241 assertTrue(DefaultHttpCacheEntrySerializer.RestrictedObjectInputStream.isAllowedClassName(className));
242 }
243
244 private static void assertIsAllowedClassNameFalse(final String className) {
245 assertFalse(DefaultHttpCacheEntrySerializer.RestrictedObjectInputStream.isAllowedClassName(className));
246 }
247
248 @Test(expected = HttpCacheEntrySerializationException.class)
249 public void throwExceptionIfUnsafeDeserialization() throws IOException {
250 impl.readFrom(new ByteArrayInputStream(serializeProhibitedObject()));
251 }
252
253 private byte[] serializeProhibitedObject() throws IOException {
254 final JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
255 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
256 final ObjectOutputStream oos = new ObjectOutputStream(baos);
257 try {
258 oos.writeObject(jdbcRowSet);
259 } finally {
260 oos.close();
261 }
262 return baos.toByteArray();
263 }
264
265 private void readWriteVerify(final HttpCacheEntry writeEntry) throws IOException {
266
267 final ByteArrayOutputStream out = new ByteArrayOutputStream();
268 impl.writeTo(writeEntry, out);
269
270
271 final ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
272 final HttpCacheEntry readEntry = impl.readFrom(in);
273
274
275 assertTrue(areEqual(readEntry, writeEntry));
276 }
277
278 private HttpCacheEntry makeCacheEntryWithVariantMap() {
279 final Header[] headers = new Header[5];
280 for (int i = 0; i < headers.length; i++) {
281 headers[i] = new BasicHeader("header" + i, "value" + i);
282 }
283 final String body = "Lorem ipsum dolor sit amet";
284
285 final ProtocolVersion pvObj = new ProtocolVersion("HTTP", 1, 1);
286 final StatusLine slObj = new BasicStatusLine(pvObj, 200, "ok");
287 final Map<String,String> variantMap = new HashMap<String,String>();
288 variantMap.put("test variant 1","true");
289 variantMap.put("test variant 2","true");
290 final HttpCacheEntry cacheEntry = new HttpCacheEntry(new Date(), new Date(),
291 slObj, headers, new HeapResource(Base64.decodeBase64(body
292 .getBytes(UTF8))), variantMap, HeaderConstants.GET_METHOD);
293
294 return cacheEntry;
295 }
296
297 private boolean areEqual(final HttpCacheEntry one, final HttpCacheEntry two) throws IOException {
298
299 if (!((one.getRequestDate().getTime() / 1000) == (two.getRequestDate()
300 .getTime() / 1000))) {
301 return false;
302 }
303 if (!((one.getResponseDate().getTime() / 1000) == (two
304 .getResponseDate().getTime() / 1000))) {
305 return false;
306 }
307 if (!one.getProtocolVersion().equals(two.getProtocolVersion())) {
308 return false;
309 }
310
311 final byte[] onesByteArray = resourceToBytes(one.getResource());
312 final byte[] twosByteArray = resourceToBytes(two.getResource());
313
314 if (!Arrays.equals(onesByteArray,twosByteArray)) {
315 return false;
316 }
317
318 final Header[] oneHeaders = one.getAllHeaders();
319 final Header[] twoHeaders = two.getAllHeaders();
320 if (!(oneHeaders.length == twoHeaders.length)) {
321 return false;
322 }
323 for (int i = 0; i < oneHeaders.length; i++) {
324 if (!oneHeaders[i].getName().equals(twoHeaders[i].getName())) {
325 return false;
326 }
327 if (!oneHeaders[i].getValue().equals(twoHeaders[i].getValue())) {
328 return false;
329 }
330 }
331
332 return true;
333 }
334
335 private byte[] resourceToBytes(final Resource res) throws IOException {
336 final InputStream inputStream = res.getInputStream();
337 final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
338
339 int readBytes;
340 final byte[] bytes = new byte[8096];
341 while ((readBytes = inputStream.read(bytes)) > 0) {
342 outputStream.write(bytes, 0, readBytes);
343 }
344
345 final byte[] byteData = outputStream.toByteArray();
346
347 inputStream.close();
348 outputStream.close();
349
350 return byteData;
351 }
352 }