[Contestj-developer] contestj/contestj2/src/main/java/org/contestj/duplicator MockInjector.java, N
Status: Inactive
Brought to you by:
thomasra
|
From: Ståle P. <st...@us...> - 2007-06-20 14:54:23
|
Update of /cvsroot/contestj/contestj/contestj2/src/main/java/org/contestj/duplicator In directory sc8-pr-cvs4.sourceforge.net:/tmp/cvs-serv14426/contestj2/src/main/java/org/contestj/duplicator Added Files: MockInjector.java Duplicator.java Log Message: Initial upload of Contestj2 even though it supports most of the Contestj features its not ready to be used atm. --- NEW FILE: Duplicator.java --- package org.contestj.duplicator; import java.io.IOException; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.CtField; import javassist.CtMethod; import javassist.CtNewMethod; import javassist.CtPrimitiveType; import javassist.Modifier; import javassist.NotFoundException; import org.apache.log4j.Logger; public class Duplicator { private static Logger log = Logger.getLogger(Duplicator.class.getName()); private static String DUPLICATE = "_duplicate"; /** * This method returns a duplicated object for use in runtime, using * javassist libraries for runtime bytecode manipulation. Send in an * instantiated class object or a class representing an interface and * get an instantiated object back, supporting the methods defined * in the class or interface for use in testing. * * @param classOrInterface * @return */ public static Object duplicate(String classOrInterface) { if(doesDuplicateClassExist(classOrInterface)) { System.out.println("Duplicate already found in Classloader, using it..."); return loadDuplicateObject(classOrInterface); } System.out.println("Duplicating " + classOrInterface + " (in-memory)"); try { Class classOrInterfaceClass = Class.forName(classOrInterface); CtClass resultClass = null; // Split the responsibilities into two classes if(classOrInterfaceClass.isInterface() || Modifier.isAbstract(classOrInterfaceClass.getModifiers()) || classOrInterfaceClass.getName().equals("java.lang.Class")) { resultClass = duplicateInterface(classOrInterfaceClass); } else { throw new RuntimeException("Can only duplicate interfaces"); } //MockInjector.injectMock(resultClass); resultClass.writeFile("/tmp"); return resultClass.toClass().newInstance(); } catch (ClassNotFoundException e) { throw new RuntimeException("Not found: " + e.getMessage()); } catch (InstantiationException e) { throw new RuntimeException("Could not instantiate: " + e.getMessage()); } catch (IllegalAccessException e) { throw new RuntimeException("Could not access: " + e.getMessage()); } catch (IOException e) { throw new RuntimeException("I/O error: " + e.getMessage()); } catch (CannotCompileException e) { throw new RuntimeException("Could not compile: " + e.getMessage()); } } private static boolean doesDuplicateClassExist(String classOrInterface) { try { Class clazz = Class.forName(classOrInterface + DUPLICATE); return (clazz != null); } catch(ClassNotFoundException ce) { return false; } catch(Exception e) { log.error("Class.forName().. exception: "+classOrInterface + DUPLICATE, e); return false; } } private static Object loadDuplicateObject(String classOrInterface) { try { Class dupe = Class.forName(classOrInterface + DUPLICATE); return dupe.newInstance(); } catch(ClassNotFoundException ce) { throw new RuntimeException("Didnt find class: " + ce.getMessage()); } catch(IllegalAccessException ie ) { throw new RuntimeException("Illegal access: " + ie.getMessage()); } catch(InstantiationException ine ) { throw new RuntimeException("Instantiation error: " + ine.getMessage()); } catch(ExceptionInInitializerError ee ) { throw new RuntimeException("Initialize error: " + ee.getMessage()); } catch(SecurityException se ) { throw new RuntimeException("Security error: " + se.getMessage()); } } private static CtClass duplicateInterface(Class interfaceObject ) { ClassPool cPool = ClassPool.getDefault(); try { String interfaceCopyName = interfaceObject.getName() + DUPLICATE; CtClass ctClass = cPool.makeClass(interfaceCopyName); CtClass ctInterface = cPool.get(interfaceObject.getName()); if(ctInterface.isInterface()) { ctClass.addInterface(ctInterface); } else { ctClass.setSuperclass(ctInterface); } overrideReturningMethods(ctClass, ctInterface); return ctClass; } catch (NotFoundException e) { throw new RuntimeException("Not found: " + e.getMessage()); } catch (CannotCompileException e) { throw new RuntimeException("Cannot compile: " + e.getMessage()); } } private static void overrideReturningMethods(CtClass copy, CtClass original) { System.out.println("Overriding returning methods"); CtMethod[] methodsOnClass = null; CtMethod[] methodsOnSuperclass = null; // Should we look for methods on the original (interface) or the copy (class)? if(original == null) { methodsOnClass = copy.getDeclaredMethods(); methodsOnSuperclass = copy.getMethods(); } else { methodsOnClass = original.getDeclaredMethods(); methodsOnSuperclass = original.getMethods(); } // Loop through all of the methods to find non-void methods for (int i = 0; i < methodsOnSuperclass.length; i++) { CtMethod method = methodsOnSuperclass[i]; System.out.println("transforming method: "+method.toString()); // Find the non-void methods try { CtClass returnType = method.getReturnType(); CtClass[] parameterTypes = method.getParameterTypes(); CtClass[] exceptionTypes = method.getExceptionTypes(); String methodName = method.getName(); if(!method.getDeclaringClass().getName().equals("java.lang.Object")) { if(!method.getReturnType().equals(CtPrimitiveType.voidType)) { System.out.println("Modifying main method body: " + method.getName()); if(original == null) { if(methodExistsOnCopy(method.getName(), method, methodsOnClass)) { System.out.println("Changing method: " + methodName); //method.setBody(createAccessorBody(returnType, methodName)); method.setBody(createReturnBody(returnType)); } else { System.out.println("Adding new method (override from super): " + method.getName()); CtMethod accessor = CtNewMethod.make( returnType, method.getName(), parameterTypes, exceptionTypes, // createAccessorBody(returnType, methodName), createReturnBody(returnType), copy); copy.addMethod(accessor); } } else { System.out.println("Adding new method: " + method.getName()); try { CtMethod accessor = CtNewMethod.make( returnType, method.getName(), parameterTypes, exceptionTypes, //createAccessorBody(returnType, methodName), createReturnBody(returnType), copy); copy.addMethod(accessor); } catch(Exception e) { System.out.println("Got exception when adding method "+method.getName()+" to class"); e.printStackTrace(); } } } else { if(original == null) { if(methodExistsOnCopy(method.getName(), method, methodsOnClass)) { System.out.println("Changing void method: " + method.getName()); method.setBody("{ System.out.println(\"calling method: "+method.getName()+"\");}"); } else { System.out.println("Adding void method (override from super): " + method.getName()); CtMethod voidMethod = CtNewMethod.make(returnType, method.getName(), parameterTypes, exceptionTypes, "{ System.out.println(\"calling method: "+method.getName()+"\");}", copy); copy.addMethod(voidMethod); } } else { System.out.println("Adding void method: " + method.getName()); CtMethod voidMethod = CtNewMethod.make(returnType, method.getName(), parameterTypes, exceptionTypes, "{ System.out.println(\"calling method: "+method.getName()+"\");}", copy); copy.addMethod(voidMethod); } } } } catch (NotFoundException e) { throw new RuntimeException("Not found: " + e); } catch (CannotCompileException e) { throw new RuntimeException("Cannot compile: " + e); } } } private static boolean methodExistsOnCopy(String methodName, CtMethod method, CtMethod[] methodsOnClass) { for (int i = 0; i < methodsOnClass.length; i++) { CtMethod m = methodsOnClass[i]; try { if(m.getName().equals(methodName)) { if(m.getParameterTypes().length == method.getParameterTypes().length) { CtClass[] mParams = m.getParameterTypes(); CtClass[] methodParams = method.getParameterTypes(); for(int j = 0;j < mParams.length;j++) { if(!(mParams[j].getName().equals(methodParams[j].getName()))) { continue; } } if(m.getReturnType().getName().equals(method.getReturnType().getName())) { return true; } } } } catch(NotFoundException e) { return false; } } return false; } private static String createReturnBody(CtClass returnType) { StringBuffer buffer = new StringBuffer("return "); if(returnType.isPrimitive()) { if(returnType.equals(CtClass.booleanType)) buffer.append("false;"); else buffer.append("0;"); } else { if(returnType.getConstructors() != null && returnType.getConstructors().length > 0) buffer.append(" new ").append(returnType.getName()).append("();"); else buffer.append(" null;"); } return buffer.toString(); } } --- NEW FILE: MockInjector.java --- package org.contestj.duplicator; import org.contestj.introduction.Mock; import org.contestj.introduction.MockImpl; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.CtField; import javassist.CtMethod; import javassist.NotFoundException; /** * MockInjector. * * @author <a href="st...@gm...">Stale W. Pedersen</a> * @version $Revision: 1.1 $ */ public class MockInjector { public static CtClass injectMock(CtClass clazz) { CtClass mockInterface = getCtClass(Mock.class.getName()); CtClass mockClass = getCtClass(MockImpl.class.getName()); //clazz.addInterface(mockInterface); CtField[] mockFields = mockClass.getFields(); try { for(CtField field : mockFields) clazz.addField(field); } catch (CannotCompileException e) { // TODO Auto-generated catch block e.printStackTrace(); } CtMethod[] mockMethods = mockClass.getMethods(); try { for(CtMethod method : mockMethods) { System.out.println("adding method: "+method.getName()); clazz.addMethod(method); } } catch (CannotCompileException e) { // TODO Auto-generated catch block e.printStackTrace(); } return clazz; } private static CtClass getCtClass(String name) { ClassPool cPool = ClassPool.getDefault(); CtClass ctMock = null; try { ctMock = cPool.get(name); } catch (NotFoundException e) { throw new RuntimeException("Not found: " + e.getMessage()); } return ctMock; } } |