package org.mobicents.slee.container.deployment.profile; import java.util.Map; import javassist.CannotCompileException; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtMethod; import javassist.CtNewConstructor; import javassist.CtNewMethod; import javax.slee.SLEEException; import javax.slee.profile.ReadOnlyProfileException; 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.deployment.jaxb.descriptors.ProfileSpecificationDescriptorImpl; import org.mobicents.slee.container.deployment.ClassUtils; import org.mobicents.slee.container.profile.AbstractProfileCmpSlee10Wrapper; import org.mobicents.slee.container.profile.ProfileObject; /** * * The Profile CMP Slee 1.0 Wrapper is an object that implements the Profile CMP * Interface, wrapping the SLEE 1.1 real profile concrete object in a SLEE 1.0 * compatible interface. This class generates such objects. * * @author martins * */ public class ProfileCmpSlee10WrapperClassGenerator { private static final Logger logger = Logger.getLogger(ProfileCmpSlee10WrapperClassGenerator.class); /** * the component to process */ private final ProfileSpecificationComponent component; /** * * @param component */ public ProfileCmpSlee10WrapperClassGenerator(ProfileSpecificationComponent component) { this.component = component; } /** * * @throws Exception */ public void generateClass() throws Exception { ProfileSpecificationDescriptorImpl descriptor = component.getDescriptor(); ClassPool pool = component.getClassPool(); String profileCmpInterfaceName = descriptor.getProfileCMPInterface().getProfileCmpInterfaceName(); String wrapperClassName = profileCmpInterfaceName + "Slee10Wrapper" ; CtClass profileCmpInterface = null; CtClass wrapperClass = null; try { profileCmpInterface = pool.get(profileCmpInterfaceName); wrapperClass = pool.makeClass(wrapperClassName); wrapperClass.setSuperclass(pool.get(AbstractProfileCmpSlee10Wrapper.class.getName())); wrapperClass.addInterface(profileCmpInterface); } catch (Exception e) { throw new SLEEException(e.getMessage(),e); } // implement only methods from profile cmp and management interface that are also on user defined local object interface Map<String, CtMethod> methodsToImplement = ClassUtils.getInterfaceMethodsFromInterface(profileCmpInterface); // generate constructor try { CtClass[] constructorParameters = new CtClass[] { pool.get(ProfileObject.class.getName()) }; String constructorBody = "{ super($$); }"; CtConstructor constructor = CtNewConstructor.make(constructorParameters, new CtClass[]{}, constructorBody , wrapperClass); wrapperClass.addConstructor(constructor); } catch (CannotCompileException e) { throw new SLEEException(e.getMessage(),e); } // implement methods delegating to an object casted to the profile cmp concrete class generated by SLEE String profileCmpConcreteClassName = component.getProfileCmpConcreteClass().getName(); for (CtMethod ctMethod : methodsToImplement.values()) { implementMethod(wrapperClass, ctMethod,"(("+profileCmpConcreteClassName+")profileObject.getProfileConcrete())"); } // generate class file try { wrapperClass.writeFile(component.getDeploymentDir().getAbsolutePath()); if (logger.isDebugEnabled()) { logger.debug("Profile CMP SLEE 1.0 Wrapper Class " + wrapperClassName + " generated in the following path " + component.getDeploymentDir().getAbsolutePath()); } } catch (Exception e) { throw new SLEEException(e.getMessage(), e); } finally { wrapperClass.defrost(); } // load it and store it in the component try { component.setProfileCmpSlee10WrapperClass(component.getClassLoader().loadClass(wrapperClassName)); } catch (ClassNotFoundException e) { throw new SLEEException(e.getMessage(),e); } } private void implementMethod(CtClass concreteClass, CtMethod method, String interceptorAccess) throws Exception { // copy method to concrete class CtMethod newMethod = CtNewMethod.copy( method, concreteClass, null ); // generate body String returnStatement = method.getReturnType().equals(CtClass.voidType) ? "" : "return ($r)"; String body= "{ " + " try {" + returnStatement + interceptorAccess +'.'+ method.getName()+"($$);" + " } catch ("+ReadOnlyProfileException.class.getName()+" e) {" + " throw new "+UnsupportedOperationException.class.getName()+"(e.getMessage(),e);" + " }" + "}"; if(logger.isDebugEnabled()) { logger.debug("Instrumented method, name:"+method.getName()+", with body:\n"+body); } newMethod.setBody(body); // add to concrete class concreteClass.addMethod(newMethod); } }