SLING-9781 - [Sling Models] Caching doesn't work with Wrapped requests (#20)

- use original sling request when caching models adapted from a wrapped request
diff --git a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
index 5425832..c61e230 100644
--- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
+++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
@@ -365,9 +365,14 @@
             boolean isAdaptable = false;
 
             Model modelAnnotation = modelClass.getModelAnnotation();
+            Object cacheKey = adaptable;
 
             if (modelAnnotation.cache()) {
-                Map<Class<?>, SoftReference<Object>> adaptableCache = adapterCache.get(adaptable);
+                if (adaptable instanceof ServletRequestWrapper) {
+                    cacheKey = unwrapRequest((ServletRequest) adaptable);
+                }
+
+                Map<Class<?>, SoftReference<Object>> adaptableCache = adapterCache.get(cacheKey);
                 if (adaptableCache != null) {
                     SoftReference<Object> softReference = adaptableCache.get(requestedType);
                     if (softReference != null) {
@@ -399,10 +404,10 @@
                         ModelType model = (ModelType) Proxy.newProxyInstance(modelClass.getType().getClassLoader(), new Class<?>[] { modelClass.getType() }, handlerResult.getValue());
 
                         if (modelAnnotation.cache()) {
-                            Map<Class<?>, SoftReference<Object>> adaptableCache = adapterCache.get(adaptable);
+                            Map<Class<?>, SoftReference<Object>> adaptableCache = adapterCache.get(cacheKey);
                             if (adaptableCache == null) {
                                 adaptableCache = Collections.synchronizedMap(new WeakHashMap<Class<?>, SoftReference<Object>>());
-                                adapterCache.put(adaptable, adaptableCache);
+                                adapterCache.put(cacheKey, adaptableCache);
                             }
                             adaptableCache.put(requestedType, new SoftReference<Object>(model));
                         }
@@ -416,10 +421,10 @@
                         result = createObject(adaptable, modelClass);
 
                         if (result.wasSuccessful() && modelAnnotation.cache()) {
-                            Map<Class<?>, SoftReference<Object>> adaptableCache = adapterCache.get(adaptable);
+                            Map<Class<?>, SoftReference<Object>> adaptableCache = adapterCache.get(cacheKey);
                             if (adaptableCache == null) {
                                 adaptableCache = Collections.synchronizedMap(new WeakHashMap<Class<?>, SoftReference<Object>>());
-                                adapterCache.put(adaptable, adaptableCache);
+                                adapterCache.put(cacheKey, adaptableCache);
                             }
                             adaptableCache.put(requestedType, new SoftReference<Object>(result.getValue()));
                         }
diff --git a/src/test/java/org/apache/sling/models/impl/CachingTest.java b/src/test/java/org/apache/sling/models/impl/CachingTest.java
index f8d9d4a..2af2fa5 100644
--- a/src/test/java/org/apache/sling/models/impl/CachingTest.java
+++ b/src/test/java/org/apache/sling/models/impl/CachingTest.java
@@ -22,6 +22,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import javax.servlet.ServletRequestWrapper;
+
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.models.impl.injectors.RequestAttributeInjector;
 import org.apache.sling.models.testmodels.classes.CachedModel;
@@ -38,6 +40,9 @@
     @Mock
     private SlingHttpServletRequest request;
 
+    @Mock
+    private ServletRequestWrapper requestWrapper;
+
     private ModelAdapterFactory factory;
 
     @Before
@@ -48,6 +53,7 @@
                 org.apache.sling.models.testmodels.interfaces.CachedModel.class, org.apache.sling.models.testmodels.interfaces.UncachedModel.class);
 
         when(request.getAttribute("testValue")).thenReturn("test");
+        when(requestWrapper.getRequest()).thenReturn(request);
     }
 
     @Test
@@ -97,4 +103,28 @@
 
         verify(request, times(2)).getAttribute("testValue");
     }
+
+    @Test
+    public void testCachedClassWithRequestWrapper() {
+        CachedModel cached1 = factory.getAdapter(request, CachedModel.class);
+        CachedModel cached2 = factory.getAdapter(requestWrapper, CachedModel.class);
+
+        assertTrue(cached1 == cached2);
+        assertEquals("test", cached1.getTestValue());
+        assertEquals("test", cached2.getTestValue());
+
+        verify(request, times(1)).getAttribute("testValue");
+    }
+
+    @Test
+    public void testCachedInterfaceWithRequestWrapper() {
+        org.apache.sling.models.testmodels.interfaces.CachedModel cached1 = factory.getAdapter(request, org.apache.sling.models.testmodels.interfaces.CachedModel.class);
+        org.apache.sling.models.testmodels.interfaces.CachedModel cached2 = factory.getAdapter(requestWrapper, org.apache.sling.models.testmodels.interfaces.CachedModel.class);
+
+        assertTrue(cached1 == cached2);
+        assertEquals("test", cached1.getTestValue());
+        assertEquals("test", cached2.getTestValue());
+
+        verify(request, times(1)).getAttribute("testValue");
+    }
 }