package org.mobicents.slee.container.deployment.profile.jpa;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javax.slee.SLEEException;
import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.ProfileSpecificationComponent;
import org.mobicents.slee.container.component.deployment.ClassPool;
import org.mobicents.slee.container.component.profile.ProfileAttribute;
import org.mobicents.slee.container.component.profile.ProfileEntity;
import org.mobicents.slee.container.component.profile.ProfileEntityFactory;
import org.mobicents.slee.container.deployment.profile.ClassGeneratorUtils;
import org.mobicents.slee.container.security.Utility;
/**
*
* Generates the concrete profile entity factory class for a profile spec
* @author martins
*/
public class ConcreteProfileEntityFactoryGenerator {
private static final Logger logger = Logger.getLogger(ConcreteProfileEntityFactoryGenerator.class);
private final ProfileSpecificationComponent profileComponent;
private final Class<?> profileEntityClass;
private final Map<String, Class<?>> profileEntityAttributeArrayValueClasses;
public ConcreteProfileEntityFactoryGenerator(ProfileSpecificationComponent profileComponent, Class<?> profileEntityClass, Map<String, Class<?>> profileEntityAttributeArrayValueClasses) {
this.profileComponent = profileComponent;
this.profileEntityClass = profileEntityClass;
this.profileEntityAttributeArrayValueClasses = profileEntityAttributeArrayValueClasses;
}
/*
* Generates the profile entity factory class
*/
public Class<?> generateClass() {
CtClass ctClass = null;
try {
ClassPool classPool = profileComponent.getClassPool();
Collection<ProfileAttribute> profileAttributes = profileComponent.getProfileAttributes().values();
String className = profileEntityClass.getName() + "F";
ctClass = classPool.makeClass(className);
CtClass profileEntityFactoryClass = classPool.get(ProfileEntityFactory.class.getName());
CtClass[] interfaces = new CtClass[] { profileEntityFactoryClass };
ctClass.setInterfaces(interfaces);
// copy newInstance method from interface and generate body
CtMethod newInstanceMethod = profileEntityFactoryClass.getDeclaredMethod("newInstance");
CtMethod newInstanceMethodCopy = CtNewMethod.copy(newInstanceMethod, ctClass, null);
String newInstanceMethodCopyBody =
"{ "+
profileEntityClass.getName()+" profileEntity = new "+profileEntityClass.getName()+"();" +
" profileEntity.setTableName($1); " +
" profileEntity.setProfileName($2); " +
" return profileEntity; " +
"}";
if (logger.isDebugEnabled()) {
logger.debug( "\nAdding method named "+newInstanceMethodCopy.getName()+" with body "+newInstanceMethodCopy+" , into class " + className );
}
newInstanceMethodCopy.setBody(newInstanceMethodCopyBody);
ctClass.addMethod(newInstanceMethodCopy);
// copy copyAttributes method from interface and generate body
CtMethod copyAttributesMethod = profileEntityFactoryClass.getDeclaredMethod("copyAttributes");
CtMethod copyAttributesMethodCopy = CtNewMethod.copy(copyAttributesMethod, ctClass, null);
// body header
String copyAttributesMethodCopyBody =
"{ "+
profileEntityClass.getName()+" newProfileEntity = ("+profileEntityClass.getName()+") $2; " +
profileEntityClass.getName()+" oldProfileEntity = ("+profileEntityClass.getName()+") $1; ";
// process fields copy
String profileEntityAttributeArrayValueClassName = null;
if(System.getSecurityManager()==null)
{
for (ProfileAttribute profileAttribute : profileAttributes) {
String accessorMethodSufix = ClassGeneratorUtils.getPojoCmpAccessorSufix(profileAttribute.getName());
if (profileAttribute.isArray()) {
profileEntityAttributeArrayValueClassName = profileEntityAttributeArrayValueClasses.get(profileAttribute.getName()).getName();
copyAttributesMethodCopyBody +=
"if (oldProfileEntity.get"+accessorMethodSufix+"() != null) { " +
// if the target list already exists then empty it so elements get deleted, otherwise create new
List.class.getName() + " new"+ profileAttribute.getName() + " = newProfileEntity.get"+accessorMethodSufix+"(); " +
"if (new"+profileAttribute.getName()+" == null) { new"+ profileAttribute.getName() + " = new " + LinkedList.class.getName() + "(); } else { new"+profileAttribute.getName()+".clear(); } " +
// extract list to copy
List.class.getName() + " old"+ profileAttribute.getName() + " = oldProfileEntity.get" + accessorMethodSufix + "(); " +
// iterate each list element
"for ("+Iterator.class.getName()+" i = old"+profileAttribute.getName()+".iterator(); i.hasNext();) { " +
profileEntityAttributeArrayValueClassName+" oldArrayValue = ("+profileEntityAttributeArrayValueClassName+") i.next(); " +
profileEntityAttributeArrayValueClassName+" newArrayValue = new "+profileEntityAttributeArrayValueClassName+"(); " +
// link to profile entity
"newArrayValue.setOwner( newProfileEntity ); " +
// copy fields
"newArrayValue.setString( oldArrayValue.getString() ); " +
"newArrayValue.setSerializable( ("+Serializable.class.getName()+") "+ProfileEntity.class.getName()+".makeDeepCopy(oldArrayValue.getSerializable()) ); " +
"new"+profileAttribute.getName()+".add(newArrayValue); " +
"} " +
"newProfileEntity.set"+accessorMethodSufix+"(new"+profileAttribute.getName()+"); };";
}
else {
if (profileAttribute.isPrimitive()) {
// just copy value
copyAttributesMethodCopyBody +=
" newProfileEntity.set"+accessorMethodSufix+"(oldProfileEntity.get"+accessorMethodSufix+"()); ";
}
else {
// just copy value but do a deep copy
copyAttributesMethodCopyBody +=
" if (oldProfileEntity.get"+accessorMethodSufix+"() != null) { newProfileEntity.set"+accessorMethodSufix+"(("+profileAttribute.getType().getName()+")"+ProfileEntity.class.getName()+".makeDeepCopy(oldProfileEntity.get"+accessorMethodSufix+"())); }; ";
}
}
}
}else
{
for (ProfileAttribute profileAttribute : profileAttributes) {
String accessorMethodSufix = ClassGeneratorUtils.getPojoCmpAccessorSufix(profileAttribute.getName());
if (profileAttribute.isArray()) {
profileEntityAttributeArrayValueClassName = profileEntityAttributeArrayValueClasses.get(profileAttribute.getName()).getName();
copyAttributesMethodCopyBody +=
"if ("+Utility.class.getName()+".makeSafeProxyCall(oldProfileEntity,\"get"+accessorMethodSufix+"\",null,null) != null) {" +
"" +
// if the target list already exists then empty it so elements get deleted, otherwise create new
List.class.getName() + " new"+ profileAttribute.getName() + " = newProfileEntity.get"+accessorMethodSufix+"(); " +
"if (new"+profileAttribute.getName()+" == null) { new"+ profileAttribute.getName() + " = new " + LinkedList.class.getName() + "(); } else { new"+profileAttribute.getName()+".clear(); } " +
// extract list to copy
//List.class.getName() + " old"+ profileAttribute.getName() + " = oldProfileEntity.get" + accessorMethodSufix + "(); " +
List.class.getName() + " old"+ profileAttribute.getName() + " = ("+List.class.getName()+")"+Utility.class.getName()+".makeSafeProxyCall(oldProfileEntity,\"get"+accessorMethodSufix+"\",null,null);"+
// iterate each list element
Iterator.class.getName()+" i = "+Utility.class.getName()+".makeSafeProxyCall(old"+profileAttribute.getName()+",\"iterator\",null,null);"+
"for (; "+Utility.class.getName()+".evaluateNext(i);) { " +
profileEntityAttributeArrayValueClassName+" oldArrayValue = ("+profileEntityAttributeArrayValueClassName+") i.next();"+
profileEntityAttributeArrayValueClassName+" newArrayValue = new "+profileEntityAttributeArrayValueClassName+"(); " +
// link to profile entity
"newArrayValue.setOwner( newProfileEntity ); " +
// copy fields
"newArrayValue.setString( oldArrayValue.getString() ); " +
"newArrayValue.setSerializable( ("+Serializable.class.getName()+") "+ProfileEntity.class.getName()+".makeDeepCopy(oldArrayValue.getSerializable()) ); " +
"new"+profileAttribute.getName()+".add(newArrayValue); " +
"} " +
//"newProfileEntity.set"+accessorMethodSufix+"(new"+profileAttribute.getName()+"); };";
Utility.class.getName()+".makeSafeProxyCall(newProfileEntity,\"set"+accessorMethodSufix+"\",new Class[]{"+Utility.class.getName()+".getReturnType(oldProfileEntity,\"get"+accessorMethodSufix+"\")},new Object[]{new"+profileAttribute.getName()+"});}";
}
else {
if (profileAttribute.isPrimitive()) {
// just copy value
//copyAttributesMethodCopyBody +=
// " newProfileEntity.set"+accessorMethodSufix+"(oldProfileEntity.get"+accessorMethodSufix+"()); ";
copyAttributesMethodCopyBody +="Object value = "+Utility.class.getName()+".makeSafeProxyCall(oldProfileEntity,\"get"+accessorMethodSufix+"\",null,null);";
copyAttributesMethodCopyBody +=Utility.class.getName()+".makeSafeProxyCall(newProfileEntity,\"set"+accessorMethodSufix+"\",new Class[]{"+Utility.class.getName()+".getReturnType(oldProfileEntity,\"get"+accessorMethodSufix+"\")},new Object[]{value});";
}
else {
// just copy value but do a deep copy
copyAttributesMethodCopyBody +=
"if ("+Utility.class.getName()+".makeSafeProxyCall(oldProfileEntity,\"get"+accessorMethodSufix+"\",null,null) != null) "
+"{ Object value = "+Utility.class.getName()+".makeSafeProxyCall(oldProfileEntity,\"get"+accessorMethodSufix+"\",null,null);"
//+"newProfileEntity.set"+accessorMethodSufix+"(("+profileAttribute.getType().getName()+")"+ProfileEntity.class.getName()+".makeDeepCopy(value)); }; "
+Utility.class.getName()+".makeSafeProxyCall(newProfileEntity,\"set"+accessorMethodSufix+"\",new Class[]{"+Utility.class.getName()+".getReturnType(oldProfileEntity,\"get"+accessorMethodSufix+"\")},new Object[]{"+ProfileEntity.class.getName()+".makeDeepCopy(value)});"
+"}";
}
}
}
}
// body footer
copyAttributesMethodCopyBody += " }";
if (logger.isDebugEnabled()) {
logger.debug( "\nAdding method named "+copyAttributesMethodCopy.getName()+" with body "+copyAttributesMethodCopyBody+" , into class " + className );
}
copyAttributesMethodCopy.setBody(copyAttributesMethodCopyBody);
ctClass.addMethod(copyAttributesMethodCopy);
String deployDir = profileComponent.getDeploymentDir().getAbsolutePath();
// write class
if (logger.isDebugEnabled())
logger.debug( "Writing ProfileEntityFactory generated class ( "+ctClass.getName()+" ) to: " + deployDir );
ctClass.writeFile( deployDir );
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (Throwable e) {
throw new SLEEException(e.getMessage(),e);
}
finally {
if (ctClass != null) {
try {
ctClass.defrost();
}
catch (Throwable e) {
logger.error(e.getMessage(),e);
}
}
}
}
}