1 package org.apache.ojb.broker.core; 2 3 17 18 import java.util.Map ; 19 20 import org.apache.ojb.broker.Identity; 21 import org.apache.ojb.broker.IdentityFactory; 22 import org.apache.ojb.broker.OJBRuntimeException; 23 import org.apache.ojb.broker.PersistenceBroker; 24 import org.apache.ojb.broker.PersistenceBrokerException; 25 import org.apache.ojb.broker.PBStateListener; 26 import org.apache.ojb.broker.PBStateEvent; 27 import org.apache.ojb.broker.core.proxy.IndirectionHandler; 28 import org.apache.ojb.broker.core.proxy.ProxyHelper; 29 import org.apache.ojb.broker.metadata.ClassDescriptor; 30 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException; 31 import org.apache.ojb.broker.metadata.FieldDescriptor; 32 import org.apache.ojb.broker.util.BrokerHelper; 33 import org.apache.ojb.broker.util.sequence.SequenceManager; 34 import org.apache.ojb.broker.util.sequence.SequenceManagerTransientImpl; 35 import org.apache.commons.lang.SystemUtils; 36 import org.apache.commons.lang.ArrayUtils; 37 import org.apache.commons.lang.exception.ExceptionUtils; 38 import org.apache.commons.collections.map.ReferenceIdentityMap; 39 40 45 public class IdentityFactoryImpl implements IdentityFactory, PBStateListener 46 { 47 private PersistenceBroker broker; 48 private Map objectToIdentityMap; 50 private SequenceManager transientSequenceManager; 51 52 public IdentityFactoryImpl(PersistenceBroker broker) 53 { 54 this.broker = broker; 55 this.objectToIdentityMap = new ReferenceIdentityMap(ReferenceIdentityMap.WEAK, ReferenceIdentityMap.HARD, true); 56 this.transientSequenceManager = new SequenceManagerTransientImpl(broker); 57 broker.addListener(this, true); 58 } 59 60 66 protected Identity createTransientOrRealIdentity(ClassDescriptor cld, Object objOrProxy) 67 { 68 if(objOrProxy == null) throw new OJBRuntimeException("Can't create Identity for 'null'-object"); 69 Identity result = null; 70 Class topLevelClass = null; 71 Class realClass = null; 72 Object [] pks = null; 73 try 74 { 75 final IndirectionHandler handler = ProxyHelper.getIndirectionHandler(objOrProxy); 76 77 synchronized(objOrProxy) 78 { 79 if(handler != null) 80 { 81 result = handler.getIdentity(); 82 } 83 else 84 { 85 realClass = objOrProxy.getClass(); 87 topLevelClass = broker.getTopLevelClass(objOrProxy.getClass()); 88 if(cld == null) 89 { 90 cld = broker.getClassDescriptor(objOrProxy.getClass()); 91 } 92 BrokerHelper helper = broker.serviceBrokerHelper(); 93 94 FieldDescriptor[] fields = cld.getPkFields(); 95 pks = new Object [fields.length]; 96 FieldDescriptor fld; 97 for(int i = 0; i < fields.length; i++) 98 { 99 fld = fields[i]; 100 103 Object value = fld.getPersistentField().get(objOrProxy); 104 if(helper.representsNull(fld, value)) 105 { 106 result = (Identity) objectToIdentityMap.get(objOrProxy); 107 if(result == null) 108 { 109 pks[i] = transientSequenceManager.getUniqueValue(fld); 110 result = new Identity(realClass, topLevelClass, pks, true); 111 objectToIdentityMap.put(objOrProxy, result); 113 } 114 break; 115 } 116 else 117 { 118 pks[i] = value; 119 } 120 } 121 if(result == null) 122 { 123 result = new Identity(realClass, topLevelClass, pks, false); 124 } 125 } 126 } 127 } 128 catch(ClassNotPersistenceCapableException e) 129 { 130 throw e; 131 } 132 catch(Exception e) 133 { 134 throw createException(e, "Can not init Identity for given object.", objOrProxy, topLevelClass, realClass, pks); 135 } 136 return result; 137 } 138 139 140 public Identity buildIdentity(Object obj) 141 { 142 return createTransientOrRealIdentity(broker.getClassDescriptor(ProxyHelper.getRealClass(obj)), obj); 143 } 144 145 146 public Identity buildIdentity(ClassDescriptor cld, Object obj) 147 { 148 return createTransientOrRealIdentity(cld, obj); 149 } 150 151 152 public Identity buildIdentity(Class realClass, Class topLevelClass, String [] pkFieldNames, Object [] pkValues) 153 { 154 Object [] orderedPKValues = pkValues; 155 if(pkValues == null) 156 { 157 throw new NullPointerException ("Given primary key value array can't be null"); 158 } 159 if(pkValues.length == 1 && (pkFieldNames == null || pkFieldNames.length == 1)) 160 { 161 165 } 166 else 167 { 168 FieldDescriptor[] flds = broker.getClassDescriptor(realClass).getPkFields(); 170 if(!isOrdered(flds, pkFieldNames)) 171 { 172 orderedPKValues = reorderFieldValues(flds, pkFieldNames, pkValues); 173 } 174 } 175 return new Identity(realClass, topLevelClass, orderedPKValues); 176 } 177 178 187 private Object [] reorderFieldValues(FieldDescriptor[] flds, String [] fieldNames, Object [] fieldValues) 188 { 189 String fieldName; 190 Object [] orderedValues = new Object [flds.length]; 191 for(int i = 0; i < flds.length; i++) 192 { 193 fieldName = flds[i].getPersistentField().getName(); 194 int realPosition = findIndexForName(fieldNames, fieldName); 195 orderedValues[i] = fieldValues[realPosition]; 196 } 197 return orderedValues; 198 } 199 200 203 private int findIndexForName(String [] fieldNames, String searchName) 204 { 205 for(int i = 0; i < fieldNames.length; i++) 206 { 207 if(searchName.equals(fieldNames[i])) 208 { 209 return i; 210 } 211 } 212 throw new PersistenceBrokerException("Can't find field name '" + searchName + 213 "' in given array of field names"); 214 } 215 216 217 private boolean isOrdered(FieldDescriptor[] flds, String [] pkFieldNames) 218 { 219 if((flds.length > 1 && pkFieldNames == null) || flds.length != pkFieldNames.length) 220 { 221 throw new PersistenceBrokerException("pkFieldName length does not match number of defined PK fields." + 222 " Expected number of PK fields is " + flds.length + ", given number was " + 223 (pkFieldNames != null ? pkFieldNames.length : 0)); 224 } 225 boolean result = true; 226 for(int i = 0; i < flds.length; i++) 227 { 228 FieldDescriptor fld = flds[i]; 229 result = result && fld.getPersistentField().getName().equals(pkFieldNames[i]); 230 } 231 return result; 232 } 233 234 235 public Identity buildIdentity(Class realClass, String [] pkFieldNames, Object [] pkValues) 236 { 237 return buildIdentity(realClass, broker.getTopLevelClass(realClass), pkFieldNames, pkValues); 238 } 239 240 241 public Identity buildIdentity(Class realClass, Class topLevelClass, Object [] pkValues) 242 { 243 return new Identity(realClass, topLevelClass, pkValues); 244 } 245 246 247 public Identity buildIdentity(Class realClass, Object pkValue) 248 { 249 return buildIdentity(realClass, (String []) null, new Object []{pkValue}); 250 } 251 252 263 private PersistenceBrokerException createException(final Exception ex, String message, final Object objectToIdentify, Class topLevelClass, Class realClass, Object [] pks) 264 { 265 final String eol = SystemUtils.LINE_SEPARATOR; 266 StringBuffer msg = new StringBuffer (); 267 if(message == null) 268 { 269 msg.append("Unexpected error: "); 270 } 271 else 272 { 273 msg.append(message).append(" :"); 274 } 275 if(topLevelClass != null) msg.append(eol).append("objectTopLevelClass=").append(topLevelClass.getName()); 276 if(realClass != null) msg.append(eol).append("objectRealClass=").append(realClass.getName()); 277 if(pks != null) msg.append(eol).append("pkValues=").append(ArrayUtils.toString(pks)); 278 if(objectToIdentify != null) msg.append(eol).append("object to identify: ").append(objectToIdentify); 279 if(ex != null) 280 { 281 Throwable rootCause = ExceptionUtils.getRootCause(ex); 283 if(rootCause != null) 284 { 285 msg.append(eol).append("The root stack trace is --> "); 286 String rootStack = ExceptionUtils.getStackTrace(rootCause); 287 msg.append(eol).append(rootStack); 288 } 289 290 return new PersistenceBrokerException(msg.toString(), ex); 291 } 292 else 293 { 294 return new PersistenceBrokerException(msg.toString()); 295 } 296 } 297 298 public void afterBegin(PBStateEvent event) 302 { 303 } 304 305 public void afterCommit(PBStateEvent event) 306 { 307 if(objectToIdentityMap.size() > 0) objectToIdentityMap.clear(); 308 } 309 310 public void afterRollback(PBStateEvent event) 311 { 312 if(objectToIdentityMap.size() > 0) objectToIdentityMap.clear(); 313 } 314 315 public void beforeClose(PBStateEvent event) 316 { 317 if(objectToIdentityMap.size() > 0) objectToIdentityMap.clear(); 318 } 319 320 public void beforeRollback(PBStateEvent event) 321 { 322 } 323 public void afterOpen(PBStateEvent event) 324 { 325 } 326 public void beforeBegin(PBStateEvent event) 327 { 328 } 329 public void beforeCommit(PBStateEvent event) 330 { 331 } 332 } 333 | Popular Tags |