/*
* Created on Mar 14, 2005
*
* The Open SLEE Project
*
* A SLEE for the People
*
* The source code contained in this file is in in the public domain.
* It can be used in any project or product without prior permission,
* license or royalty payments. There is no claim of correctness and
* NO WARRANTY OF ANY KIND provided with this code.
*/
package org.mobicents.slee.container.deployment;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javax.slee.management.DeploymentException;
import javax.slee.management.ManagementException;
import javax.slee.management.NotificationSource;
import javax.slee.management.SbbNotification;
import javax.slee.usage.SampleStatistics;
import javax.slee.usage.SbbUsageMBean;
import javax.slee.usage.UsageMBean;
import org.apache.log4j.Logger;
import org.mobicents.slee.container.component.SbbComponent;
import org.mobicents.slee.container.component.SleeComponentWithUsageParametersInterface;
import org.mobicents.slee.container.component.deployment.ClassPool;
import org.mobicents.slee.container.management.jmx.SbbUsageMBeanImpl;
import org.mobicents.slee.container.management.jmx.UsageMBeanImpl;
/**
* Generator for the concrete usage usage parameter mbean.
* @author F.Moggia
* @author <a href="mailto:michele.laporta@gmail.com">Michele La Porta</a>
* @author martins
*/
public class ConcreteUsageParameterMBeanGenerator {
private static Logger logger= Logger.getLogger(ConcreteUsageParameterMBeanGenerator.class);
private final SleeComponentWithUsageParametersInterface component;
public ConcreteUsageParameterMBeanGenerator(SleeComponentWithUsageParametersInterface component) {
this.component = component;
}
/**
* Create a constructor. This method simply records the input parameters in
* appropriately named fields.
*
* @param
* @param classes
*/
private void createConstructor(CtClass concreteClass, CtClass usageMBeanInterface, CtClass notificationSource)
throws Exception {
CtConstructor ctCons = new CtConstructor(new CtClass[]{usageMBeanInterface,notificationSource}, concreteClass);
ctCons.setBody("{ super($1,$2); }");
concreteClass.addConstructor(ctCons);
}
public void generateConcreteUsageParameterMBean(
) throws Exception {
Class usageParamInterfaceClass = component.getUsageParametersInterface();
if (usageParamInterfaceClass == null)
return;
ClassPool classPool = component.getClassPool();
String usageParamInterfaceName = usageParamInterfaceClass.getName();
CtClass usageParamInterface = classPool.get(usageParamInterfaceName);
CtClass usageMBeanInterface = null;
CtClass usageMBeanImplClass = null;
CtClass constructorSecondParameterCtClass = null;
if (component.isSlee11()) {
usageMBeanInterface = classPool.get(UsageMBean.class
.getName());
usageMBeanImplClass = classPool.get(UsageMBeanImpl.class
.getName());
constructorSecondParameterCtClass = classPool.get(NotificationSource.class
.getName());
}
else {
if (component instanceof SbbComponent) {
usageMBeanInterface = classPool.get(SbbUsageMBean.class
.getName());
usageMBeanImplClass = classPool.get(SbbUsageMBeanImpl.class
.getName());
constructorSecondParameterCtClass = classPool.get(SbbNotification.class.getName());
}
else {
throw new DeploymentException("only sbb components can have usage param mbeans in slee 1.0, how did this pass validation?!? component = "+component);
}
}
// generate the mbean interface
String concreteMBeanInterfaceName = usageParamInterfaceName + "MBean";
CtClass ctInterface = classPool.makeInterface(concreteMBeanInterfaceName);
ctInterface.addInterface(usageMBeanInterface);
// generate the mbean class
String concreteMBeanClassName = usageParamInterfaceName + "MBeanImpl";
CtClass ctClass = classPool.makeClass(concreteMBeanClassName);
ctClass.setSuperclass(usageMBeanImplClass);
ConcreteClassGeneratorUtils.createInterfaceLinks(ctClass,new CtClass[]{ctInterface});
if (logger.isDebugEnabled()) {
logger.debug("generating "+concreteMBeanInterfaceName+" and "+concreteMBeanClassName);
}
// create constructor
this.createConstructor(ctClass, classPool.get(Class.class.getName()),constructorSecondParameterCtClass);
CtMethod[] methods = usageParamInterface.getMethods();
for (int i = 0; i < methods.length; i++) {
// Generate the concrete method.
generateAbstractMethod(ctInterface, methods[i]);
generateConcreteMethod(ctClass, methods[i]);
}
String deploymentPathStr = component.getDeploymentDir().getAbsolutePath();
ctInterface.writeFile(deploymentPathStr);
logger.debug("Writing file " + concreteMBeanInterfaceName);
ctClass.writeFile(deploymentPathStr);
logger.debug("Writing file " + concreteMBeanClassName);
component.setUsageParametersMBeanConcreteInterface(Thread.currentThread().getContextClassLoader().loadClass(concreteMBeanInterfaceName));
component.setUsageParametersMBeanImplConcreteClass(Thread.currentThread().getContextClassLoader().loadClass(concreteMBeanClassName));
ctInterface.defrost();
ctClass.defrost();
// slee 1.1. components also need a notification manager
if (component.isSlee11()) {
new ConcreteUsageNotificationManagerMBeanGenerator(component).generateConcreteUsageNotificationManagerMBean();
}
}
private void generateConcreteMethod(CtClass ctClass, CtMethod method) throws Exception{
String methodName = method.getName();
String body = "";
if (methodName.startsWith("increment")) {
body += "public long get" + methodName.substring("increment".length())
+ "( boolean reset ) throws " + ManagementException.class.getName() + " {"
+ "return (("+component.getUsageParametersConcreteClass().getName()+")getUsageParameter()).get" + methodName.substring("increment".length()
) + "(reset);"
+ "}";
if ( logger.isDebugEnabled())
logger.debug("METHOD BODY " + body);
CtMethod newmethod = CtNewMethod.make(body, ctClass);
ctClass.addMethod(newmethod);
} else if (methodName.startsWith("sample")) {
body += "public " + SampleStatistics.class.getName() + " get" + methodName.substring("sample".length())
+ "( boolean reset ) throws " + ManagementException.class.getName()+ " {"
+ "return (("+component.getUsageParametersConcreteClass().getName()+")getUsageParameter()).get" + methodName.substring("sample".length()) + "(reset);"
+ "}";
logger.debug("METHOD BODY " + body);
CtMethod newmethod = CtNewMethod.make(body, ctClass);
ctClass.addMethod(newmethod);
} else {
return;
}
}
private void generateAbstractMethod(CtClass ctClass, CtMethod method)
throws Exception {
String methodName = method.getName();
String body = "";
ClassPool classPool = component.getClassPool();
CtClass managementExceptionClass = classPool.get(ManagementException.class.getName());
CtClass sampleStatisticsClass = classPool.get(SampleStatistics.class.getName());
CtMethod newMethod = null;
if (methodName.startsWith("increment")) {
CtClass[] parameters = {CtClass.booleanType};
CtClass[] exceptions = {managementExceptionClass};
newMethod = CtNewMethod.abstractMethod(CtClass.longType,
"get" + methodName.substring("increment".length()),
parameters,
exceptions,
ctClass);
/*
* body += "public long get" + methodName.substring(9) + "( boolean
* reset ) throws " + ManagementException.class+ "";
*/
} else if (methodName.startsWith("sample")) {
CtClass[] parameters = {CtClass.booleanType};
CtClass[] exceptions = {managementExceptionClass};
newMethod = CtNewMethod.abstractMethod(sampleStatisticsClass,
"get" + methodName.substring("sample".length()),
parameters,
exceptions,
ctClass);
body += "public " + SampleStatistics.class.getName() + " " + methodName.substring("sample".length())
+ "( boolean reset ) throws " + ManagementException.class+ ";";
} else {
return;
}
ctClass.addMethod(newMethod);
}
}