1 22 package org.jboss.ejb.plugins.cmp.jdbc; 23 24 import java.lang.reflect.Method ; 25 import java.sql.Connection ; 26 import java.sql.PreparedStatement ; 27 import java.sql.SQLException ; 28 import java.util.ArrayList ; 29 import java.util.Date ; 30 import java.util.List ; 31 import javax.ejb.CreateException ; 32 import javax.ejb.FinderException ; 33 import javax.management.MalformedObjectNameException ; 34 import javax.sql.DataSource ; 35 36 import org.jboss.deployment.DeploymentException; 37 import org.jboss.ejb.EntityEnterpriseContext; 38 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMPFieldBridge; 39 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCCMRFieldBridge; 40 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCEntityBridge; 41 import org.jboss.ejb.plugins.cmp.jdbc.bridge.JDBCFieldBridge; 42 import org.jboss.ejb.plugins.cmp.jdbc.metadata.JDBCEntityCommandMetaData; 43 import org.jboss.logging.Logger; 44 import org.jboss.mx.util.MBeanProxyExt; 45 import org.jboss.security.AuthenticationManager; 46 47 53 public abstract class JDBCAbstractCreateCommand implements JDBCCreateCommand 54 { 55 protected Logger log; 56 protected boolean debug; 57 protected boolean trace; 58 protected JDBCEntityBridge entity; 59 protected AuthenticationManager securityManager; 60 protected boolean createAllowed; 61 protected SQLExceptionProcessorMBean exceptionProcessor; 62 protected String insertSQL; 63 protected JDBCFieldBridge[] insertFields; 64 protected boolean insertAfterEjbPostCreate; 65 66 private JDBCCMPFieldBridge createdPrincipal; 68 private JDBCCMPFieldBridge createdTime; 69 private JDBCCMPFieldBridge updatedPrincipal; 70 private JDBCCMPFieldBridge updatedTime; 71 72 public void init(JDBCStoreManager manager) throws DeploymentException 73 { 74 log = Logger.getLogger(getClass().getName() + '.' + manager.getMetaData().getName()); 75 debug = log.isDebugEnabled(); 76 trace = log.isTraceEnabled(); 77 78 entity = (JDBCEntityBridge) manager.getEntityBridge(); 79 securityManager = manager.getContainer().getSecurityManager(); 80 81 insertAfterEjbPostCreate = manager.getContainer() 82 .getBeanMetaData().getContainerConfiguration().isInsertAfterEjbPostCreate(); 83 84 createAllowed = true; 86 JDBCFieldBridge[] pkFields = entity.getPrimaryKeyFields(); 87 for(int i = 0; i < pkFields.length; i++) 88 { 89 if(pkFields[i].isReadOnly()) 90 { 91 createAllowed = false; 92 log.debug("Create will not be allowed because pk field " 93 + pkFields[i].getFieldName() + "is read only."); 94 break; 95 } 96 } 97 98 initGeneratedFields(); 99 100 JDBCEntityCommandMetaData entityCommand = manager.getMetaData().getEntityCommand(); 101 if(entityCommand == null) 102 { 103 throw new DeploymentException("entity-command is null"); 104 } 105 initEntityCommand(entityCommand); 106 107 initInsertFields(); 108 initInsertSQL(); 109 } 110 111 protected void initEntityCommand(JDBCEntityCommandMetaData entityCommand) throws DeploymentException 112 { 113 String objectName = entityCommand.getAttribute("SQLExceptionProcessor"); 114 if(objectName != null) 115 { 116 try 117 { 118 exceptionProcessor = (SQLExceptionProcessorMBean) MBeanProxyExt.create(SQLExceptionProcessorMBean.class, objectName); 119 } 120 catch(MalformedObjectNameException e) 121 { 122 throw new DeploymentException("Invalid object name for SQLExceptionProcessor: ", e); 123 } 124 } 125 } 126 127 public Object execute(Method m, Object [] args, EntityEnterpriseContext ctx) throws CreateException 128 { 129 if(insertAfterEjbPostCreate) 131 { 132 if(!JDBCEntityBridge.isEjbCreateDone(ctx)) 133 { 134 checkCreateAllowed(); 135 generateFields(ctx); 136 JDBCEntityBridge.setEjbCreateDone(ctx); 137 } 138 else 139 { 140 beforeInsert(ctx); 141 performInsert(ctx); 142 afterInsert(ctx); 143 JDBCEntityBridge.setCreated(ctx); 144 } 145 } 146 else 147 { 148 checkCreateAllowed(); 149 generateFields(ctx); 150 beforeInsert(ctx); 151 performInsert(ctx); 152 afterInsert(ctx); 153 JDBCEntityBridge.setCreated(ctx); 154 } 155 return getPrimaryKey(ctx); 156 } 157 158 protected void checkCreateAllowed() throws CreateException 159 { 160 if(!createAllowed) 161 { 162 throw new CreateException ("Creation is not allowed because a primary key field is read only."); 163 } 164 } 165 166 protected JDBCCMPFieldBridge getGeneratedPKField() throws DeploymentException 167 { 168 JDBCCMPFieldBridge pkField = null; 170 JDBCFieldBridge[] pkFields = entity.getPrimaryKeyFields(); 171 for(int i = 0; i < pkFields.length; ++i) 172 { 173 if(pkField != null) 174 throw new DeploymentException("Generation only supported with single PK field"); 175 pkField = (JDBCCMPFieldBridge)pkFields[i]; 176 } 177 return pkField; 178 } 179 180 protected void initGeneratedFields() throws DeploymentException 181 { 182 createdPrincipal = entity.getCreatedPrincipalField(); 183 if(securityManager == null && createdPrincipal != null) 184 { 185 throw new DeploymentException("No security-domain configured but created-by specified"); 186 } 187 updatedPrincipal = entity.getUpdatedPrincipalField(); 188 if(securityManager == null && updatedPrincipal != null) 189 { 190 throw new DeploymentException("No security-domain configured but updated-by specified"); 191 } 192 createdTime = entity.getCreatedTimeField(); 193 updatedTime = entity.getUpdatedTimeField(); 194 } 195 196 protected void generateFields(EntityEnterpriseContext ctx) throws CreateException 197 { 198 if(securityManager != null) 200 { 201 String principalName = ctx.getEJBContext().getCallerPrincipal().getName(); 202 if(createdPrincipal != null && createdPrincipal.getInstanceValue(ctx) == null) 203 { 204 createdPrincipal.setInstanceValue(ctx, principalName); 205 } 206 212 } 213 214 Date date = null; 216 if(createdTime != null && createdTime.getInstanceValue(ctx) == null) 217 { 218 date = new Date (); 219 createdTime.setInstanceValue(ctx, date); 220 } 221 229 } 230 231 protected void initInsertFields() 232 { 233 JDBCFieldBridge[] fields = entity.getTableFields(); 234 List insertFieldsList = new ArrayList (fields.length); 235 for(int i = 0; i < fields.length; i++) 236 { 237 JDBCFieldBridge field = fields[i]; 238 if(isInsertField(field)) 239 insertFieldsList.add(field); 240 } 241 242 insertFields = (JDBCFieldBridge[]) insertFieldsList.toArray(new JDBCFieldBridge[insertFieldsList.size()]); 243 } 244 245 protected boolean isInsertField(JDBCFieldBridge field) 246 { 247 boolean result = 248 !(field instanceof JDBCCMRFieldBridge) 249 && field.getJDBCType() != null 250 && !field.isReadOnly(); 251 if(field instanceof JDBCCMPFieldBridge) 252 result = result && !((JDBCCMPFieldBridge) field).isRelationTableField(); 253 return result; 254 } 255 256 protected void initInsertSQL() 257 { 258 StringBuffer sql = new StringBuffer (250); 259 sql.append(SQLUtil.INSERT_INTO) 260 .append(entity.getQualifiedTableName()) 261 .append(" ("); 262 263 SQLUtil.getColumnNamesClause(insertFields, sql); 264 265 sql.append(')') 266 .append(SQLUtil.VALUES).append('('); 267 SQLUtil.getValuesClause(insertFields, sql) 268 .append(')'); 269 insertSQL = sql.toString(); 270 271 if(debug) 272 log.debug("Insert Entity SQL: " + insertSQL); 273 } 274 275 protected void beforeInsert(EntityEnterpriseContext ctx) throws CreateException 276 { 277 } 278 279 protected void performInsert(EntityEnterpriseContext ctx) throws CreateException 280 { 281 Connection c = null; 282 PreparedStatement ps = null; 283 boolean throwRuntimeExceptions = entity.getMetaData().getThrowRuntimeExceptions(); 284 285 if (throwRuntimeExceptions) 288 { 289 try 290 { 291 c = entity.getDataSource().getConnection(); 292 } 293 catch (SQLException sqle) 294 { 295 javax.ejb.EJBException ejbe = new javax.ejb.EJBException ("Could not get a connection; " + sqle); 296 ejbe.initCause(sqle); 297 throw ejbe; 298 } 299 } 300 301 try 302 { 303 if(debug) 304 log.debug("Executing SQL: " + insertSQL); 305 306 307 if ( ! throwRuntimeExceptions) 309 { 310 c = entity.getDataSource().getConnection(); 311 } 312 ps = prepareStatement(c, insertSQL, ctx); 313 314 int index = 1; 316 for(int fieldInd = 0; fieldInd < insertFields.length; ++fieldInd) 317 { 318 index = insertFields[fieldInd].setInstanceParameters(ps, index, ctx); 319 } 320 321 int rowsAffected = executeInsert(index, ps, ctx); 323 if(rowsAffected != 1) 324 { 325 throw new CreateException ("Expected one affected row but update returned" + rowsAffected + 326 " for id=" + ctx.getId()); 327 } 328 } 329 catch(SQLException e) 330 { 331 if(exceptionProcessor != null && exceptionProcessor.isDuplicateKey(e)) 332 { 333 log.error("Failed to create instance.", e); 334 throw new CreateException ( 335 "Integrity constraint violation. Possibly unique key violation or invalid foreign key value." 336 ); 337 } 338 else 339 { 340 log.error("Could not create entity", e); 341 CreateException ce = new CreateException ("Could not create entity: " + e); 342 ce.initCause(e); 343 throw ce; 344 } 345 } 346 finally 347 { 348 JDBCUtil.safeClose(ps); 349 JDBCUtil.safeClose(c); 350 } 351 352 for(int fieldInd = 0; fieldInd < insertFields.length; ++fieldInd) 354 { 355 insertFields[fieldInd].setClean(ctx); 356 } 357 } 358 359 protected PreparedStatement prepareStatement(Connection c, String sql, EntityEnterpriseContext ctx) throws SQLException 360 { 361 return c.prepareStatement(sql); 362 } 363 364 protected int executeInsert(int paramIndex, PreparedStatement ps, EntityEnterpriseContext ctx) throws SQLException 365 { 366 return ps.executeUpdate(); 367 } 368 369 protected void afterInsert(EntityEnterpriseContext ctx) throws CreateException 370 { 371 } 372 373 protected Object getPrimaryKey(EntityEnterpriseContext ctx) 374 { 375 return entity.extractPrimaryKeyFromInstance(ctx); 376 } 377 } 378 | Popular Tags |