package org.jboss.seam.contexts; import java.io.Serializable; import javax.persistence.EntityManager; import org.hibernate.Session; import org.jboss.seam.Component; import org.jboss.seam.Seam; import org.jboss.seam.persistence.HibernatePersistenceProvider; import org.jboss.seam.persistence.PersistenceContexts; import org.jboss.seam.persistence.PersistenceProvider; import org.jboss.seam.transaction.Transaction; /** * A swizzled entity reference, consisting of the class, * id and persistence context name. * * @see EntityBean * @see org.jboss.seam.persistence.ManagedEntityInterceptor * * @author Gavin King * */ class PassivatedEntity implements Serializable { private static final long serialVersionUID = 6565440294007267788L; private Object id; private Object version; private String persistenceContext; private Class<?> entityClass; //TODO: make this transient, and serialize only the class name.. private PassivatedEntity(Object id, Object version, Class<?> entityClass, String persistenceContext) { this.id = id; this.persistenceContext = persistenceContext; this.entityClass = entityClass; this.version = version; } private String getPersistenceContext() { return persistenceContext; } private Object getId() { return id; } private Class<?> getEntityClass() { return entityClass; } public boolean isVersioned() { return version!=null; } public Object toEntityReference(boolean checkVersion) { Object persistenceContext = Component.getInstance( getPersistenceContext() ); if ( persistenceContext==null ) { return null; } else { if (persistenceContext instanceof EntityManager) { return getEntityFromEntityManager(persistenceContext, checkVersion); } else { return getEntityFromHibernate(persistenceContext, checkVersion); } } } private Object getEntityFromHibernate(Object persistenceContext, boolean checkVersion) { //TODO: split this out to somewhere to isolate the Hibernate dependency!! Session session = (Session) persistenceContext; if ( session.isOpen() ) { Object result = session.load( getEntityClass(), (Serializable) getId() ); if (result!=null && checkVersion) { checkVersion(session, result); } return result; } else { return null; } } private void checkVersion(Session session, Object result) { Object version = HibernatePersistenceProvider.getVersion(result, session); if (version!=null) { HibernatePersistenceProvider.checkVersion(result, session, this.version, version); } } private Object getEntityFromEntityManager(Object persistenceContext, boolean checkVersion) { EntityManager em = (EntityManager) persistenceContext; if ( em.isOpen() ) { Object result = em.getReference( getEntityClass(), getId() ); if (result!=null && checkVersion) { checkVersion(em, result); } return result; } else { return null; } } private void checkVersion(EntityManager em, Object result) { Object version = PersistenceProvider.instance().getVersion(result, em); if (version!=null) { PersistenceProvider.instance().checkVersion(result, em, this.version, version); } } /*public static Object unpassivateEntityAndCheckVersion(String key) { return unpassivateEntity(key, true); } public static Object unpassivateEntity(String key) { return unpassivateEntity(key, false); } private static Object unpassivateEntity(String key, boolean checkVersion) { PassivatedEntity passivatedEntity = (PassivatedEntity) Contexts.getConversationContext().get(key); return passivatedEntity==null ? null : passivatedEntity.toEntityReference(checkVersion); }*/ public static PassivatedEntity passivateEntity(Object value) { Class entityClass = Seam.getEntityClass( value.getClass() ); if (entityClass!=null) { for ( String persistenceContextName: PersistenceContexts.instance().getTouchedContexts() ) { Object persistenceContext = Component.getInstance(persistenceContextName); return createPassivatedEntity(value, entityClass, persistenceContextName, persistenceContext); } } return null; } private static PassivatedEntity createPassivatedEntity(Object value, Class entityClass, String persistenceContextName, Object persistenceContext) { if (persistenceContext instanceof EntityManager) { return createUsingEntityManager(value, entityClass, persistenceContextName, persistenceContext); } else { return createUsingHibernate(value, entityClass, persistenceContextName, persistenceContext); } } /*private static String storeConversationContext(PassivatedEntity result) { if (result==null) { return null; } else { String key = result.getKey(); Contexts.getConversationContext().set( key, result ); return key; } } private String getKey() { return "org.jboss.seam.passivatedEntity." + entityClass.getName() + '#' + getId(); }*/ private static PassivatedEntity createUsingHibernate(Object value, Class entityClass, String persistenceContextName, Object persistenceContext) { //TODO: split this out to somewhere to isolate the Hibernate dependency!! Session session = (Session) persistenceContext; if ( isManaged(value, session) ) { Object id = session.getIdentifier(value); Object version = HibernatePersistenceProvider.getVersion(value, session); return create(entityClass, persistenceContextName, id, version); } else { return null; } } private static boolean isManaged(Object value, Session session) { boolean managed; try { managed = session.isOpen() && session.contains(value); } catch (RuntimeException re) { //just in case! //TODO; deleteme managed = false; } return managed; } private static PassivatedEntity createUsingEntityManager(Object value, Class entityClass, String persistenceContextName, Object persistenceContext) { EntityManager em = (EntityManager) persistenceContext; if ( isManaged(value, em) ) { Object id = PersistenceProvider.instance().getId(value, em); Object version = PersistenceProvider.instance().getVersion(value, em); return create(entityClass, persistenceContextName, id, version); } else { return null; } } private static boolean isManaged(Object value, EntityManager em) { boolean managed; try { managed = em.isOpen() && em.contains(value); } catch (RuntimeException re) { //workaround for bug in HEM! //TODO; deleteme managed = false; } return managed; } private static PassivatedEntity create(Class entityClass, String persistenceContextName, Object id, Object version) { if (id==null) { //this can happen if persist() fails in Hibernate return null; } else { return new PassivatedEntity(id, version, entityClass, persistenceContextName); } } static boolean isTransactionRolledBackOrMarkedRollback() { try { return Transaction.instance().isRolledBackOrMarkedRollback(); } catch (Exception e) { return false; } } @Override public String toString() { return entityClass + "#" + id; } }