package org.mockejb;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.ejb.*;
import org.apache.commons.logging.*;
import org.mockejb.interceptor.*;
public class BMPFinderHandler implements Aspect, Serializable {
private static Log logger = LogFactory.getLog( BMPFinderHandler.class.getName() );
protected EntityDatabase entityDatabase;
public BMPFinderHandler( final EntityDatabase entityDatabase ){
this.entityDatabase = entityDatabase;
}
public Pointcut getPointcut(){
return PointcutPair.and( new MethodPatternPointcut( "ejbFind" ),
new ClassPointcut( EntityBean.class, true) );
}
public void intercept( InvocationContext invocationContext ) throws Exception {
invocationContext.proceed();
BasicEjbDescriptor ejbDescriptor= (
BasicEjbDescriptor) invocationContext.getPropertyValue("descriptor");
MockEjbContext ejbContext = (
MockEjbContext) invocationContext.getPropertyValue( MockEjbContext.class.getName() );
if ( ejbDescriptor instanceof EntityBeanDescriptor &&
!((EntityBeanDescriptor) ejbDescriptor).isCMP() ) {
EntityBeanDescriptor descriptor = (EntityBeanDescriptor) ejbDescriptor;
invocationContext.proceed();
logger.debug("Intercepted "+invocationContext.getProxyMethod());
Object pkOrPkCollection = invocationContext.getReturnObject();
if ( ! (pkOrPkCollection instanceof Collection) &&
!(pkOrPkCollection instanceof EJBObject) &&
!(pkOrPkCollection instanceof EJBLocalObject)) {
Object entity = findInCacheOrCreate( descriptor, ejbContext,pkOrPkCollection);
invocationContext.setReturnObject( entity );
} else if ( pkOrPkCollection instanceof Collection) {
Collection pks = (Collection)pkOrPkCollection;
Iterator i = pks.iterator();
Collection resultingCollection = new ArrayList();
while( i.hasNext() ) {
Object pk = i.next();
if ( !(pk instanceof EJBObject) &&
!(pk instanceof EJBLocalObject)) {
Object entity = findInCacheOrCreate( descriptor, ejbContext, pk);
resultingCollection.add(entity);
}
}
invocationContext.setReturnObject( resultingCollection );
} }
}
protected Object findInCacheOrCreate( EntityBeanDescriptor descriptor,
MockEjbContext ejbContext, Object pk ) throws Exception {
Object newEntity = entityDatabase.find(descriptor.getHomeClass(), pk);
if (newEntity == null) {
logger.debug( "Entity "+descriptor.getIfaceClass().getName()+
" for PK "+pk+" was not found in the EntityDatabase. Will try to create the new entity and call ejbLoad");
GenericHome home = (GenericHome) ejbContext.getEJBLocalHome();
newEntity = home.genericCreate();
EjbBeanAccess beanAccess = (EjbBeanAccess) newEntity;
Object bean = beanAccess.getBean();
if (! (bean instanceof EntityBean)) {
throw new EJBException("Can't call ejbLoad on the "+bean.getClass().getName()+
" because it does not implement EntityBean interface. You can avod this error by"+
" adding the entity with PK "+pk+" to the EntityDatabase." );
}
MockEjbContext newEntityContext = beanAccess.getEjbContext();
newEntityContext.setPrimaryKey( pk );
EntityBean entityBean = (EntityBean)bean;
entityBean.ejbLoad();
}
return newEntity;
}
public boolean equals( Object obj ){
if ( obj instanceof BMPFinderHandler &&
entityDatabase.equals( ((BMPFinderHandler)obj).entityDatabase ) )
return true;
else
return false;
}
public int hashCode() {
return this.getClass().hashCode()+entityDatabase.hashCode();
}
}