package org.mobicents.slee.container.profile; import java.util.Map; import javax.slee.CreateException; import javax.slee.SLEEException; import javax.slee.TransactionRequiredLocalException; import javax.slee.profile.UnrecognizedProfileNameException; import javax.transaction.SystemException; import org.mobicents.slee.container.component.profile.ProfileEntity; import org.mobicents.slee.runtime.transaction.SleeTransactionManager; import org.mobicents.slee.runtime.transaction.TransactionalAction; /** * The transaction view of a profile table. * * @author martins * */ public class ProfileTableTransactionView { /** * the profile table */ private final ProfileTableImpl profileTable; /** * * @param profileTable */ public ProfileTableTransactionView(ProfileTableImpl profileTable) { this.profileTable = profileTable; } /** * * @return * @throws SLEEException */ private Map getTxData() throws SLEEException { final SleeTransactionManager txManager = profileTable .getSleeContainer().getTransactionManager(); txManager.mandateTransaction(); try { return txManager.getTransactionContext().getData(); } catch (SystemException e) { throw new SLEEException(e.getMessage(), e); } } /** * Retrieves a profile object for the table and specified profile name, * there is only one profile object per profile entity per transaction * * @param profileName * @return * @throws TransactionRequiredLocalException * @throws SLEEException */ public ProfileObject getProfile(String profileName) throws TransactionRequiredLocalException, SLEEException { Map txData = getTxData(); ProfileTransactionID key = new ProfileTransactionID(profileName, profileTable.getProfileTableName()); ProfileObject value = (ProfileObject) txData.get(key); if (value == null) { ProfileObjectPool pool = profileTable.getSleeContainer() .getProfileObjectPoolManagement().getObjectPool( profileTable.getProfileTableName()); value = pool.borrowObject(); passivateProfileObjectOnTxEnd(profileTable.getSleeContainer() .getTransactionManager(), value, pool); try { value.profileActivate(profileName); } catch (UnrecognizedProfileNameException e) { value.invalidateObject(); pool.invalidateObject(value); return null; } txData.put(key, value); } return value; } /** * * Retrieves a profile object for the table and specified profile entity, * there is only one profile object per profile entity per transaction * * @param profileEntity * @return * @throws TransactionRequiredLocalException * @throws SLEEException */ public ProfileObject getProfile(ProfileEntity profileEntity) throws TransactionRequiredLocalException, SLEEException { Map txData = getTxData(); ProfileTransactionID key = new ProfileTransactionID(profileEntity .getProfileName(), profileTable.getProfileTableName()); ProfileObject value = (ProfileObject) txData.get(key); if (value == null) { ProfileObjectPool pool = profileTable.getSleeContainer() .getProfileObjectPoolManagement().getObjectPool( profileTable.getProfileTableName()); value = pool.borrowObject(); passivateProfileObjectOnTxEnd(profileTable.getSleeContainer() .getTransactionManager(), value, pool); value.profileActivate(profileEntity); txData.put(key, value); } return value; } /** * * @param profileName * @return * @throws TransactionRequiredLocalException * @throws SLEEException * @throws CreateException */ public ProfileObject createProfile(String profileName) throws TransactionRequiredLocalException, SLEEException, CreateException { Map txData = getTxData(); ProfileTransactionID key = new ProfileTransactionID(profileName, profileTable.getProfileTableName()); ProfileObject value = (ProfileObject) txData.get(key); if (value == null) { ProfileObjectPool pool = profileTable.getSleeContainer() .getProfileObjectPoolManagement().getObjectPool( profileTable.getProfileTableName()); value = pool.borrowObject(); passivateProfileObjectOnTxEnd(profileTable.getSleeContainer() .getTransactionManager(), value, pool); value.profileCreate(profileName); txData.put(key, value); } return value; } /** * Adds transactional actions to the active transaction to passivate a * profile object. * * @param txManager * @param profileObject * @param pool */ public static void passivateProfileObjectOnTxEnd( SleeTransactionManager txManager, final ProfileObject profileObject, final ProfileObjectPool pool) { TransactionalAction afterRollbackAction = new TransactionalAction() { public void execute() { profileObject.invalidateObject(); pool.returnObject(profileObject); } }; TransactionalAction beforeCommitAction = new TransactionalAction() { public void execute() { if (profileObject.getState() == ProfileObjectState.READY) { if (!profileObject.getProfileEntity().isRemove()) { profileObject.fireAddOrUpdatedEventIfNeeded(); profileObject.profilePassivate(); } else { profileObject.profileRemove(true); } pool.returnObject(profileObject); } } }; try { txManager.addAfterRollbackAction(afterRollbackAction); txManager.addBeforeCommitPriorityAction(beforeCommitAction); } catch (SystemException e) { throw new SLEEException(e.getMessage(), e); } } /** * * @author martins * */ private class ProfileTransactionID { private final String profileName; private final String profileTableName; public ProfileTransactionID(String profileName, String profileTableName) { this.profileName = profileName; this.profileTableName = profileTableName; } @Override public int hashCode() { return profileTableName.hashCode() * 31 + ((profileName == null) ? 0 : profileName.hashCode()); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ProfileTransactionID other = (ProfileTransactionID) obj; if (profileName == null) { if (other.profileName != null) return false; } else if (!profileName.equals(other.profileName)) return false; return profileTableName.equals(other.profileTableName); } } }