View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.client5.http.impl.cache;
28  
29  
30  import static org.hamcrest.MatcherAssert.assertThat;
31  import static org.junit.jupiter.api.Assertions.assertEquals;
32  import static org.junit.jupiter.api.Assertions.assertFalse;
33  import static org.junit.jupiter.api.Assertions.assertTrue;
34  
35  import java.io.ByteArrayOutputStream;
36  import java.io.IOException;
37  import java.io.ObjectOutputStream;
38  import java.math.BigDecimal;
39  import java.nio.charset.StandardCharsets;
40  import java.time.Instant;
41  import java.util.Date;
42  import java.util.HashMap;
43  import java.util.Map;
44  
45  import org.apache.hc.client5.http.cache.HttpCacheEntry;
46  import org.apache.hc.client5.http.cache.HttpCacheStorageEntry;
47  import org.apache.hc.client5.http.cache.Resource;
48  import org.apache.hc.core5.http.Header;
49  import org.apache.hc.core5.http.HttpStatus;
50  import org.apache.hc.core5.http.message.BasicHeader;
51  import org.apache.hc.core5.http.message.StatusLine;
52  import org.junit.jupiter.api.BeforeEach;
53  import org.junit.jupiter.api.Test;
54  
55  @SuppressWarnings("deprecation")
56  public class TestByteArrayCacheEntrySerializer {
57  
58      private ByteArrayCacheEntrySerializer impl;
59  
60      @BeforeEach
61      public void setUp() {
62          impl = new ByteArrayCacheEntrySerializer();
63      }
64  
65      @Test
66      public void canSerializeEntriesWithVariantMapsDeprecatedConstructor() throws Exception {
67          readWriteVerify(makeCacheEntryDeprecatedConstructorWithVariantMap("somekey"));
68      }
69  
70      @Test
71      public void canSerializeEntriesWithVariantMapsAndInstant() throws Exception {
72          readWriteVerify(makeCacheEntryWithVariantMap("somekey"));
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 isAllowedClassNameInstantTrue() {
97          assertIsAllowedClassNameTrue(Instant.class.getName());
98      }
99  
100     @Test
101     public void isAllowedClassNameStatusLineTrue() {
102         assertIsAllowedClassNameTrue(StatusLine.class.getName());
103     }
104 
105     @Test
106     public void isAllowedClassNameResourceTrue() {
107         assertIsAllowedClassNameTrue(Resource.class.getName());
108     }
109 
110     @Test
111     public void isAllowedClassNameByteArrayTrue() {
112         assertIsAllowedClassNameTrue("[B");
113     }
114 
115     @Test
116     public void isAllowedClassNameByteArrayArrayTrue() {
117         assertIsAllowedClassNameTrue("[[B");
118     }
119 
120     @Test
121     public void isAllowedClassNameCharArrayTrue() {
122         assertIsAllowedClassNameTrue("[C");
123     }
124 
125     @Test
126     public void isAllowedClassNameCharArrayArrayTrue() {
127         assertIsAllowedClassNameTrue("[[C");
128     }
129 
130     @Test
131     public void isAllowedClassNameDoubleArrayTrue() {
132         assertIsAllowedClassNameTrue("[D");
133     }
134 
135     @Test
136     public void isAllowedClassNameDoubleArrayArrayTrue() {
137         assertIsAllowedClassNameTrue("[[D");
138     }
139 
140     @Test
141     public void isAllowedClassNameFloatArrayTrue() {
142         assertIsAllowedClassNameTrue("[F");
143     }
144 
145     @Test
146     public void isAllowedClassNameFloatArrayArrayTrue() {
147         assertIsAllowedClassNameTrue("[[F");
148     }
149 
150     @Test
151     public void isAllowedClassNameIntArrayTrue() {
152         assertIsAllowedClassNameTrue("[I");
153     }
154 
155     @Test
156     public void isAllowedClassNameIntArrayArrayTrue() {
157         assertIsAllowedClassNameTrue("[[I");
158     }
159 
160     @Test
161     public void isAllowedClassNameLongArrayTrue() {
162         assertIsAllowedClassNameTrue("[J");
163     }
164 
165     @Test
166     public void isAllowedClassNameLongArrayArrayTrue() {
167         assertIsAllowedClassNameTrue("[[J");
168     }
169 
170     @Test
171     public void isAllowedClassNameShortArrayTrue() {
172         assertIsAllowedClassNameTrue("[S");
173     }
174 
175     @Test
176     public void isAllowedClassNameShortArrayArrayTrue() {
177         assertIsAllowedClassNameTrue("[[S");
178     }
179 
180     @Test
181     public void isAllowedClassNameCollectionsInvokerTransformerFalse() {
182         assertIsAllowedClassNameFalse("org.apache.commons.collections.functors.InvokerTransformer");
183     }
184 
185     @Test
186     public void isAllowedClassNameCollections4InvokerTransformerFalse() {
187         assertIsAllowedClassNameFalse("org.apache.commons.collections4.functors.InvokerTransformer");
188     }
189 
190     @Test
191     public void isAllowedClassNameCollectionsInstantiateTransformerFalse() {
192         assertIsAllowedClassNameFalse("org.apache.commons.collections.functors.InstantiateTransformer");
193     }
194 
195     @Test
196     public void isAllowedClassNameCollections4InstantiateTransformerFalse() {
197         assertIsAllowedClassNameFalse("org.apache.commons.collections4.functors.InstantiateTransformer");
198     }
199 
200     @Test
201     public void isAllowedClassNameGroovyConvertedClosureFalse() {
202         assertIsAllowedClassNameFalse("org.codehaus.groovy.runtime.ConvertedClosure");
203     }
204 
205     @Test
206     public void isAllowedClassNameGroovyMethodClosureFalse() {
207         assertIsAllowedClassNameFalse("org.codehaus.groovy.runtime.MethodClosure");
208     }
209 
210     @Test
211     public void isAllowedClassNameSpringObjectFactoryFalse() {
212         assertIsAllowedClassNameFalse("org.springframework.beans.factory.ObjectFactory");
213     }
214 
215     @Test
216     public void isAllowedClassNameCalanTemplatesImplFalse() {
217         assertIsAllowedClassNameFalse("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
218     }
219 
220     @Test
221     public void isAllowedClassNameCalanTemplatesImplArrayFalse() {
222         assertIsAllowedClassNameFalse("[Lcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
223     }
224 
225     @Test
226     public void isAllowedClassNameJavaRmiRegistryFalse() {
227         assertIsAllowedClassNameFalse("java.rmi.registry.Registry");
228     }
229 
230     @Test
231     public void isAllowedClassNameJavaRmiServerRemoteObjectInvocationHandlerFalse() {
232         assertIsAllowedClassNameFalse("java.rmi.server.RemoteObjectInvocationHandler");
233     }
234 
235     @Test
236     public void isAllowedClassNameJavaxXmlTransformTemplatesFalse() {
237         assertIsAllowedClassNameFalse("javax.xml.transform.Templates");
238     }
239 
240     @Test
241     public void isAllowedClassNameJavaxManagementMBeanServerInvocationHandlerFalse() {
242         assertIsAllowedClassNameFalse("javax.management.MBeanServerInvocationHandler");
243     }
244 
245     private static void assertIsAllowedClassNameTrue(final String className) {
246         assertTrue(ByteArrayCacheEntrySerializer.RestrictedObjectInputStream.isAllowedClassName(className));
247     }
248 
249     private static void assertIsAllowedClassNameFalse(final String className) {
250         assertFalse(ByteArrayCacheEntrySerializer.RestrictedObjectInputStream.isAllowedClassName(className));
251     }
252 
253     private byte[] serializeProhibitedObject() throws IOException {
254         final BigDecimal bigDecimal = new BigDecimal("1000.00");
255         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
256         try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
257             oos.writeObject(bigDecimal);
258         }
259         return baos.toByteArray();
260     }
261 
262     public void readWriteVerify(final HttpCacheStorageEntry writeEntry) throws Exception {
263         // write the entry
264         final byte[] bytes = impl.serialize(writeEntry);
265         // read the entry
266         final HttpCacheStorageEntry readEntry = impl.deserialize(bytes);
267         // compare
268         assertEquals(readEntry.getKey(), writeEntry.getKey());
269         assertThat(readEntry.getContent(), HttpCacheEntryMatcher.equivalent(writeEntry.getContent()));
270     }
271 
272 
273     private HttpCacheStorageEntry makeCacheEntryDeprecatedConstructorWithVariantMap(final String key) {
274         final Header[] headers = new Header[5];
275         for (int i = 0; i < headers.length; i++) {
276             headers[i] = new BasicHeader("header" + i, "value" + i);
277         }
278         final String body = "Lorem ipsum dolor sit amet";
279 
280         final Map<String,String> variantMap = new HashMap<>();
281         variantMap.put("test variant 1","true");
282         variantMap.put("test variant 2","true");
283         final HttpCacheEntry cacheEntry = new HttpCacheEntry(
284                 Instant.now(),
285                 Instant.now(),
286                 HttpStatus.SC_OK,
287                 headers,
288                 new HeapResource(body.getBytes(StandardCharsets.UTF_8)), variantMap);
289 
290         return new HttpCacheStorageEntry(key, cacheEntry);
291     }
292 
293     private HttpCacheStorageEntry makeCacheEntryWithVariantMap(final String key) {
294         final Header[] headers = new Header[5];
295         for (int i = 0; i < headers.length; i++) {
296             headers[i] = new BasicHeader("header" + i, "value" + i);
297         }
298         final String body = "Lorem ipsum dolor sit amet";
299 
300         final Map<String,String> variantMap = new HashMap<>();
301         variantMap.put("test variant 1","true");
302         variantMap.put("test variant 2","true");
303         final HttpCacheEntry cacheEntry = new HttpCacheEntry(
304                 Instant.now(),
305                 Instant.now(),
306                 HttpStatus.SC_OK,
307                 headers,
308                 new HeapResource(body.getBytes(StandardCharsets.UTF_8)), variantMap);
309 
310         return new HttpCacheStorageEntry(key, cacheEntry);
311     }
312 
313 }