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  public class TestByteArrayCacheEntrySerializer {
56  
57      private ByteArrayCacheEntrySerializer impl;
58  
59      @BeforeEach
60      public void setUp() {
61          impl = new ByteArrayCacheEntrySerializer();
62      }
63  
64      @Test
65      public void canSerializeEntriesWithVariantMapsDeprecatedConstructor() throws Exception {
66          readWriteVerify(makeCacheEntryDeprecatedConstructorWithVariantMap("somekey"));
67      }
68  
69      @Test
70      public void canSerializeEntriesWithVariantMapsAndInstant() throws Exception {
71          readWriteVerify(makeCacheEntryWithVariantMap("somekey"));
72      }
73  
74      @Test
75      public void isAllowedClassNameStringTrue() {
76          assertIsAllowedClassNameTrue(String.class.getName());
77      }
78  
79      @Test
80      public void isAllowedClassNameStringArrayTrue() {
81          assertIsAllowedClassNameTrue("[L" + String.class.getName());
82      }
83  
84      @Test
85      public void isAllowedClassNameStringArrayArrayTrue() {
86          assertIsAllowedClassNameTrue("[[L" + String.class.getName());
87      }
88  
89      @Test
90      public void isAllowedClassNameDataTrue() {
91          assertIsAllowedClassNameTrue(Date.class.getName());
92      }
93  
94      @Test
95      public void isAllowedClassNameInstantTrue() {
96          assertIsAllowedClassNameTrue(Instant.class.getName());
97      }
98  
99      @Test
100     public void isAllowedClassNameStatusLineTrue() {
101         assertIsAllowedClassNameTrue(StatusLine.class.getName());
102     }
103 
104     @Test
105     public void isAllowedClassNameResourceTrue() {
106         assertIsAllowedClassNameTrue(Resource.class.getName());
107     }
108 
109     @Test
110     public void isAllowedClassNameByteArrayTrue() {
111         assertIsAllowedClassNameTrue("[B");
112     }
113 
114     @Test
115     public void isAllowedClassNameByteArrayArrayTrue() {
116         assertIsAllowedClassNameTrue("[[B");
117     }
118 
119     @Test
120     public void isAllowedClassNameCharArrayTrue() {
121         assertIsAllowedClassNameTrue("[C");
122     }
123 
124     @Test
125     public void isAllowedClassNameCharArrayArrayTrue() {
126         assertIsAllowedClassNameTrue("[[C");
127     }
128 
129     @Test
130     public void isAllowedClassNameDoubleArrayTrue() {
131         assertIsAllowedClassNameTrue("[D");
132     }
133 
134     @Test
135     public void isAllowedClassNameDoubleArrayArrayTrue() {
136         assertIsAllowedClassNameTrue("[[D");
137     }
138 
139     @Test
140     public void isAllowedClassNameFloatArrayTrue() {
141         assertIsAllowedClassNameTrue("[F");
142     }
143 
144     @Test
145     public void isAllowedClassNameFloatArrayArrayTrue() {
146         assertIsAllowedClassNameTrue("[[F");
147     }
148 
149     @Test
150     public void isAllowedClassNameIntArrayTrue() {
151         assertIsAllowedClassNameTrue("[I");
152     }
153 
154     @Test
155     public void isAllowedClassNameIntArrayArrayTrue() {
156         assertIsAllowedClassNameTrue("[[I");
157     }
158 
159     @Test
160     public void isAllowedClassNameLongArrayTrue() {
161         assertIsAllowedClassNameTrue("[J");
162     }
163 
164     @Test
165     public void isAllowedClassNameLongArrayArrayTrue() {
166         assertIsAllowedClassNameTrue("[[J");
167     }
168 
169     @Test
170     public void isAllowedClassNameShortArrayTrue() {
171         assertIsAllowedClassNameTrue("[S");
172     }
173 
174     @Test
175     public void isAllowedClassNameShortArrayArrayTrue() {
176         assertIsAllowedClassNameTrue("[[S");
177     }
178 
179     @Test
180     public void isAllowedClassNameCollectionsInvokerTransformerFalse() {
181         assertIsAllowedClassNameFalse("org.apache.commons.collections.functors.InvokerTransformer");
182     }
183 
184     @Test
185     public void isAllowedClassNameCollections4InvokerTransformerFalse() {
186         assertIsAllowedClassNameFalse("org.apache.commons.collections4.functors.InvokerTransformer");
187     }
188 
189     @Test
190     public void isAllowedClassNameCollectionsInstantiateTransformerFalse() {
191         assertIsAllowedClassNameFalse("org.apache.commons.collections.functors.InstantiateTransformer");
192     }
193 
194     @Test
195     public void isAllowedClassNameCollections4InstantiateTransformerFalse() {
196         assertIsAllowedClassNameFalse("org.apache.commons.collections4.functors.InstantiateTransformer");
197     }
198 
199     @Test
200     public void isAllowedClassNameGroovyConvertedClosureFalse() {
201         assertIsAllowedClassNameFalse("org.codehaus.groovy.runtime.ConvertedClosure");
202     }
203 
204     @Test
205     public void isAllowedClassNameGroovyMethodClosureFalse() {
206         assertIsAllowedClassNameFalse("org.codehaus.groovy.runtime.MethodClosure");
207     }
208 
209     @Test
210     public void isAllowedClassNameSpringObjectFactoryFalse() {
211         assertIsAllowedClassNameFalse("org.springframework.beans.factory.ObjectFactory");
212     }
213 
214     @Test
215     public void isAllowedClassNameCalanTemplatesImplFalse() {
216         assertIsAllowedClassNameFalse("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
217     }
218 
219     @Test
220     public void isAllowedClassNameCalanTemplatesImplArrayFalse() {
221         assertIsAllowedClassNameFalse("[Lcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
222     }
223 
224     @Test
225     public void isAllowedClassNameJavaRmiRegistryFalse() {
226         assertIsAllowedClassNameFalse("java.rmi.registry.Registry");
227     }
228 
229     @Test
230     public void isAllowedClassNameJavaRmiServerRemoteObjectInvocationHandlerFalse() {
231         assertIsAllowedClassNameFalse("java.rmi.server.RemoteObjectInvocationHandler");
232     }
233 
234     @Test
235     public void isAllowedClassNameJavaxXmlTransformTemplatesFalse() {
236         assertIsAllowedClassNameFalse("javax.xml.transform.Templates");
237     }
238 
239     @Test
240     public void isAllowedClassNameJavaxManagementMBeanServerInvocationHandlerFalse() {
241         assertIsAllowedClassNameFalse("javax.management.MBeanServerInvocationHandler");
242     }
243 
244     private static void assertIsAllowedClassNameTrue(final String className) {
245         assertTrue(ByteArrayCacheEntrySerializer.RestrictedObjectInputStream.isAllowedClassName(className));
246     }
247 
248     private static void assertIsAllowedClassNameFalse(final String className) {
249         assertFalse(ByteArrayCacheEntrySerializer.RestrictedObjectInputStream.isAllowedClassName(className));
250     }
251 
252     private byte[] serializeProhibitedObject() throws IOException {
253         final BigDecimal bigDecimal = new BigDecimal("1000.00");
254         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
255         try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
256             oos.writeObject(bigDecimal);
257         }
258         return baos.toByteArray();
259     }
260 
261     public void readWriteVerify(final HttpCacheStorageEntry writeEntry) throws Exception {
262         // write the entry
263         final byte[] bytes = impl.serialize(writeEntry);
264         // read the entry
265         final HttpCacheStorageEntry readEntry = impl.deserialize(bytes);
266         // compare
267         assertEquals(readEntry.getKey(), writeEntry.getKey());
268         assertThat(readEntry.getContent(), HttpCacheEntryMatcher.equivalent(writeEntry.getContent()));
269     }
270 
271 
272     private HttpCacheStorageEntry makeCacheEntryDeprecatedConstructorWithVariantMap(final String key) {
273         final Header[] headers = new Header[5];
274         for (int i = 0; i < headers.length; i++) {
275             headers[i] = new BasicHeader("header" + i, "value" + i);
276         }
277         final String body = "Lorem ipsum dolor sit amet";
278 
279         final Map<String,String> variantMap = new HashMap<>();
280         variantMap.put("test variant 1","true");
281         variantMap.put("test variant 2","true");
282         final HttpCacheEntry cacheEntry = new HttpCacheEntry(
283                 Instant.now(),
284                 Instant.now(),
285                 HttpStatus.SC_OK,
286                 headers,
287                 new HeapResource(body.getBytes(StandardCharsets.UTF_8)), variantMap);
288 
289         return new HttpCacheStorageEntry(key, cacheEntry);
290     }
291 
292     private HttpCacheStorageEntry makeCacheEntryWithVariantMap(final String key) {
293         final Header[] headers = new Header[5];
294         for (int i = 0; i < headers.length; i++) {
295             headers[i] = new BasicHeader("header" + i, "value" + i);
296         }
297         final String body = "Lorem ipsum dolor sit amet";
298 
299         final Map<String,String> variantMap = new HashMap<>();
300         variantMap.put("test variant 1","true");
301         variantMap.put("test variant 2","true");
302         final HttpCacheEntry cacheEntry = new HttpCacheEntry(
303                 Instant.now(),
304                 Instant.now(),
305                 HttpStatus.SC_OK,
306                 headers,
307                 new HeapResource(body.getBytes(StandardCharsets.UTF_8)), variantMap);
308 
309         return new HttpCacheStorageEntry(key, cacheEntry);
310     }
311 
312 }