1 package org.apache.ojb.broker; 2 3 17 18 import org.apache.ojb.broker.metadata.ClassDescriptor; 19 import org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException; 20 import org.apache.ojb.broker.core.ValueContainer; 21 import org.apache.ojb.broker.core.proxy.IndirectionHandler; 22 import org.apache.ojb.broker.core.proxy.ProxyHelper; 23 import org.apache.ojb.broker.util.BrokerHelper; 24 import org.apache.commons.lang.SystemUtils; 25 import org.apache.commons.lang.ArrayUtils; 26 27 import java.io.ByteArrayInputStream ; 28 import java.io.ByteArrayOutputStream ; 29 import java.io.ObjectInputStream ; 30 import java.io.ObjectOutputStream ; 31 import java.io.Serializable ; 32 import java.util.Arrays ; 33 import java.util.zip.GZIPInputStream ; 34 import java.util.zip.GZIPOutputStream ; 35 36 71 public class Identity implements Serializable 72 { 73 74 private static final long serialVersionUID = 3182285550574178710L; 75 76 private static final int IS_TRANSIENT = 3; 77 private static final int IS_PERMANENT = 17; 78 81 private static final int iConstant = 37; 82 83 86 private Class m_objectsTopLevelClass; 87 88 91 private Class m_objectsRealClass = null; 92 93 96 private Object [] m_pkValues; 97 98 private final int isTransient; 99 100 108 private transient String m_stringRepresentation = null; 109 private transient Integer m_hashCode; 110 111 114 protected Identity() 115 { 116 isTransient = IS_TRANSIENT; 117 } 118 119 132 public Identity(final Class realClass, final Class topLevel, final Object [] pkValues, final boolean isTransient) 133 { 134 m_objectsTopLevelClass = topLevel; 135 m_objectsRealClass = realClass; 136 m_pkValues = pkValues; 137 this.isTransient = isTransient ? IS_TRANSIENT : IS_PERMANENT; 138 checkForPrimaryKeys(null); 139 } 140 141 152 public Identity(final Class realClass, final Class topLevel, final Object [] pkValues) 153 { 154 m_objectsTopLevelClass = topLevel; 155 m_objectsRealClass = realClass; 156 m_pkValues = pkValues; 157 this.isTransient = IS_PERMANENT; 158 checkForPrimaryKeys(null); 159 } 160 161 167 public Identity(final Object objectToIdentitify, final PersistenceBroker targetBroker) 168 { 169 this.isTransient = IS_PERMANENT; 170 init(objectToIdentitify, targetBroker, null); 171 } 172 173 180 public Identity(final Object objectToIdentitify, final PersistenceBroker targetBroker, final ClassDescriptor cld) 181 { 182 this.isTransient = IS_PERMANENT; 183 init(objectToIdentitify, targetBroker, cld); 184 } 185 186 private void init(final Object objectToIdentify, final PersistenceBroker targetBroker, ClassDescriptor cld) 187 { 188 if(objectToIdentify == null) throw new OJBRuntimeException("Can't create Identity for 'null'-object"); 189 try 190 { 191 final IndirectionHandler handler = ProxyHelper.getIndirectionHandler(objectToIdentify); 192 193 synchronized(objectToIdentify) 194 { 195 if (handler != null) 196 { 197 final Identity sourceOID = handler.getIdentity(); 198 m_objectsTopLevelClass = sourceOID.m_objectsTopLevelClass; 199 m_objectsRealClass = sourceOID.m_objectsRealClass; 200 m_pkValues = sourceOID.m_pkValues; 201 } 202 else 203 { 204 if (cld == null) 205 { 206 cld = targetBroker.getClassDescriptor(objectToIdentify.getClass()); 207 } 208 209 m_objectsTopLevelClass = targetBroker.getTopLevelClass(objectToIdentify.getClass()); 211 m_objectsRealClass = objectToIdentify.getClass(); 212 213 final BrokerHelper helper = targetBroker.serviceBrokerHelper(); 216 final ValueContainer[] pkValues = helper.getValuesForObject(cld.getPkFields(), objectToIdentify, false, true); 217 if (pkValues == null || pkValues.length == 0) 218 { 219 throw createException("Can't extract PK value fields", objectToIdentify, null); 220 } 221 m_pkValues = helper.extractValueArray(pkValues); 222 } 223 } 224 225 checkForPrimaryKeys(objectToIdentify); 226 } 227 catch (ClassNotPersistenceCapableException e) 228 { 229 throw e; 230 } 231 catch (Exception e) 232 { 233 throw createException("Can not init Identity for given object.", objectToIdentify, e); 234 } 235 } 236 237 245 public static Identity fromByteArray(final byte[] anArray) throws PersistenceBrokerException 246 { 247 try 251 { 252 final ByteArrayInputStream bais = new ByteArrayInputStream (anArray); 253 final GZIPInputStream gis = new GZIPInputStream (bais); 254 final ObjectInputStream ois = new ObjectInputStream (gis); 255 final Identity result = (Identity) ois.readObject(); 256 ois.close(); 257 gis.close(); 258 bais.close(); 259 return result; 260 } 261 catch (Exception ex) 262 { 263 throw new PersistenceBrokerException(ex); 264 } 265 } 266 267 272 public boolean isTransient() 273 { 274 return isTransient == IS_TRANSIENT; 275 } 276 277 284 public Class getObjectsTopLevelClass() 285 { 286 return m_objectsTopLevelClass; 287 } 288 289 294 public Class getObjectsRealClass() 295 { 296 return m_objectsRealClass; 297 } 298 299 304 public void setObjectsRealClass(final Class objectsRealClass) 305 { 306 this.m_objectsRealClass = objectsRealClass; 307 } 308 309 316 public byte[] serialize() throws PersistenceBrokerException 317 { 318 try 323 { 324 final ByteArrayOutputStream bao = new ByteArrayOutputStream (); 325 final GZIPOutputStream gos = new GZIPOutputStream (bao); 326 final ObjectOutputStream oos = new ObjectOutputStream (gos); 327 oos.writeObject(this); 328 oos.close(); 329 gos.close(); 330 bao.close(); 331 return bao.toByteArray(); 332 } 333 catch (Exception ignored) 334 { 335 throw new PersistenceBrokerException(ignored); 336 } 337 } 338 339 343 public String toString() 344 { 345 if (m_stringRepresentation == null) 346 { 347 final StringBuffer buf = new StringBuffer (); 348 buf.append(m_objectsTopLevelClass.getName()); 349 for (int i = 0; i < m_pkValues.length; i++) 350 { 351 buf.append((i == 0) ? "{" : ","); 352 buf.append(m_pkValues[i]); 353 } 354 buf.append("}"); 355 if(isTransient == IS_TRANSIENT) buf.append("-transient"); 356 m_stringRepresentation = buf.toString(); 357 } 358 return m_stringRepresentation; 359 } 360 361 362 369 protected void checkForPrimaryKeys(final Object realObject) throws ClassNotPersistenceCapableException 370 { 371 if (m_pkValues == null || m_pkValues.length == 0) 373 { 374 throw createException("OJB needs at least one primary key attribute for class: ", realObject, null); 375 } 376 } 380 381 386 public Object [] getPrimaryKeyValues() 387 { 388 return m_pkValues; 389 } 390 391 394 public boolean equals(final Object obj) 395 { 396 if(this == obj) return true; 397 398 boolean result = false; 399 if (obj instanceof Identity) 400 { 401 final Identity id = (Identity) obj; 402 result = m_objectsTopLevelClass.equals(id.m_objectsTopLevelClass) && isTransient == id.isTransient; 403 if(result) 404 { 405 final Object [] otherPkValues = id.m_pkValues; 406 result = m_pkValues.length == otherPkValues.length; 407 if(result) 408 { 409 for (int i = 0; result && i < m_pkValues.length; i++) 410 { 411 result = (m_pkValues[i] == null) ? (otherPkValues[i] == null) 412 : m_pkValues[i].equals(otherPkValues[i]); 413 414 if (!result && m_pkValues[i] instanceof byte[] && otherPkValues[i] instanceof byte[]) 416 { 417 result = Arrays.equals((byte[]) m_pkValues[i], (byte[]) otherPkValues[i]); 418 } 419 } 420 } 421 } 422 } 423 return result; 424 } 425 426 429 public int hashCode() 430 { 431 436 if(m_hashCode == null) 437 { 438 int iTotal = isTransient; 439 Object obj; 440 for (int i = 0; i < m_pkValues.length; i++) 441 { 442 obj = m_pkValues[i]; 443 if(obj instanceof byte[]) 444 { 445 iTotal = iTotal * iConstant + ((byte[]) obj).length; 446 } 447 else 448 { 449 iTotal = iTotal * iConstant + (obj != null ? obj.hashCode() : 0); 450 } 451 } 452 iTotal = iTotal * iConstant + m_objectsTopLevelClass.hashCode(); 453 m_hashCode = new Integer (iTotal); 454 } 455 return m_hashCode.intValue(); 456 } 457 458 private ClassNotPersistenceCapableException createException(String msg, final Object objectToIdentify, final Exception e) 459 { 460 final String eol = SystemUtils.LINE_SEPARATOR; 461 if(msg == null) 462 { 463 msg = "Unexpected error:"; 464 } 465 if(e != null) 466 { 467 return new ClassNotPersistenceCapableException(msg + eol + 468 "objectTopLevelClass=" + (m_objectsTopLevelClass != null ? m_objectsTopLevelClass.getName() : null) + eol + 469 "objectRealClass=" + (m_objectsRealClass != null ? m_objectsRealClass.getName() : null) + eol + 470 "pkValues=" + (m_pkValues != null ? ArrayUtils.toString(m_pkValues) : null) + 471 (objectToIdentify != null ? (eol + "object to identify: " + objectToIdentify) : ""), e); 472 } 473 else 474 { 475 return new ClassNotPersistenceCapableException(msg + eol + 476 "objectTopLevelClass=" + (m_objectsTopLevelClass != null ? m_objectsTopLevelClass.getName() : null) + eol + 477 "objectRealClass=" + (m_objectsRealClass != null ? m_objectsRealClass.getName() : null) + eol + 478 "pkValues=" + (m_pkValues != null ? ArrayUtils.toString(m_pkValues) : null) + 479 eol + "object to identify: " + objectToIdentify); 480 } 481 } 482 } | Popular Tags |