package org.jboss.ejb.plugins;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.ejb.EJBException;
import org.jboss.ejb.EntityEnterpriseContext;
import org.jboss.ejb.GenericEntityObjectFactory;
import org.jboss.ha.framework.interfaces.DistributedState;
import org.jboss.metadata.BeanMetaData;
import org.jboss.metadata.ClusterConfigMetaData;
import org.jboss.metadata.EntityMetaData;
public class CMPClusteredInMemoryPersistenceManager implements org.jboss.ejb.EntityPersistenceStore
{
protected org.jboss.ejb.EntityContainer con = null;
protected Field idField = null;
protected DistributedState ds = null;
protected String DS_CATEGORY = null;
protected Method isModified = null;
public CMPClusteredInMemoryPersistenceManager ()
{
}
public void setContainer (org.jboss.ejb.Container con)
{
this.con = (org.jboss.ejb.EntityContainer)con;
}
public void create () throws Exception
{
BeanMetaData bmd = con.getBeanMetaData();
ClusterConfigMetaData ccmd = bmd.getClusterConfigMetaData ();
String partitionName = ccmd.getPartitionName();
String name = "jboss:service=DistributedState,partitionName="+partitionName;
ds = (DistributedState)org.jboss.system.Registry.lookup (name);
String ejbName = bmd.getEjbName();
this.DS_CATEGORY = "CMPClusteredInMemoryPersistenceManager-" + ejbName;
idField = con.getBeanClass ().getField ("id");
try
{
isModified = con.getBeanClass ().getMethod ("isModified", new Class[0]);
if (!isModified.getReturnType ().equals (Boolean.TYPE))
isModified = null; }
catch (NoSuchMethodException ignored)
{
}
}
public void start () throws Exception
{
}
public void stop ()
{
}
public void destroy ()
{
}
public Object createBeanClassInstance () throws Exception
{
return con.getBeanClass ().newInstance ();
}
public void initEntity (EntityEnterpriseContext ctx)
{
Object instance = ctx.getInstance ();
Class ejbClass = instance.getClass ();
Field cmpField;
Class cmpFieldType;
EntityMetaData metaData = (EntityMetaData)con.getBeanMetaData ();
java.util.Iterator i= metaData.getCMPFields ();
while(i.hasNext ())
{
try
{
try
{
cmpField = ejbClass.getField ((String)i.next ());
cmpFieldType = cmpField.getType ();
if (cmpFieldType.equals (boolean.class))
{
cmpField.setBoolean (instance,false);
}
else if (cmpFieldType.equals (byte.class))
{
cmpField.setByte (instance,(byte)0);
}
else if (cmpFieldType.equals (int.class))
{
cmpField.setInt (instance,0);
}
else if (cmpFieldType.equals (long.class))
{
cmpField.setLong (instance,0L);
}
else if (cmpFieldType.equals (short.class))
{
cmpField.setShort (instance,(short)0);
}
else if (cmpFieldType.equals (char.class))
{
cmpField.setChar (instance,'\u0000');
}
else if (cmpFieldType.equals (double.class))
{
cmpField.setDouble (instance,0d);
}
else if (cmpFieldType.equals (float.class))
{
cmpField.setFloat (instance,0f);
}
else
{
cmpField.set (instance,null);
}
}
catch (NoSuchFieldException e)
{
}
}
catch (Exception e)
{
throw new EJBException (e);
}
}
}
public Object createEntity (Method m, Object[] args,
EntityEnterpriseContext ctx) throws Exception
{
try
{
Object id = idField.get (ctx.getInstance ());
if (this.ds.get (DS_CATEGORY, id.toString ()) != null)
throw new javax.ejb.DuplicateKeyException ("Already exists:"+id);
storeEntity (id, ctx.getInstance ());
return id;
}
catch (IllegalAccessException e)
{
throw new javax.ejb.CreateException ("Could not create entity:"+e);
}
}
public Object postCreateEntity (Method m, Object[] args,
EntityEnterpriseContext ctx) throws Exception
{
return null;
}
public Object findEntity (Method finderMethod, Object[] args,
EntityEnterpriseContext instance,
GenericEntityObjectFactory factory) throws Exception
{
if (finderMethod.getName ().equals ("findByPrimaryKey"))
{
if (this.ds.get (DS_CATEGORY, args[0].toString ()) == null)
throw new javax.ejb.FinderException (args[0]+" does not exist");
return factory.getEntityEJBObject(args[0]);
}
else
return null;
}
public Collection findEntities (Method finderMethod, Object[] args,
EntityEnterpriseContext instance, GenericEntityObjectFactory factory) throws Exception
{
Collection results = Collections.EMPTY_LIST;
if (finderMethod.getName ().equals ("findAll"))
{
Collection tmpColl = this.ds.getAllKeys (DS_CATEGORY);
if (tmpColl != null)
results = GenericEntityObjectFactory.UTIL.getEntityCollection(factory, tmpColl);
}
return results;
}
public void activateEntity (EntityEnterpriseContext instance) { }
public void loadEntity (EntityEnterpriseContext ctx)
{
try
{
byte[] content = (byte[])this.ds.get (this.DS_CATEGORY, ctx.getId ().toString ());
if (content == null)
throw new javax.ejb.EJBException ("No entry exists (any more?) with this id: " + ctx.getId ());
java.io.ObjectInputStream in = new org.jboss.ejb.plugins.CMPClusteredInMemoryPersistenceManager.CMPObjectInputStream (
new java.io.ByteArrayInputStream (content));
Object obj = ctx.getInstance ();
Field[] f = obj.getClass ().getFields ();
for (int i = 0; i < f.length; i++)
{
f[i].set (obj, in.readObject ());
}
in.close ();
}
catch (javax.ejb.EJBException e)
{
throw e;
}
catch (Exception e)
{
throw new EJBException ("Load failed", e);
}
}
public boolean isStoreRequired (EntityEnterpriseContext ctx) throws Exception
{
if(isModified == null)
{
return true;
}
Object[] args =
{};
Boolean modified = (Boolean) isModified.invoke (ctx.getInstance (), args);
return modified.booleanValue ();
}
public boolean isModified (EntityEnterpriseContext ctx) throws Exception
{
return isStoreRequired(ctx);
}
public void storeEntity (EntityEnterpriseContext ctx) throws java.rmi.RemoteException
{
try
{
storeEntity (ctx.getId (), ctx.getInstance ());
}
catch (Exception e)
{
throw new java.rmi.RemoteException (e.toString ());
}
}
public void passivateEntity (EntityEnterpriseContext instance)
{
}
public void removeEntity (EntityEnterpriseContext ctx) throws javax.ejb.RemoveException
{
try
{
if (this.ds.remove (this.DS_CATEGORY, ctx.getId ().toString (), false) == null)
throw new javax.ejb.RemoveException ("Could not remove bean:" +
ctx.getId ());
}
catch (Exception e)
{
throw new javax.ejb.RemoveException (e.toString ());
}
}
protected void storeEntity (Object id, Object obj) throws Exception
{
try
{
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream ();
java.io.ObjectOutputStream out = new org.jboss.ejb.plugins.CMPClusteredInMemoryPersistenceManager.CMPObjectOutputStream (baos);
Field[] f = obj.getClass ().getFields ();
for (int i = 0; i < f.length; i++)
{
out.writeObject (f[i].get (obj));
}
out.close ();
this.ds.set (this.DS_CATEGORY, id.toString (), baos.toByteArray (), false);
} catch (Exception e)
{
throw new EJBException ("Store failed", e);
}
}
static class CMPObjectOutputStream extends java.io.ObjectOutputStream
{
public CMPObjectOutputStream (java.io.OutputStream out) throws IOException
{
super (out);
enableReplaceObject (true);
}
protected Object replaceObject (Object obj)
throws IOException
{
if (obj instanceof javax.ejb.EJBObject)
return ((javax.ejb.EJBObject)obj).getHandle ();
return obj;
}
}
static class CMPObjectInputStream extends java.io.ObjectInputStream
{
public CMPObjectInputStream (java.io.InputStream in) throws IOException
{
super (in);
enableResolveObject (true);
}
protected Object resolveObject (Object obj)
throws IOException
{
if (obj instanceof javax.ejb.Handle)
return ((javax.ejb.Handle)obj).getEJBObject ();
return obj;
}
}
}