Skip to content

Instantly share code, notes, and snippets.

@nallachaitu
Created September 8, 2012 12:03
Show Gist options
  • Save nallachaitu/3674230 to your computer and use it in GitHub Desktop.
Save nallachaitu/3674230 to your computer and use it in GitHub Desktop.
class generation -- I have added the name lukas for the areas you need to take a look
package org.jboss.arquillian.qunit.junit;
//Javassist jar is needed to run this code.
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javassist.CannotCompileException;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.compiler.MemberResolver.Method;
public class ClassGenerator
{
//Given a class Name and a list of method names,it generates
//a class that contain generated methods with a dummy stub.
public Class<?> getClass(String className, List<String> list) throws CannotCompileException
{
try
{
ClassPool pool = ClassPool.getDefault();
//adding the classes in the target of this project --- Lukas you need to change it to point it to appropriate path
String path = "C:\\Users\\nallacha\\arquillian-qunit\\target\\classes\\org\\jboss\\arquillian\\qunit\\junit";
pool.insertClassPath(path);
// pool.appendClassPath("C:\Users\nallacha\.m2\repository\org\seleniumhq\selenium\selenium-java\2.24.1\");
// adding the classpath of the ClassGenerator class to include the search path for finding the ClassGenerator class.
pool.insertClassPath(new ClassClassPath(this.getClass()));
// Lukas -- i have tried adding the WebDriver classes path like below but it is not working.
//String WebDriverPath = "C:\\Users\\nallacha\\.m2\\repository\\org\\seleniumhq\\selenium\\selenium-java\\2.24.1\\org\\openqa\\selenium";
//pool.insertClassPath(WebDriverPath);
//importing WebDriver as it is needed
pool.importPackage("org.openqa.selenium.WebDriver");
// create the class
CtClass class_ = pool.makeClass(className);
/*
* adding WebDriver as a field
* For defining the type of the field,a CtClass should be created.
* representing the WebDriver.
*
*/
ClassFile classFile = class_.getClassFile();
ConstPool constPool = classFile.getConstPool();
CtClass WebDriver_ = pool.getCtClass("WebDriver");
//making WebDriver as an instance of the generated Class with @Drone annotation
CtField browser_ = new CtField(WebDriver_,"browser",class_);
//adding an annotation.
AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation("org.arquillian.drone", constPool);
//TODO: need to add a drone annotation to the field browser_.
attr.addAnnotation(annotation);
class_.addField(browser_);
CtClass String_ = pool.getCtClass("String");
String methodStub = "";
// create the methods
for (String methodName : list)
{
/* There are two ways of creating methods. First one is to create a method and add parameters, method body
* second way is to create abstract method with parameters and later add the method body.
*
* methodStub = "public void " +methodName+ "() {}";
* CtMethod method = CtNewMethod.make(methodStub, class_);
* method.addParameter(WebDriver_);
* method.addParameter(String_);
* method.addParameter(String_);
* method.insertAfter("TestHandler.runQunitMethod($$);");
*/
/* Doing it by creating a abstract method first and making it non abstract later.
* The generated method takes first parameter type as WebDriver
* second type as String, third type as String
*/
CtMethod method = new CtMethod(CtClass.voidType,methodName,new CtClass[]{WebDriver_,String_,String_},class_);
class_.addMethod(method);
method.setBody("TestHandler.runQunitMethod($$);");
// create the annotation test for the constructed method
//AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
annotation = new Annotation("org.junit.Test", constPool);
attr.addAnnotation(annotation);
//add the annotation to the method
method.getMethodInfo().addAttribute(attr);
}
//changing all the methods from abstract to non-abstract.
class_.setModifiers(class_.getModifiers() & ~Modifier.ABSTRACT);
Class<?> generatedClass = class_.toClass();
return generatedClass;
} catch (Exception e) {
e.printStackTrace();
System.out.println("hello");
throw new IllegalStateException(e);
}
}
//GetClasses takes a HashMap of class names corresponds to respective
//method names.
public List<Class<?>> getClasses(HashMap<String,List<String>> classes ) throws CannotCompileException //to be implemented
{
List<Class<?>> classes_ = new ArrayList<Class<?>>();
Set<String> names = classes.keySet();
for(String name : names)
{
classes_.add(getClass(name, classes.get(name)));
}
return classes_;
}
public static void main(String[] args) throws CannotCompileException
{
ClassGenerator test = new ClassGenerator();
ArrayList<String> names = new ArrayList<String>();
names.add("method1");
names.add("method2");
Class<?> class_ = test.getClass("nalla",names);
System.out.println("class name: " + class_.getName());
java.lang.reflect.Method[] methods = class_.getDeclaredMethods();
System.out.println("method names: " + methods.length);
//How to call the methods using the class file once they are generated
/* ClassGenerator test = new ClassGenerator();
ArrayList<String> names = new ArrayList<String>();
names.add("hello");
try {
Class<?> class_ = test.getClass("god",names);
} catch (CannotCompileException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment