/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, 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.ejb; import java.io.Serializable; import java.rmi.RemoteException; import java.security.Principal; import java.util.Collection; import java.util.Date; import javax.ejb.EJBContext; import javax.ejb.EJBException; import javax.ejb.EJBHome; import javax.ejb.EJBLocalHome; import javax.ejb.EJBLocalObject; import javax.ejb.EJBObject; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.Timer; import javax.ejb.TimerService; import javax.transaction.UserTransaction; import org.jboss.ejb.plugins.lock.NonReentrantLock; /** * The EntityEnterpriseContext is used to associate EntityBean instances * with metadata about it. * * @see EnterpriseContext * * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Oberg</a> * @author <a href="mailto:marc.fleury@telkel.com">Marc Fleury</a> * @author <a href="mailto:docodan@mvcsoft.com">Daniel OConnor</a> * @version $Revision: 81030 $ */ public class EntityEnterpriseContext extends EnterpriseContext { private EJBObject ejbObject; private EJBLocalObject ejbLocalObject; private EntityContext ctx; /** * True if this instance has been registered with the TM for transactional * demarcation. */ private boolean hasTxSynchronization = false; /** * Specifies whether the instance is associated with a transaction and should be synchronized. */ private GlobalTxEntityMap.TxAssociation txAssociation = GlobalTxEntityMap.NONE; /** * True if this instances' state is valid when a bean is called the state * is not synchronized with the DB but "valid" as long as the transaction * runs. */ private boolean valid = false; /** * Is this context in a readonly invocation. */ private boolean readOnly = false; /** * The persistence manager may attach any metadata it wishes to this * context here. */ private Object persistenceCtx; /** The cacheKey for this context */ private Object key; private NonReentrantLock methodLock = new NonReentrantLock(); /** used to force passivation after commit even if the co is not C */ private boolean passivateAfterCommit; public EntityEnterpriseContext(Object instance, Container con) throws RemoteException { super(instance, con); ctx = new EntityContextImpl(); try { AllowedOperationsAssociation.pushInMethodFlag(IN_SET_ENTITY_CONTEXT); ((EntityBean)instance).setEntityContext(ctx); } finally { AllowedOperationsAssociation.popInMethodFlag(); } } /** * A non-reentrant deadlock detectable lock that is used to protected against * entity bean reentrancy. * @return */ public NonReentrantLock getMethodLock() { return methodLock; } public void clear() { super.clear(); hasTxSynchronization = false; valid = false; readOnly = false; key = null; persistenceCtx = null; ejbObject = null; ejbLocalObject = null; txAssociation = GlobalTxEntityMap.NONE; passivateAfterCommit = false; } public void discard() throws RemoteException { ((EntityBean)instance).unsetEntityContext(); } public EJBContext getEJBContext() { return ctx; } public void setEJBObject(EJBObject eo) { ejbObject = eo; } public EJBObject getEJBObject() { // Context can have no EJBObject (created by finds) in which case // we need to wire it at call time if(ejbObject == null && con.getProxyFactory() != null) { ejbObject = (EJBObject)con.getProxyFactory().getEntityEJBObject(id); } return ejbObject; } public void setEJBLocalObject(EJBLocalObject eo) { ejbLocalObject = eo; } public EJBLocalObject getEJBLocalObject() { if(ejbLocalObject == null && con.getLocalHomeClass() != null) { ejbLocalObject = ((EntityContainer)con).getLocalProxyFactory().getEntityEJBLocalObject(id); } return ejbLocalObject; } public void setCacheKey(Object key) { this.key = key; } public Object getCacheKey() { return key; } public void setPersistenceContext(Object ctx) { this.persistenceCtx = ctx; } public Object getPersistenceContext() { return persistenceCtx; } public void hasTxSynchronization(boolean value) { hasTxSynchronization = value; } public boolean hasTxSynchronization() { return hasTxSynchronization; } public GlobalTxEntityMap.TxAssociation getTxAssociation() { return txAssociation; } public void setTxAssociation(GlobalTxEntityMap.TxAssociation txAssociation) { this.txAssociation = txAssociation; } public void setValid(boolean valid) { this.valid = valid; } public boolean isValid() { return valid; } public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } public boolean isReadOnly() { return readOnly; } public boolean isPassivateAfterCommit() { return passivateAfterCommit; } public void setPassivateAfterCommit(boolean passivateAfterCommit) { this.passivateAfterCommit = passivateAfterCommit; } public String toString() { return getContainer().getBeanMetaData().getEjbName() + '#' + getId(); } protected class EntityContextImpl extends EJBContextImpl implements EntityContext { public EJBHome getEJBHome() { AllowedOperationsAssociation.assertAllowedIn("getEJBHome", IN_SET_ENTITY_CONTEXT | IN_UNSET_ENTITY_CONTEXT | IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_FIND | IN_EJB_HOME | IN_EJB_ACTIVATE | IN_EJB_PASSIVATE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return super.getEJBHome(); } public EJBLocalHome getEJBLocalHome() { AllowedOperationsAssociation.assertAllowedIn("getEJBLocalHome", IN_SET_ENTITY_CONTEXT | IN_UNSET_ENTITY_CONTEXT | IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_FIND | IN_EJB_HOME | IN_EJB_ACTIVATE | IN_EJB_PASSIVATE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return super.getEJBLocalHome(); } public Principal getCallerPrincipal() { AllowedOperationsAssociation.assertAllowedIn("getCallerPrincipal", IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_FIND | IN_EJB_HOME | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return super.getCallerPrincipal(); } public boolean getRollbackOnly() { AllowedOperationsAssociation.assertAllowedIn("getRollbackOnly", IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_FIND | IN_EJB_HOME | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return super.getRollbackOnly(); } public void setRollbackOnly() { AllowedOperationsAssociation.assertAllowedIn("setRollbackOnly", IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_FIND | IN_EJB_HOME | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); super.setRollbackOnly(); } public boolean isCallerInRole(String id) { AllowedOperationsAssociation.assertAllowedIn("getCallerInRole", IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_FIND | IN_EJB_HOME | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return super.isCallerInRole(id); } public UserTransaction getUserTransaction() { AllowedOperationsAssociation.assertAllowedIn("getUserTransaction", NOT_ALLOWED); return super.getUserTransaction(); } public EJBObject getEJBObject() { AllowedOperationsAssociation.assertAllowedIn("getEJBObject", IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_ACTIVATE | IN_EJB_PASSIVATE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); if(((EntityContainer)con).getRemoteClass() == null) { throw new IllegalStateException( "No remote interface defined." ); } if (ejbObject == null) { // Create a new CacheKey Object cacheKey = ((EntityCache)((EntityContainer)con).getInstanceCache()).createCacheKey(id); EJBProxyFactory proxyFactory = con.getProxyFactory(); if(proxyFactory == null) { String defaultInvokerName = con.getBeanMetaData(). getContainerConfiguration().getDefaultInvokerName(); proxyFactory = con.lookupProxyFactory(defaultInvokerName); } ejbObject = (EJBObject)proxyFactory.getEntityEJBObject(cacheKey); } return ejbObject; } public EJBLocalObject getEJBLocalObject() { AllowedOperationsAssociation.assertAllowedIn("getEJBLocalObject", IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_ACTIVATE | IN_EJB_PASSIVATE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); if (con.getLocalHomeClass()==null) throw new IllegalStateException( "No local interface for bean." ); if (ejbLocalObject == null) { Object cacheKey = ((EntityCache)((EntityContainer)con).getInstanceCache()).createCacheKey(id); ejbLocalObject = ((EntityContainer)con).getLocalProxyFactory().getEntityEJBLocalObject(cacheKey); } return ejbLocalObject; } public Object getPrimaryKey() { AllowedOperationsAssociation.assertAllowedIn("getPrimaryKey", IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_ACTIVATE | IN_EJB_PASSIVATE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return id; } public TimerService getTimerService() throws IllegalStateException { AllowedOperationsAssociation.assertAllowedIn("getTimerService", IN_EJB_CREATE | IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_HOME | IN_EJB_ACTIVATE | IN_EJB_PASSIVATE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); return new TimerServiceWrapper(this, getContainer().getTimerService(id)); } } /** * Delegates to the underlying TimerService, after checking access */ public class TimerServiceWrapper implements TimerService { //private EnterpriseContext.EJBContextImpl context; private TimerService timerService; public TimerServiceWrapper(EnterpriseContext.EJBContextImpl ctx, TimerService timerService) { //this.context = ctx; this.timerService = timerService; } public Timer createTimer(long duration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException { assertAllowedIn("TimerService.createTimer"); return timerService.createTimer(duration, info); } public Timer createTimer(long initialDuration, long intervalDuration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException { assertAllowedIn("TimerService.createTimer"); return timerService.createTimer(initialDuration, intervalDuration, info); } public Timer createTimer(Date expiration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException { assertAllowedIn("TimerService.createTimer"); return timerService.createTimer(expiration, info); } public Timer createTimer(Date initialExpiration, long intervalDuration, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException { assertAllowedIn("TimerService.createTimer"); return timerService.createTimer(initialExpiration, intervalDuration, info); } public Collection getTimers() throws IllegalStateException, EJBException { assertAllowedIn("TimerService.getTimers"); return timerService.getTimers(); } private void assertAllowedIn(String timerMethod) { AllowedOperationsAssociation.assertAllowedIn(timerMethod, IN_EJB_POST_CREATE | IN_EJB_REMOVE | IN_EJB_LOAD | IN_EJB_STORE | IN_BUSINESS_METHOD | IN_EJB_TIMEOUT); } } }