1 4 package com.tc.objectserver.managedobject; 5 6 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap; 7 8 import com.tc.exception.TCRuntimeException; 9 import com.tc.io.serializer.TCObjectInputStream; 10 import com.tc.io.serializer.TCObjectOutputStream; 11 import com.tc.object.ObjectID; 12 import com.tc.object.dna.api.DNACursor; 13 import com.tc.object.dna.api.PhysicalAction; 14 import com.tc.objectserver.managedobject.bytecode.ClassSpec; 15 import com.tc.objectserver.managedobject.bytecode.FieldType; 16 import com.tc.objectserver.managedobject.bytecode.PhysicalStateClassLoader; 17 import com.tc.objectserver.persistence.api.ClassPersistor; 18 import com.tc.util.Assert; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.ByteArrayOutputStream ; 22 import java.lang.reflect.Constructor ; 23 import java.util.ArrayList ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.SortedMap ; 29 import java.util.TreeMap ; 30 import java.util.Map.Entry; 31 32 public class PhysicalManagedObjectStateFactory { 33 34 private static final Class [] CONSTRUCTOR_PARAMS_CLASS = new Class [0]; 35 private static final Object [] CONSTRUCTOR_PARAMS = new Object [0]; 36 private final PhysicalStateClassLoader loader; 37 private final Map knownClasses; 38 private final ClassPersistor persistor; 39 private int sequenceId = 0; 40 41 public PhysicalManagedObjectStateFactory(ClassPersistor persistor) { 42 this.loader = new PhysicalStateClassLoader(); 43 this.knownClasses = new ConcurrentHashMap(); 44 this.persistor = persistor; 45 loadAllClassesFromDB(); 46 } 47 48 private synchronized void loadAllClassesFromDB() { 49 SortedMap map = new TreeMap (persistor.retrieveAllClasses()); 50 for (Iterator i = map.entrySet().iterator(); i.hasNext();) { 51 Map.Entry e = (Entry) i.next(); 52 Integer clazzId = (Integer ) e.getKey(); 53 byte clazzBytes[] = (byte[]) e.getValue(); 54 int cid = clazzId.intValue(); 55 if (sequenceId < cid) { 56 sequenceId = cid; 57 } 58 loadFromBytes(cid, clazzBytes); 59 } 60 } 61 62 private void addKnownClasses(String classIdentifier, String genClassName, int cid) { 63 knownClasses.put(classIdentifier, genClassName); 64 knownClasses.put(new Integer (cid), genClassName); 65 } 66 67 private void addKnownClasses(ClassSpec cs) { 68 addKnownClasses(cs.getClassIdentifier(), cs.getGeneratedClassName(), cs.getClassID()); 69 } 70 71 private void loadFromBytes(int classId, byte[] clazzBytes) { 72 try { 73 ByteArrayInputStream bai = new ByteArrayInputStream (clazzBytes); 74 TCObjectInputStream tci = new TCObjectInputStream(bai); 75 76 String classIdentifier = tci.readString(); 77 String genClassName = tci.readString(); 78 79 loader.defineClassFromBytes(genClassName, classId, clazzBytes, clazzBytes.length - bai.available(), bai 80 .available()); 81 addKnownClasses(classIdentifier, genClassName, classId); 82 } catch (Exception ex) { 83 throw new TCRuntimeException(ex); 84 } 85 } 86 87 private void writeToDB(ClassSpec cs, byte[] data) { 88 try { 89 String classIdentifier = cs.getClassIdentifier(); 90 String genClassName = cs.getGeneratedClassName(); 91 92 ByteArrayOutputStream bao = new ByteArrayOutputStream (data.length + 1024); 93 TCObjectOutputStream tco = new TCObjectOutputStream(bao); 94 tco.writeString(classIdentifier); 95 tco.writeString(genClassName); 96 tco.write(data); 97 tco.flush(); 98 99 persistor.storeClass(cs.getClassID(), bao.toByteArray()); 100 } catch (Exception ex) { 101 throw new TCRuntimeException(ex); 102 } 103 } 104 105 public PhysicalManagedObjectState create(long strIdx, ObjectID parentID, String className, String loaderDesc, 106 DNACursor cursor) { 107 ClassSpec cs = new ClassSpec(className, loaderDesc, strIdx); 108 String classIdentifier = cs.getClassIdentifier(); 109 String generatedClassName = (String ) knownClasses.get(classIdentifier); 110 if (generatedClassName == null) { 111 Object lock = cs.getLock(); 112 synchronized (lock) { 113 generatedClassName = (String ) knownClasses.get(classIdentifier); 115 if (generatedClassName == null) { 116 PhysicalManagedObjectState po = createNewClassAndInitializeObject(parentID, cs, cursor); 117 return po; 118 } 119 } 120 } 121 return createNewObject(generatedClassName, parentID); 122 } 123 124 public PhysicalManagedObjectState create(ObjectID parentID, int classId) throws ClassNotFoundException { 125 Integer cid = new Integer (classId); 126 String className = (String ) knownClasses.get(cid); 127 if (className == null) { throw new ClassNotFoundException ("Unknown Class Id :" + classId + " Details : parent = " 128 + parentID); } 129 return createNewObject(className, parentID); 130 } 131 132 public PhysicalManagedObjectState recreate(long classID, ObjectID pid, String className, String loaderDesc, 133 DNACursor cursor, PhysicalManagedObjectState oldState) { 134 ClassSpec cs = new ClassSpec(className, loaderDesc, classID); 135 String classIdentifier = cs.getClassIdentifier(); 136 String generatedClassName = (String ) knownClasses.get(classIdentifier); 137 Assert.assertNotNull(generatedClassName); 138 Object lock = cs.getLock(); 139 synchronized (lock) { 140 PhysicalManagedObjectState newState = oldState; 141 if (!oldState.getClass().getName().equals(generatedClassName)) { 142 newState = createNewObject(generatedClassName, pid); 144 initNewStateFromOld(newState, oldState); 145 } 146 List deltaFields = findDeltaFields(newState, cursor); 147 if (deltaFields.isEmpty()) { 148 return newState; 150 } else { 151 cs.setSuperClassName(newState.getClass().getName()); 153 PhysicalManagedObjectState latestState = createNewClassAndInitializeObject(pid, cs, deltaFields); 154 return initNewStateFromOld(latestState, oldState); 155 } 156 } 157 } 158 159 private PhysicalManagedObjectState initNewStateFromOld(PhysicalManagedObjectState newState, 160 PhysicalManagedObjectState oldState) { 161 if (newState == oldState) { return newState; } 162 Map fields2Vals = oldState.addValues(new HashMap()); 163 for (Iterator i = fields2Vals.entrySet().iterator(); i.hasNext();) { 164 Map.Entry e = (Entry) i.next(); 165 newState.set((String ) e.getKey(), e.getValue()); 166 } 167 return newState; 168 } 169 170 private List findDeltaFields(PhysicalManagedObjectState state, DNACursor cursor) { 171 try { 172 List deltaFields = new ArrayList (); 173 Map fields2Values = new HashMap(); 174 state.addValues(fields2Values); 175 cursor.reset(); 176 while (cursor.next()) { 177 PhysicalAction action = cursor.getPhysicalAction(); 178 if (!fields2Values.containsKey(action.getFieldName())) { 179 deltaFields.add(createFieldType(action, deltaFields.size())); 180 } 181 } 182 return deltaFields; 183 } catch (Exception ex) { 184 throw new TCRuntimeException(ex); 185 } finally { 186 cursor.reset(); 187 } 188 } 189 190 193 private PhysicalManagedObjectState createNewObject(String stateClassName, ObjectID parentID) { 194 try { 195 Class c = loader.loadClass(stateClassName); 196 Constructor constructor = c.getConstructor(CONSTRUCTOR_PARAMS_CLASS); 197 PhysicalManagedObjectState po = (PhysicalManagedObjectState) constructor.newInstance(CONSTRUCTOR_PARAMS); 198 initializeManagedObjectState(po, parentID); 199 return po; 200 } catch (Exception e) { 201 throw new TCRuntimeException(e); 202 } 203 } 204 205 208 private PhysicalManagedObjectState createNewClassAndInitializeObject(ObjectID parentID, ClassSpec cs, DNACursor cursor) { 209 try { 210 List fields = new ArrayList (cursor.getActionCount()); 211 cursor.reset(); 212 while (cursor.next()) { 213 PhysicalAction action = cursor.getPhysicalAction(); 214 fields.add(createFieldType(action, fields.size())); 215 } 216 return createNewClassAndInitializeObject(parentID, cs, fields); 217 } catch (Exception ex) { 218 throw new TCRuntimeException(ex); 219 } finally { 220 cursor.reset(); 221 } 222 } 223 224 private PhysicalManagedObjectState createNewClassAndInitializeObject(ObjectID parentID, ClassSpec cs, List fields) { 225 try { 226 int clazzId = getNextSequenceID(); 227 cs.setGeneratedClassID(clazzId); 228 byte data[] = loader.createClassBytes(cs, parentID, fields); 229 230 String generatedClassName = cs.getGeneratedClassName(); 231 Class c = loader.defineClassFromBytes(generatedClassName, clazzId, data, 0, data.length); 232 addKnownClasses(cs); 233 writeToDB(cs, data); 234 Constructor constructor = c.getConstructor(CONSTRUCTOR_PARAMS_CLASS); 235 PhysicalManagedObjectState mo = (PhysicalManagedObjectState) constructor.newInstance(CONSTRUCTOR_PARAMS); 236 initializeManagedObjectState(mo, parentID); 237 return mo; 238 } catch (Exception e) { 239 throw new TCRuntimeException(e); 240 } 241 } 242 243 private void initializeManagedObjectState(PhysicalManagedObjectState po, ObjectID parentID) { 244 po.setParentID(parentID); 245 } 246 247 private synchronized int getNextSequenceID() { 248 return ++sequenceId; 249 } 250 251 private FieldType createFieldType(PhysicalAction action, int id) { 252 String fieldName = action.getFieldName(); 253 Object value = action.getObject(); 254 return FieldType.create(fieldName, value, action.isReference(), id); 255 } 256 257 } 258 | Popular Tags |