1 22 package org.jboss.ejb.plugins.cmp.jdbc.bridge; 23 24 import java.lang.reflect.Field ; 25 26 import java.sql.PreparedStatement ; 27 import java.sql.ResultSet ; 28 import java.sql.SQLException ; 29 30 import javax.ejb.EJBException ; 31 32 import org.jboss.deployment.DeploymentException; 33 import org.jboss.ejb.EntityEnterpriseContext; 34 35 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCCMPFieldMetaData; 36 37 import org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager; 38 import org.jboss.ejb.plugins.cmp.jdbc.JDBCType; 39 import org.jboss.ejb.plugins.cmp.jdbc.CMPFieldStateFactory; 40 import org.jboss.ejb.plugins.cmp.jdbc.JDBCTypeFactory; 41 import org.jboss.ejb.plugins.cmp.jdbc.LockingStrategy; 42 import org.jboss.ejb.plugins.cmp.jdbc.JDBCEntityPersistenceStore; 43 import org.jboss.ejb.plugins.cmp.jdbc.JDBCResultSetReader; 44 45 import org.jboss.logging.Logger; 46 47 72 public abstract class JDBCAbstractCMPFieldBridge implements JDBCCMPFieldBridge 73 { 74 protected final Logger log; 75 protected final JDBCStoreManager manager; 76 private final JDBCType jdbcType; 77 protected final String fieldName; 78 private final Class fieldType; 79 protected final boolean readOnly; 80 protected final long readTimeOut; 81 protected final boolean primaryKeyMember; 82 private final Class primaryKeyClass; 83 private final Field primaryKeyField; 84 protected final int jdbcContextIndex; 85 protected final int tableIndex; 86 protected CMPFieldStateFactory stateFactory; 87 protected boolean checkDirtyAfterGet; 88 89 protected byte defaultFlags = 0; 90 91 private LockingStrategy lockingStrategy = LockingStrategy.NONE; 92 93 public JDBCAbstractCMPFieldBridge(JDBCStoreManager manager, 94 JDBCCMPFieldMetaData metadata) 95 throws DeploymentException 96 { 97 this(manager, metadata, manager.getJDBCTypeFactory().getJDBCType(metadata)); 98 } 99 100 public JDBCAbstractCMPFieldBridge(JDBCStoreManager manager, 101 JDBCCMPFieldMetaData metadata, 102 JDBCType jdbcType) 103 throws DeploymentException 104 { 105 this.manager = manager; 106 this.fieldName = metadata.getFieldName(); 107 this.fieldType = metadata.getFieldType(); 108 this.jdbcType = jdbcType; 109 this.readOnly = metadata.isReadOnly(); 110 this.readTimeOut = metadata.getReadTimeOut(); 111 this.primaryKeyMember = metadata.isPrimaryKeyMember(); 112 this.primaryKeyClass = metadata.getEntity().getPrimaryKeyClass(); 113 this.primaryKeyField = metadata.getPrimaryKeyField(); 114 115 final JDBCEntityBridge entityBridge = (JDBCEntityBridge)manager.getEntityBridge(); 116 this.jdbcContextIndex = entityBridge.getNextJDBCContextIndex(); 117 118 if(!metadata.isRelationTableField()) 119 tableIndex = entityBridge.addTableField(this); 120 else 121 tableIndex = -1; 122 123 final JDBCTypeFactory typeFactory = manager.getJDBCTypeFactory(); 124 stateFactory = JDBCTypeFactory.getCMPFieldStateFactory( 125 typeFactory, metadata.getStateFactory(), fieldType 126 ); 127 checkDirtyAfterGet = JDBCTypeFactory.checkDirtyAfterGet( 128 typeFactory, metadata.getCheckDirtyAfterGet(), fieldType 129 ); 130 131 this.log = createLogger(manager, fieldName); 132 } 133 134 public JDBCAbstractCMPFieldBridge(JDBCStoreManager manager, 135 String fieldName, 136 Class fieldType, 137 JDBCType jdbcType, 138 boolean readOnly, 139 long readTimeOut, 140 Class primaryKeyClass, 141 Field primaryKeyField, 142 int jdbcContextIndex, 143 int tableIndex, 144 boolean checkDirtyAfterGet, 145 CMPFieldStateFactory stateFactory) 146 { 147 this.manager = manager; 148 this.fieldName = fieldName; 149 this.fieldType = fieldType; 150 this.jdbcType = jdbcType; 151 this.readOnly = readOnly; 152 this.readTimeOut = readTimeOut; 153 this.primaryKeyMember = false; 154 this.primaryKeyClass = primaryKeyClass; 155 this.primaryKeyField = primaryKeyField; 156 this.jdbcContextIndex = jdbcContextIndex; 157 this.tableIndex = tableIndex; 158 this.stateFactory = stateFactory; 159 this.checkDirtyAfterGet = checkDirtyAfterGet; 160 this.log = createLogger(manager, fieldName); 161 } 162 163 public byte getDefaultFlags() 164 { 165 return defaultFlags; 166 } 167 168 169 public void addDefaultFlag(byte flag) 170 { 171 defaultFlags |= flag; 172 } 173 174 public JDBCEntityPersistenceStore getManager() 175 { 176 return manager; 177 } 178 179 public String getFieldName() 180 { 181 return fieldName; 182 } 183 184 public JDBCType getJDBCType() 185 { 186 return jdbcType; 187 } 188 189 public Class getFieldType() 190 { 191 return fieldType; 192 } 193 194 public boolean isPrimaryKeyMember() 195 { 196 return primaryKeyMember; 197 } 198 199 public Field getPrimaryKeyField() 200 { 201 return primaryKeyField; 202 } 203 204 public boolean isReadOnly() 205 { 206 return readOnly; 207 } 208 209 public long getReadTimeOut() 210 { 211 return readTimeOut; 212 } 213 214 public Object getValue(EntityEnterpriseContext ctx) 215 { 216 Object value = getInstanceValue(ctx); 217 if(ctx.isValid()) 218 { 219 lockingStrategy.accessed(this, ctx); 220 if(checkDirtyAfterGet) 221 { 222 setDirtyAfterGet(ctx); 223 } 224 } 225 return value; 226 } 227 228 public void setValue(EntityEnterpriseContext ctx, Object value) 229 { 230 if(isReadOnly()) 231 { 232 throw new EJBException ("Field is read-only: fieldName=" + fieldName); 233 } 234 if(primaryKeyMember && JDBCEntityBridge.isEjbCreateDone(ctx)) 235 { 236 throw new IllegalStateException ("A CMP field that is a member " + 237 "of the primary key can only be set in ejbCreate " + 238 "[EJB 2.0 Spec. 10.3.5]."); 239 } 240 241 if(ctx.isValid()) 242 { 243 if(!isLoaded(ctx)) 244 { 245 manager.loadField(this, ctx); 247 } 248 lockingStrategy.changed(this, ctx); 249 } 250 setInstanceValue(ctx, value); 251 } 252 253 public Object getPrimaryKeyValue(Object primaryKey) 254 throws IllegalArgumentException 255 { 256 try 257 { 258 if(primaryKeyField != null) 259 { 260 if(primaryKey == null) 261 { 262 return null; 263 } 264 265 return primaryKeyField.get(primaryKey); 267 } 268 else 269 { 270 return primaryKey; 272 } 273 } 274 catch(Exception e) 275 { 276 throw new EJBException ("Internal error getting primary key " + 278 "field member " + getFieldName(), e); 279 } 280 } 281 282 public Object setPrimaryKeyValue(Object primaryKey, Object value) 283 throws IllegalArgumentException 284 { 285 try 286 { 287 if(primaryKeyField != null) 288 { 289 if(value == null && primaryKey == null) 292 { 293 return null; 294 } 295 296 if(primaryKey == null) 298 { 299 primaryKey = primaryKeyClass.newInstance(); 300 } 301 302 primaryKeyField.set(primaryKey, value); 304 return primaryKey; 305 } 306 else 307 { 308 return value; 310 } 311 } 312 catch(Exception e) 313 { 314 throw new EJBException ("Internal error setting instance field " + 316 getFieldName(), e); 317 } 318 } 319 320 public abstract void resetPersistenceContext(EntityEnterpriseContext ctx); 321 322 325 public void initInstance(EntityEnterpriseContext ctx) 326 { 327 if(!readOnly) 328 { 329 Object value; 330 if(fieldType == boolean.class) 331 value = Boolean.FALSE; 332 else if(fieldType == byte.class) 333 value = new Byte ((byte)0); 334 else if(fieldType == int.class) 335 value = new Integer (0); 336 else if(fieldType == long.class) 337 value = new Long (0L); 338 else if(fieldType == short.class) 339 value = new Short ((short)0); 340 else if(fieldType == char.class) 341 value = new Character ('\u0000'); 342 else if(fieldType == double.class) 343 value = new Double (0d); 344 else if(fieldType == float.class) 345 value = new Float (0f); 346 else 347 value = null; 348 setInstanceValue(ctx, value); 349 } 350 } 351 352 public int setInstanceParameters(PreparedStatement ps, int parameterIndex, EntityEnterpriseContext ctx) 353 { 354 Object instanceValue = getInstanceValue(ctx); 355 return setArgumentParameters(ps, parameterIndex, instanceValue); 356 } 357 358 public int setPrimaryKeyParameters(PreparedStatement ps, int parameterIndex, Object primaryKey) 359 throws IllegalArgumentException 360 { 361 Object primaryKeyValue = getPrimaryKeyValue(primaryKey); 362 return setArgumentParameters(ps, parameterIndex, primaryKeyValue); 363 } 364 365 public int setArgumentParameters(PreparedStatement ps, int parameterIndex, Object arg) 366 { 367 try 368 { 369 int[] jdbcTypes = jdbcType.getJDBCTypes(); 370 for(int i = 0; i < jdbcTypes.length; i++) 371 { 372 Object columnValue = jdbcType.getColumnValue(i, arg); 373 jdbcType.getParameterSetter()[i].set(ps, parameterIndex++, jdbcTypes[i], columnValue, log); 374 } 376 return parameterIndex; 377 } 378 catch(SQLException e) 379 { 380 throw new EJBException ("Internal error setting parameters for field " + getFieldName(), e); 382 } 383 } 384 385 public int loadInstanceResults(ResultSet rs, int parameterIndex, EntityEnterpriseContext ctx) 386 { 387 try 388 { 389 Object [] argumentRef = new Object [1]; 391 392 parameterIndex = loadArgumentResults(rs, parameterIndex, argumentRef); 394 395 setInstanceValue(ctx, argumentRef[0]); 397 398 lockingStrategy.loaded(this, ctx); 399 400 return parameterIndex; 401 } 402 catch(EJBException e) 403 { 404 throw e; 406 } 407 catch(Exception e) 408 { 409 throw new EJBException ("Internal error getting results for field " + getFieldName(), e); 411 } 412 } 413 414 public int loadPrimaryKeyResults(ResultSet rs, int parameterIndex, Object [] pkRef) 415 throws IllegalArgumentException 416 { 417 Object [] argumentRef = new Object [1]; 419 420 parameterIndex = loadArgumentResults(rs, parameterIndex, argumentRef, true); 421 422 pkRef[0] = argumentRef[0] == null ? null : setPrimaryKeyValue(pkRef[0], argumentRef[0]); 424 425 return parameterIndex; 427 } 428 429 public int loadArgumentResults(ResultSet rs, int parameterIndex, Object [] argumentRef) 430 throws IllegalArgumentException 431 { 432 return loadArgumentResults(rs, parameterIndex, argumentRef, false); 433 } 434 435 public boolean isRelationTableField() 436 { 437 return tableIndex < 0; 438 } 439 440 public final int getFieldIndex() 441 { 442 return jdbcContextIndex; 443 } 444 445 public Class getPrimaryKeyClass() 446 { 447 return primaryKeyClass; 448 } 449 450 451 public int getTableIndex() 452 { 453 return tableIndex; 454 } 455 456 public void setLockingStrategy(LockingStrategy lockingStrategy) 457 { 458 this.lockingStrategy = lockingStrategy; 459 } 460 461 protected abstract void setDirtyAfterGet(EntityEnterpriseContext ctx); 462 463 public boolean isCMPField() 464 { 465 return true; 466 } 467 468 private int loadArgumentResults(ResultSet rs, int parameterIndex, Object [] argumentRef, boolean nullColumnNullifiesResult) 469 throws IllegalArgumentException 470 { 471 try 472 { 473 argumentRef[0] = null; 476 477 Class [] javaTypes = jdbcType.getJavaTypes(); 479 JDBCResultSetReader[] rsReaders = jdbcType.getResultSetReaders(); 480 for(int i = 0; i < javaTypes.length; i++) 481 { 482 Object columnValue = rsReaders[i].get(rs, parameterIndex++, javaTypes[i], log); 483 if(nullColumnNullifiesResult && columnValue == null) 484 { 485 argumentRef[0] = null; 486 parameterIndex += javaTypes.length - i - 1; 487 break; 488 } 489 argumentRef[0] = jdbcType.setColumnValue(i, argumentRef[0], columnValue); 490 } 491 492 return parameterIndex; 494 } 495 catch(SQLException e) 496 { 497 throw new EJBException ("Internal error getting results " + 499 "for field member " + getFieldName(), e); 500 } 501 } 502 503 private Logger createLogger(JDBCStoreManager manager, String fieldName) 504 { 505 return Logger.getLogger( 506 this.getClass().getName() + 507 "." + 508 manager.getMetaData().getName() + 509 "#" + 510 fieldName); 511 } 512 } 513 | Popular Tags |