Author: jason.greene(a)jboss.com
Date: 2008-01-16 17:46:23 -0500 (Wed, 16 Jan 2008)
New Revision: 5153
Modified:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/CachedType.java
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java
pojo/branches/2.1/src/main/resources/META-INF/pojocache-aop.xml
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/LocalTest.java
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/ReplicatedTest.java
pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/test/Person.java
Log:
Merge 4857 and 4858
Modified:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java
===================================================================
---
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java 2008-01-16
22:36:22 UTC (rev 5152)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/AdvisedPojoHandler.java 2008-01-16
22:46:23 UTC (rev 5153)
@@ -26,6 +26,7 @@
import org.jboss.cache.pojo.memory.FieldPersistentReference;
import org.jboss.cache.pojo.util.AopUtil;
import org.jboss.cache.pojo.util.Instantiator;
+import org.jboss.cache.pojo.util.ObjectUtil;
/**
* Handling the advised pojo operations. No consideration of object graph here.
@@ -49,14 +50,33 @@
util_ = util;
}
- public Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance)
- throws CacheException
+ public Object get(Fqn<?> fqn, Class<?> clazz, PojoInstance pojoInstance)
throws CacheException
{
CachedType type = pCache_.getCachedType(clazz);
- Object obj =Instantiator.newInstance(clazz);
+ Object obj = Instantiator.newInstance(clazz);
+
+ // Eager initialize final fields, since these may not be intercepted
+
+ try
+ {
+ for (FieldPersistentReference ref : type.getFinalFields())
+ {
+ Field field = ref.getField();
+ Object result;
+
+ if (CachedType.isSimpleAttribute(field))
+ result = cache_.get(fqn, field.getName());
+ else
+ result = pCache_.getObject(fqn, field.getName());
+
+ field.set(obj, result);
+ }
+ }
+ catch (Exception e)
+ {
+ log.warn("Could not initialize final fields on object: " +
ObjectUtil.identityString(obj));
+ }
- // TODO Need to populate the object from the cache as well.
- // Insert interceptor at runtime
InstanceAdvisor advisor = ((Advised) obj)._getInstanceAdvisor();
CacheFieldInterceptor interceptor = new CacheFieldInterceptor(pCache_, fqn, type);
interceptor.setAopInstance(pojoInstance);
Modified: pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/CachedType.java
===================================================================
--- pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/CachedType.java 2008-01-16
22:36:22 UTC (rev 5152)
+++ pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/impl/CachedType.java 2008-01-16
22:46:23 UTC (rev 5153)
@@ -31,8 +31,8 @@
public class CachedType
{
// Types that are considered "primitive".
- private static final Set immediates =
- new HashSet(Arrays.asList(new Object[]{
+ private static final Set<Object> immediates =
+ new HashSet<Object>(Arrays.asList(new Object[]{
String.class,
Boolean.class,
Double.class,
@@ -57,8 +57,9 @@
private boolean immediate;
// Java fields . Will use special FieldPersistentReference to prevent classloader
leakage.
- private List fields = new ArrayList();
- private Map fieldMap = new HashMap();// Name -> CachedAttribute
+ private List<FieldPersistentReference> fields = new
ArrayList<FieldPersistentReference>();
+ private List<FieldPersistentReference> finalFields = new
ArrayList<FieldPersistentReference>();
+ private Map<String, FieldPersistentReference> fieldMap = new HashMap<String,
FieldPersistentReference>();// Name -> CachedAttribute
public CachedType()
{
@@ -92,14 +93,19 @@
return immutable;
}
- public List getFields()
+ public List<FieldPersistentReference> getFields()
{
return fields;
}
+
+ public List<FieldPersistentReference> getFinalFields()
+ {
+ return finalFields;
+ }
public Field getField(String name)
{
- FieldPersistentReference ref = (FieldPersistentReference) fieldMap.get(name);
+ FieldPersistentReference ref = fieldMap.get(name);
if (ref == null) return null;
return (Field) ref.get();
}
@@ -209,7 +215,7 @@
for (int i = 0; i < classFields.length; i++)
{
Field f = classFields[i];
- if (isNonReplicatable(f)) continue;
+ if (isNonReplicable(f)) continue;
PrivilegedCode.setAccessible(f);
@@ -217,17 +223,20 @@
fields.add(persistentRef);
fieldMap.put(f.getName(), persistentRef);
+
+ if (Modifier.isFinal(f.getModifiers()))
+ finalFields.add(persistentRef);
}
}
- public static boolean isNonReplicatable(Field field)
+ public static boolean isNonReplicable(Field field)
{
int mods = field.getModifiers();
/**
* The following modifiers are ignored in the cache, i.e., they will not be stored
in the cache.
* Whenever, user trying to access these fields, it will be accessed from the
in-memory version.
*/
- return Modifier.isStatic(mods) || Modifier.isTransient(mods) ||
Modifier.isFinal(mods) ||
+ return Modifier.isStatic(mods) || Modifier.isTransient(mods) ||
field.isAnnotationPresent(org.jboss.cache.pojo.annotation.Transient.class);
}
Modified:
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java
===================================================================
---
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java 2008-01-16
22:36:22 UTC (rev 5152)
+++
pojo/branches/2.1/src/main/java/org/jboss/cache/pojo/interceptors/dynamic/CacheFieldInterceptor.java 2008-01-16
22:46:23 UTC (rev 5153)
@@ -112,7 +112,7 @@
// Only if this field is replicatable. static, transient and final are not.
CachedType fieldType = pCache_.getCachedType(field.getType());
Object value = ((FieldWriteInvocation) fieldInvocation).getValue();
- if (!CachedType.isNonReplicatable(field))
+ if (!CachedType.isNonReplicable(field))
{
if (CachedType.isSimpleAttribute(field))
{
@@ -136,7 +136,7 @@
// Only if this field is replicatable
CachedType fieldType = pCache_.getCachedType(field.getType());
- if (!CachedType.isNonReplicatable(field))
+ if (!CachedType.isNonReplicable(field))
{
Object result;
if (CachedType.isSimpleAttribute(field))
Modified: pojo/branches/2.1/src/main/resources/META-INF/pojocache-aop.xml
===================================================================
--- pojo/branches/2.1/src/main/resources/META-INF/pojocache-aop.xml 2008-01-16 22:36:22
UTC (rev 5152)
+++ pojo/branches/2.1/src/main/resources/META-INF/pojocache-aop.xml 2008-01-16 22:46:23
UTC (rev 5153)
@@ -137,10 +137,13 @@
instrumented as well.
-->
- <!-- If a POJO has PojoCachable annotation, it will be asepectized. -->
+ <!-- If a POJO has Replicable annotation, it will be asepectized. -->
<!--
Supports inheritance and polymorphism. It can either be a concrete class
or an interface. All sub-classes or interface implementors will be instrumeneted.
-->
<prepare expr="field(*
$instanceof{(a)org.jboss.cache.pojo.annotation.Replicable}->*)" />
-</aop>
+
+ <!-- Work around that ensures annotated classes which do not access fields are
instrumented -->
+ <introduction
expr="class($instanceof{(a)org.jboss.cache.pojo.annotation.Replicable})"/>
+</aop>
\ No newline at end of file
Modified: pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/LocalTest.java
===================================================================
--- pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/LocalTest.java 2008-01-16
22:36:22 UTC (rev 5152)
+++ pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/LocalTest.java 2008-01-16
22:46:23 UTC (rev 5153)
@@ -58,7 +58,12 @@
private Person createPerson(String id, String name, int age)
{
- Person p = new Person();
+ return createPerson(id, name, age, null);
+ }
+
+ private Person createPerson(String id, String name, int age, Map<String, String>
finalMap)
+ {
+ Person p = new Person(finalMap);
p.setName(name);
p.setAge(age);
Address add = new Address();
@@ -154,6 +159,7 @@
}
}
+
public void testMap() throws Exception
{
log.info("testMap() ....");
@@ -178,7 +184,29 @@
assertEquals("Hobbies size", 2, hobbies.size());
log.debug("Hobbies is " + hobbies.toString());
}
+ public void testFinalMap() throws Exception
+ {
+ log.info("testMap() ....");
+ Person ben = createPerson("/person/test1", "Ben Wang", 40, new
HashMap<String, String>());
+ assertEquals((Object) "Ben Wang", ben.getName());
+ Map<String, String> map = ben.getFinalMap();
+ if (!(map instanceof ClassProxy))
+ {
+ fail("Final map is not an instance of ClassProxy");
+ }
+
+ map.put("test1", "testa");
+ map.put("test2", "testb");
+ assertEquals("Hobbies size", 2, map.size());
+ ben = (Person) cache_.detach("/person/test1");
+ map = ben.getFinalMap();
+ if (!(map instanceof HashMap))
+ {
+ fail("Final map is not an instance of HashMap");
+ }
+ }
+
public void testMapDetachAttach() throws Exception
{
log.info("testMapDetachATtach() ....");
Modified: pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/ReplicatedTest.java
===================================================================
--- pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/ReplicatedTest.java 2008-01-16
22:36:22 UTC (rev 5152)
+++ pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/ReplicatedTest.java 2008-01-16
22:46:23 UTC (rev 5153)
@@ -4,7 +4,9 @@
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -49,7 +51,12 @@
private Person createPerson(String id, String name, int age)
{
- Person p = new Person();
+ return createPerson(id, name, age, null);
+ }
+
+ private Person createPerson(String id, String name, int age, Map<String, String>
map)
+ {
+ Person p = new Person(map);
p.setName(name);
p.setAge(age);
cache.attach(id, p);
@@ -112,6 +119,17 @@
((Person) cache1.find("/person/test1")).getCurrentStatus());
cache.detach("/person/test1");
}
+
+ public void testFinal() throws Exception
+ {
+ Person jason = createPerson("/person/test1", "Jason Greene",
28, new HashMap<String, String>());
+ jason.getFinalMap().put("test1", "testa");
+ jason.getFinalMap().put("test2", "testb");
+
+ Person jason2 = (Person) cache1.find("/person/test1");
+ assertEquals("testa", jason2.getFinalMap().get("test1"));
+ assertEquals("testb", jason2.getFinalMap().get("test2"));
+ }
public void testModification() throws Exception
{
Modified: pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/test/Person.java
===================================================================
--- pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/test/Person.java 2008-01-16
22:36:22 UTC (rev 5152)
+++ pojo/branches/2.1/src/test/java/org/jboss/cache/pojo/test/Person.java 2008-01-16
22:46:23 UTC (rev 5153)
@@ -7,6 +7,8 @@
package org.jboss.cache.pojo.test;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -40,11 +42,17 @@
private List<String> medication = null;
private static final int AGE1 = 50;
private static final int AGE2 = 60;
+ private final Map<String, String> finalMap;
public Person()
{
-
+ this(null);
}
+
+ public Person(Map<String, String> map)
+ {
+ finalMap = map;
+ }
public String getName()
{
@@ -162,6 +170,11 @@
{
this.languages = languages;
}
+
+ public Map<String, String> getFinalMap()
+ {
+ return this.finalMap;
+ }
public String toString()
{