You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2014/01/03 16:22:50 UTC
svn commit: r1555126 - in /sling/trunk/bundles/api/src:
main/java/org/apache/sling/api/resource/ResourceMetadata.java
test/java/org/apache/sling/api/resource/ResourceMetadataTest.java
Author: cziegeler
Date: Fri Jan 3 15:22:50 2014
New Revision: 1555126
URL: http://svn.apache.org/r1555126
Log:
SLING-2786 : ResourceMetadata contains stale unmodifiableMap cache after clone()
Modified:
sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java
sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/ResourceMetadataTest.java
Modified: sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java?rev=1555126&r1=1555125&r2=1555126&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java (original)
+++ sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceMetadata.java Fri Jan 3 15:22:50 2014
@@ -334,11 +334,20 @@ public class ResourceMetadata extends Ha
this.checkReadOnly();
return super.remove(key);
}
+
+ @Override
+ public Object clone() {
+ ResourceMetadata result = (ResourceMetadata) super.clone();
+ result.lockedEntrySet = null;
+ result.lockedKeySet = null;
+ result.lockedValues = null;
+ return result;
+ }
- // volatile for correct double-checked locking in getLockedData()
- private volatile Set<Map.Entry<String, Object>> lockedEntrySet;
- private Set<String> lockedKeySet;
- private Collection<Object> lockedValues;
+ // volatile for correct double-checked locking in getLockedData()
+ private transient volatile Set<Map.Entry<String, Object>> lockedEntrySet;
+ private transient Set<String> lockedKeySet;
+ private transient Collection<Object> lockedValues;
private void getLockedData() {
if(isReadOnly && lockedEntrySet == null) {
Modified: sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/ResourceMetadataTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/ResourceMetadataTest.java?rev=1555126&r1=1555125&r2=1555126&view=diff
==============================================================================
--- sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/ResourceMetadataTest.java (original)
+++ sling/trunk/bundles/api/src/test/java/org/apache/sling/api/resource/ResourceMetadataTest.java Fri Jan 3 15:22:50 2014
@@ -18,21 +18,28 @@
*/
package org.apache.sling.api.resource;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.fail;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
import org.junit.Test;
public class ResourceMetadataTest {
-
+
private static final Map<String, Object> TEST_MAP = new HashMap<String, Object>();
static {
TEST_MAP.put("first", "one");
TEST_MAP.put("second", Integer.MAX_VALUE);
}
-
+
@Test
public void testLockedPut() {
final ResourceMetadata m = new ResourceMetadata();
@@ -44,7 +51,7 @@ public class ResourceMetadataTest {
// all good
}
}
-
+
@Test
public void testLockedClear() {
final ResourceMetadata m = new ResourceMetadata();
@@ -56,7 +63,7 @@ public class ResourceMetadataTest {
// all good
}
}
-
+
@Test
public void testLockedPutAll() {
final ResourceMetadata m = new ResourceMetadata();
@@ -68,7 +75,7 @@ public class ResourceMetadataTest {
// all good
}
}
-
+
@Test
public void testLockedRemove() {
final ResourceMetadata m = new ResourceMetadata();
@@ -80,25 +87,76 @@ public class ResourceMetadataTest {
// all good
}
}
-
+
@Test
public void testLockedEntrySet() {
final ResourceMetadata m = new ResourceMetadata();
m.lock();
m.entrySet().toString();
}
-
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLockedEntrySetRemove() {
+ final ResourceMetadata m = new ResourceMetadata();
+ m.put("key", "value");
+ m.lock();
+ Set<Entry<String, Object>> values = m.entrySet();
+ Iterator<Entry<String, Object>> it = values.iterator();
+ it.next();
+ it.remove();
+ }
+
@Test
public void testLockedKeySet() {
final ResourceMetadata m = new ResourceMetadata();
m.lock();
m.keySet().toString();
}
-
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLockedKeySetRemove() {
+ final ResourceMetadata m = new ResourceMetadata();
+ m.put("key", "value");
+ m.lock();
+ Set<String> keys = m.keySet();
+ keys.remove("key1");
+ }
+
@Test
public void testLockedValues() {
final ResourceMetadata m = new ResourceMetadata();
m.lock();
m.values().toString();
}
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testLockedValuesRemove() {
+ final ResourceMetadata m = new ResourceMetadata();
+ m.put("key", "value");
+ m.lock();
+ Collection<Object> values = m.values();
+ values.remove("value");
+ }
+
+ @Test
+ public void testLockedClone() {
+ final ResourceMetadata m1 = new ResourceMetadata();
+ m1.put("key", "value");
+ m1.lock();
+
+ // Force caching of the internal views
+ m1.keySet();
+ final ResourceMetadata m2 = (ResourceMetadata) m1.clone();
+
+ assertNotSame(m1, m2);
+ assertEquals(m1, m2);
+ assertNotSame(m1.keySet(), m2.keySet());
+ assertEquals(m1.keySet(), m2.keySet());
+ assertNotSame(m1.entrySet(), m2.entrySet());
+ assertEquals(m1.entrySet(), m2.entrySet());
+ assertNotSame(m1.values(), m2.values());
+
+ // Collections.UnmodifiableCollection doesn't implement equals()
+ assertEquals(new ArrayList<Object>(m1.values()), new ArrayList<Object>(m2.values()));
+ }
}