1 22 package org.jboss.aspects.versioned; 23 24 import org.jboss.aop.Advised; 25 import org.jboss.aop.ClassAdvisor; 26 import org.jboss.aop.InstanceAdvised; 27 import org.jboss.logging.Logger; 28 import org.jboss.tm.TransactionLocal; 29 import org.jboss.util.id.GUID; 30 31 import javax.naming.InitialContext ; 32 import javax.transaction.Transaction ; 33 import javax.transaction.TransactionManager ; 34 35 import java.lang.ref.WeakReference ; 36 import java.lang.reflect.Field ; 37 import java.util.HashMap ; 38 import java.util.Iterator ; 39 import java.util.Map ; 40 41 42 47 public class DistributedPOJOState extends StateManager implements DistributedState, java.io.Externalizable 48 { 49 private static final long serialVersionUID = 7640633352012924284L; 50 51 54 private static Logger log = Logger.getLogger(DistributedPOJOState.class); 55 56 protected String classname; 57 protected HashMap fieldMap; 58 transient protected TransactionManager tm; 59 transient protected WeakReference advisedRef; 60 transient protected TransactionLocal txState = new TransactionLocal(); 61 transient protected SynchronizationManager synchManager; 62 transient protected DistributedVersionManager versionManager; 63 64 public DistributedPOJOState() {} 65 66 public DistributedPOJOState(GUID daguid, long datimeout, Advised advised, DistributedVersionManager versionManager, SynchronizationManager synchManager) 67 throws Exception 68 { 69 super(daguid, datimeout); 70 this.fieldMap = new HashMap (); 71 this.classname = advised.getClass().getName(); 72 InitialContext ctx = new InitialContext (); 73 this.tm = (TransactionManager )ctx.lookup("java:/TransactionManager"); 74 this.synchManager = synchManager; 75 this.versionManager = versionManager; 76 this.advisedRef = new WeakReference (advised); 77 } 78 79 public InstanceAdvised getObject() 80 { 81 if (advisedRef != null) 82 { 83 return (InstanceAdvised)advisedRef.get(); 84 } 85 return null; 86 } 87 88 public boolean equals(Object obj) 89 { 90 if (!(obj instanceof DistributedPOJOState)) return false; 91 DistributedPOJOState pojo = (DistributedPOJOState)obj; 92 return guid.equals(pojo.guid); 93 } 94 95 public int hashCode() 96 { 97 return guid.hashCode(); 98 99 } 100 101 public InstanceAdvised buildObject(SynchronizationManager manager, DistributedVersionManager versionManager) 102 throws Exception 103 { 104 log.trace("building a " + classname + " of guid " + guid); 105 this.versionManager = versionManager; 106 this.synchManager = manager; 107 Class clazz = Thread.currentThread().getContextClassLoader().loadClass(classname); 108 Advised advised = (Advised)clazz.newInstance(); 109 this.advisedRef = new WeakReference (advised); 110 versionManager.addVersioning(this, advised); 111 manager.putState(guid, this); 112 manager.putObject(guid, advised); 113 114 Iterator it = fieldMap.values().iterator(); 115 while(it.hasNext()) 116 { 117 DistributedFieldUpdate update = (DistributedFieldUpdate)it.next(); 118 ClassAdvisor advisor = (ClassAdvisor)advised._getAdvisor(); 119 log.trace("build field " + advisor.getAdvisedFields()[update.getFieldIndex()].getName()); 120 Object val = update.getNonDereferencedValue(); 121 if (val != null && (val instanceof VersionReference)) 122 { 123 VersionReference ref = (VersionReference)val; 124 log.trace("VersionReference.guid: " + ref.getGUID() + " for field " + advisor.getAdvisedFields()[update.getFieldIndex()].getName()); 125 val = manager.getObject(ref.getGUID()); 126 if (val == null) 127 { 128 DistributedState fieldVal = manager.getState(ref.getGUID()); 129 val = fieldVal.buildObject(manager, versionManager); 130 } 131 ref.set((InstanceAdvised)val); 132 } 133 } 134 return advised; 135 } 136 137 public HashMap getTxState() 138 { 139 return (HashMap )txState.get(); 140 } 141 142 public HashMap getTxState(Transaction tx) 143 { 144 return (HashMap )txState.get(tx); 145 } 146 147 public Object fieldRead(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable 148 { 149 acquireReadLock(); 150 try 151 { 152 org.jboss.aop.joinpoint.FieldReadInvocation fieldInvocation = (org.jboss.aop.joinpoint.FieldReadInvocation)invocation; 153 Integer index = new Integer (fieldInvocation.getIndex()); 154 HashMap map = getTxState(); 155 if (map == null) 156 { 157 map = fieldMap; 158 } 159 DistributedFieldUpdate update = (DistributedFieldUpdate)map.get(index); 160 Object val = update.getValue(); 161 return val; 162 } 163 finally 164 { 165 releaseReadLock(); 166 } 167 } 168 169 public Object fieldWrite(org.jboss.aop.joinpoint.Invocation invocation) throws Throwable 170 { 171 org.jboss.aop.joinpoint.FieldWriteInvocation fieldInvocation = (org.jboss.aop.joinpoint.FieldWriteInvocation)invocation; 172 Integer index = new Integer (fieldInvocation.getIndex()); 173 Object val = fieldInvocation.getValue(); 174 175 if (val instanceof Advised) 176 { 177 Advised advisedValue = (Advised)val; 178 val = versionManager.makeVersioned(advisedValue); 179 } 180 181 Transaction tx = tm.getTransaction(); 182 if (tx == null) 183 { 184 acquireWriteLock(); 185 try 186 { 187 DistributedFieldUpdate update = (DistributedFieldUpdate)fieldMap.get(index); 189 long versionId = update.getVersionId() + 1; 190 update.setVersionId(versionId); 191 update.setValue(val); 192 HashMap fieldUpdates = new HashMap (); 193 fieldUpdates.put(index, update); 194 synchManager.noTxUpdate(new DistributedPOJOUpdate(guid, fieldUpdates)); 195 return null; 196 } 197 finally 198 { 199 releaseWriteLock(); 200 } 201 } 202 203 acquireReadLock(); 204 try 205 { 206 HashMap map = (HashMap )txState.get(); 207 if (map == null) 208 { 209 map = new HashMap (); 210 DistributedFieldUpdate update = (DistributedFieldUpdate)fieldMap.get(index); 211 DistributedFieldUpdate newUpdate = new DistributedFieldUpdate(val, update.getVersionId() + 1, index.intValue()); 212 synchManager.registerUpdate(tx, this); 213 map.put(index, newUpdate); 214 txState.set(tx, map); 215 } 216 else 217 { 218 DistributedFieldUpdate newUpdate = (DistributedFieldUpdate)map.get(index); 219 if (newUpdate == null) 220 { 221 DistributedFieldUpdate update = (DistributedFieldUpdate)fieldMap.get(index); 222 newUpdate = new DistributedFieldUpdate(val, update.getVersionId() + 1, index.intValue()); 223 map.put(index, newUpdate); 224 } 225 else 226 { 227 newUpdate.setValue(val); 228 } 229 } 230 } 231 finally 232 { 233 releaseReadLock(); 234 } 235 236 return null; 237 } 238 239 public DistributedUpdate createTxUpdate(Transaction tx) 240 { 241 HashMap state = getTxState(tx); 242 return new DistributedPOJOUpdate(guid, state); 243 } 244 245 public void checkOptimisticLock(Transaction tx) 246 { 247 HashMap state = getTxState(tx); 249 Iterator it = state.entrySet().iterator(); 250 while (it.hasNext()) 251 { 252 Map.Entry entry = (Map.Entry )it.next(); 253 Integer index = (Integer )entry.getKey(); 254 DistributedFieldUpdate update = (DistributedFieldUpdate)entry.getValue(); 255 DistributedFieldUpdate orig = (DistributedFieldUpdate)fieldMap.get(index); 256 if (update.getVersionId() <= orig.getVersionId()) 257 { 258 Advised advised = null; 259 if (advisedRef != null) 260 { 261 advised = (Advised)advisedRef.get(); 262 } 263 if (advised != null) 264 { 265 ClassAdvisor advisor = (ClassAdvisor)advised._getAdvisor(); 266 Field field = advisor.getAdvisedFields()[index.intValue()]; 267 throw new OptimisticLockFailure("optimistic lock failure for field " + field.getName() 268 + " of class " + field.getDeclaringClass().getName()); 269 } 270 } 271 } 272 } 273 274 public void mergeState(Transaction tx) throws Exception 275 { 276 HashMap newState = getTxState(tx); 277 mergeState(newState); 278 } 279 280 public void mergeState(DistributedUpdate update) throws Exception 281 { 282 HashMap newState = ((DistributedPOJOUpdate)update).fieldUpdates; 283 mergeState(newState); 284 } 285 286 public void mergeState(HashMap newState) throws Exception 287 { 288 Iterator it = newState.entrySet().iterator(); 290 while (it.hasNext()) 291 { 292 Map.Entry entry = (Map.Entry )it.next(); 293 DistributedFieldUpdate update = (DistributedFieldUpdate)entry.getValue(); 294 if (update.getNonDereferencedValue() instanceof VersionReference) 295 { 296 VersionReference ref = (VersionReference)update.getNonDereferencedValue(); 297 if (ref.get() == null) ref.set((InstanceAdvised)synchManager.getObject(ref.getGUID())); 298 } 299 } 300 fieldMap.putAll(newState); } 302 303 public void writeExternal(java.io.ObjectOutput out) 304 throws java.io.IOException 305 { 306 super.writeExternal(out); 307 out.writeObject(classname); 308 out.writeObject(fieldMap); 309 } 310 311 public void readExternal(java.io.ObjectInput in) 312 throws java.io.IOException , ClassNotFoundException 313 { 314 super.readExternal(in); 315 this.classname = (String )in.readObject(); 316 this.fieldMap = (HashMap )in.readObject(); 317 try 318 { 319 InitialContext ctx = new InitialContext (); 320 this.tm = (TransactionManager )ctx.lookup("java:/TransactionManager"); 321 } 322 catch (Exception ex) 323 { 324 throw new RuntimeException (ex); 325 } 326 this.txState = new TransactionLocal(); 327 } 328 329 } 330 | Popular Tags |