/jboss-as-7.1.1.Final/cmp/src/main/java/org/jboss/as/cmp/jdbc/JDBCAbstractCreateCommand.java
# · Java · 303 lines · 214 code · 36 blank · 53 comment · 49 complexity · 24b248ebdad2a203753d8a9cca2a17e1 MD5 · raw file
- /*
- * JBoss, Home of Professional Open Source.
- * Copyright 2011, Red Hat, Inc., and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
- package org.jboss.as.cmp.jdbc;
- import java.lang.reflect.Method;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.List;
- import javax.ejb.CreateException;
- import org.jboss.as.cmp.CmpMessages;
- import static org.jboss.as.cmp.CmpMessages.MESSAGES;
- import org.jboss.as.cmp.context.CmpEntityBeanContext;
- import org.jboss.as.cmp.jdbc.bridge.JDBCCMPFieldBridge;
- import org.jboss.as.cmp.jdbc.bridge.JDBCCMRFieldBridge;
- import org.jboss.as.cmp.jdbc.bridge.JDBCEntityBridge;
- import org.jboss.as.cmp.jdbc.bridge.JDBCFieldBridge;
- import org.jboss.as.cmp.jdbc.metadata.JDBCEntityCommandMetaData;
- import org.jboss.logging.Logger;
- import org.jboss.security.AuthenticationManager;
- /**
- * Base class for create commands that drives the operation sequence.
- *
- * @author <a href="mailto:jeremy@boynes.com">Jeremy Boynes</a>
- * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
- */
- public abstract class JDBCAbstractCreateCommand implements JDBCCreateCommand {
- protected Logger log;
- protected boolean debug;
- protected boolean trace;
- protected JDBCEntityBridge entity;
- protected AuthenticationManager securityManager;
- protected boolean createAllowed;
- protected SQLExceptionProcessor exceptionProcessor;
- protected String insertSQL;
- protected JDBCFieldBridge[] insertFields;
- protected boolean insertAfterEjbPostCreate;
- // Generated fields
- private JDBCCMPFieldBridge createdPrincipal;
- private JDBCCMPFieldBridge createdTime;
- private JDBCCMPFieldBridge updatedPrincipal;
- private JDBCCMPFieldBridge updatedTime;
- public void init(JDBCStoreManager manager) {
- log = Logger.getLogger(getClass().getName() + '.' + manager.getMetaData().getName());
- debug = log.isDebugEnabled();
- trace = log.isTraceEnabled();
- entity = (JDBCEntityBridge) manager.getEntityBridge();
- insertAfterEjbPostCreate = manager.getCmpConfig().isInsertAfterEjbPostCreate();
- // set create allowed
- createAllowed = true;
- JDBCFieldBridge[] pkFields = entity.getPrimaryKeyFields();
- for (int i = 0; i < pkFields.length; i++) {
- if (pkFields[i].isReadOnly()) {
- createAllowed = false;
- log.debug("Create will not be allowed because pk field "
- + pkFields[i].getFieldName() + "is read only.");
- break;
- }
- }
- initGeneratedFields();
- JDBCEntityCommandMetaData entityCommand = manager.getMetaData().getEntityCommand();
- if (entityCommand == null) {
- throw MESSAGES.entityCommandIsNull();
- }
- initEntityCommand(entityCommand);
- initInsertFields();
- initInsertSQL();
- }
- protected void initEntityCommand(JDBCEntityCommandMetaData entityCommand) {
- exceptionProcessor = null;
- }
- public Object execute(Method m, Object[] args, CmpEntityBeanContext ctx) throws CreateException {
- // TODO: implement this logic nicer
- if (insertAfterEjbPostCreate) {
- if (!JDBCEntityBridge.isEjbCreateDone(ctx)) {
- checkCreateAllowed();
- generateFields(ctx);
- JDBCEntityBridge.setEjbCreateDone(ctx);
- } else {
- beforeInsert(ctx);
- performInsert(ctx);
- afterInsert(ctx);
- JDBCEntityBridge.setCreated(ctx);
- }
- } else {
- checkCreateAllowed();
- generateFields(ctx);
- beforeInsert(ctx);
- performInsert(ctx);
- afterInsert(ctx);
- JDBCEntityBridge.setCreated(ctx);
- }
- return getPrimaryKey(ctx);
- }
- protected void checkCreateAllowed() throws CreateException {
- if (!createAllowed) {
- throw MESSAGES.creationNotAllowedPKReadOnly();
- }
- }
- protected JDBCCMPFieldBridge getGeneratedPKField() {
- // extract the pk field to be generated
- JDBCCMPFieldBridge pkField = null;
- JDBCFieldBridge[] pkFields = entity.getPrimaryKeyFields();
- for (int i = 0; i < pkFields.length; ++i) {
- if (pkField != null)
- throw MESSAGES.generationOnlySupportedWithSinglePK();
- pkField = (JDBCCMPFieldBridge) pkFields[i];
- }
- return pkField;
- }
- protected void initGeneratedFields() {
- createdPrincipal = entity.getCreatedPrincipalField();
- if (securityManager == null && createdPrincipal != null) {
- throw MESSAGES.noSecurityDomainForCreatedBy();
- }
- updatedPrincipal = entity.getUpdatedPrincipalField();
- if (securityManager == null && updatedPrincipal != null) {
- throw MESSAGES.noSecurityDomainForCreatedBy();
- }
- createdTime = entity.getCreatedTimeField();
- updatedTime = entity.getUpdatedTimeField();
- }
- protected void generateFields(CmpEntityBeanContext ctx) throws CreateException {
- // Audit principal fields
- if (securityManager != null) {
- String principalName = ctx.getCallerPrincipal().getName();
- if (createdPrincipal != null && createdPrincipal.getInstanceValue(ctx) == null) {
- createdPrincipal.setInstanceValue(ctx, principalName);
- }
- /*
- if(updatedPrincipal != null && updatedPrincipal.getInstanceValue(ctx) == null)
- {
- updatedPrincipal.setInstanceValue(ctx, principalName);
- }
- */
- }
- // Audit time fields
- Date date = null;
- if (createdTime != null && createdTime.getInstanceValue(ctx) == null) {
- date = new Date();
- createdTime.setInstanceValue(ctx, date);
- }
- /*
- if(updatedTime != null && updatedTime.getInstanceValue(ctx) == null)
- {
- if(date == null)
- date = new Date();
- updatedTime.setInstanceValue(ctx, date);
- }
- */
- }
- protected void initInsertFields() {
- JDBCFieldBridge[] fields = entity.getTableFields();
- List insertFieldsList = new ArrayList(fields.length);
- for (int i = 0; i < fields.length; i++) {
- JDBCFieldBridge field = fields[i];
- if (isInsertField(field))
- insertFieldsList.add(field);
- }
- insertFields = (JDBCFieldBridge[]) insertFieldsList.toArray(new JDBCFieldBridge[insertFieldsList.size()]);
- }
- protected boolean isInsertField(JDBCFieldBridge field) {
- boolean result =
- !(field instanceof JDBCCMRFieldBridge)
- && field.getJDBCType() != null
- && !field.isReadOnly();
- if (field instanceof JDBCCMPFieldBridge)
- result = result && !((JDBCCMPFieldBridge) field).isRelationTableField();
- return result;
- }
- protected void initInsertSQL() {
- StringBuffer sql = new StringBuffer(250);
- sql.append(SQLUtil.INSERT_INTO)
- .append(entity.getQualifiedTableName())
- .append(" (");
- SQLUtil.getColumnNamesClause(insertFields, sql);
- sql.append(')')
- .append(SQLUtil.VALUES).append('(');
- SQLUtil.getValuesClause(insertFields, sql)
- .append(')');
- insertSQL = sql.toString();
- if (debug)
- log.debug("Insert Entity SQL: " + insertSQL);
- }
- protected void beforeInsert(CmpEntityBeanContext ctx) throws CreateException {
- }
- protected void performInsert(CmpEntityBeanContext ctx) throws CreateException {
- Connection c = null;
- PreparedStatement ps = null;
- boolean throwRuntimeExceptions = entity.getMetaData().getThrowRuntimeExceptions();
- // if metadata is true, the getConnection is done inside
- // its own try catch block to throw a runtime exception (EJBException)
- if (throwRuntimeExceptions) {
- try {
- c = entity.getDataSource().getConnection();
- } catch (SQLException sqle) {
- javax.ejb.EJBException ejbe = new javax.ejb.EJBException("Could not get a connection; " + sqle);
- ejbe.initCause(sqle);
- throw ejbe;
- }
- }
- try {
- if (log.isDebugEnabled()) {
- log.debug("Executing SQL: " + insertSQL);
- }
- // if metadata is false, the getConnection is done inside this try catch block
- if (!throwRuntimeExceptions) {
- c = entity.getDataSource().getConnection();
- }
- ps = prepareStatement(c, insertSQL, ctx);
- // set the parameters
- int index = 1;
- for (int fieldInd = 0; fieldInd < insertFields.length; ++fieldInd) {
- index = insertFields[fieldInd].setInstanceParameters(ps, index, ctx);
- }
- // execute statement
- int rowsAffected = executeInsert(index, ps, ctx);
- if (rowsAffected != 1) {
- throw CmpMessages.MESSAGES.expectedOneRow(rowsAffected, ctx.getPrimaryKey());
- }
- } catch (SQLException e) {
- if (exceptionProcessor != null && exceptionProcessor.isDuplicateKey(e)) {
- throw CmpMessages.MESSAGES.uniqueKeyViolationInvalidFk(ctx.getPrimaryKey());
- } else {
- throw CmpMessages.MESSAGES.couldNotCreateEntity(e);
- }
- } finally {
- JDBCUtil.safeClose(ps);
- JDBCUtil.safeClose(c);
- }
- // Mark the inserted fields as clean.
- for (int fieldInd = 0; fieldInd < insertFields.length; ++fieldInd) {
- insertFields[fieldInd].setClean(ctx);
- }
- }
- protected PreparedStatement prepareStatement(Connection c, String sql, CmpEntityBeanContext ctx) throws SQLException {
- return c.prepareStatement(sql);
- }
- protected int executeInsert(int paramIndex, PreparedStatement ps, CmpEntityBeanContext ctx) throws SQLException {
- return ps.executeUpdate();
- }
- protected void afterInsert(CmpEntityBeanContext ctx) throws CreateException {
- }
- protected Object getPrimaryKey(CmpEntityBeanContext ctx) {
- return entity.extractPrimaryKeyFromInstance(ctx);
- }
- }