/* * Copyright 2010-2012 VMware and contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springsource.loaded.testgen; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.Set; /** * This class is not actually part of the test infrastructure itself. It is a quick and dirty Java application that * prints out Java source code for a 'Invoker' class. That is, a class that contains code invoking the different * reflection methods of a given Target type. We use the reflection API to get all the methods defined on a given type * and create a method that call that method. * * @author kdvolder */ public class InvokerGenerator { public static void main(String[] args) { InvokerGenerator generator = new InvokerGenerator(Constructor.class); // System.out.println(generator.getCode()); System.out.println(generator.getMethodNameArray()); } private static final String INDENT_STR = " "; /** * Set this to tell the generator what the target type is. */ private Class<?> targetClass; /** * Set this to define the package in which the invoker lives. */ private String invokerPkg; /** * Class name of the invokder class (without package) */ private String invokerClassName; private Set<String> imports = null; public InvokerGenerator(Class<?> targetClass) { this.targetClass = targetClass; this.invokerPkg = "reflection"; this.invokerClassName = targetClass.getSimpleName() + "Invoker"; } /** * @return the generated code as a String */ public String getCode() { imports = new HashSet<String>(); addImport(targetClass); String methods = getMethods(); String header = getHeader(); String footer = getFooter(); return header + methods + footer; } private String getMethodNameArray() { StringBuffer code = new StringBuffer(); Method[] methods = targetClass.getDeclaredMethods(); for (Method method : methods) { if (Modifier.isPublic(method.getModifiers())) { code.append('"'); code.append(method.getDeclaringClass().getSimpleName() + "."); code.append(method.getName()); code.append("\",\n"); } } return code.toString(); } private void addImport(Class<?> clazz) { if (clazz.isPrimitive()) { return; } if (clazz.isArray()) { addImport(clazz.getComponentType()); return; } imports.add(clazz.getName()); } private String getFooter() { return "}\n"; } private String getMethods() { StringBuffer code = new StringBuffer(); Method[] methods = targetClass.getDeclaredMethods(); for (Method method : methods) { if (Modifier.isPublic(method.getModifiers())) { generateCallerMethod(method, code); } } return code.toString(); } private void generateCallerMethod(Method method, StringBuffer code) { code.append(INDENT_STR); code.append("public static " + method.getReturnType().getSimpleName() + " " + "call" + capitalize(method.getName()) + "("); addImport(method.getReturnType()); generateFormalParams(method, code); code.append(")\n"); Class<?>[] exceptions = method.getExceptionTypes(); if (exceptions.length > 0) { code.append(INDENT_STR + "throws "); for (int i = 0; i < exceptions.length; i++) { addImport(exceptions[i]); if (i > 0) { code.append(", "); } code.append(exceptions[i].getSimpleName()); } code.append("\n"); } code.append(INDENT_STR + "{\n"); generateBody(method, code); code.append(INDENT_STR + "}\n\n"); } private void generateBody(Method method, StringBuffer code) { code.append(INDENT_STR + INDENT_STR); if (method.getReturnType() != void.class) { code.append("return "); } if (Modifier.isStatic(method.getModifiers())) { code.append(targetClass.getSimpleName() + "."); } else { code.append("thiz."); } code.append(method.getName() + "("); generateActualParams(method, code); code.append(");\n"); } private void generateActualParams(Method method, StringBuffer code) { int i = 0; for (Class<?> param : method.getParameterTypes()) { addImport(param); if (i > 0) { code.append(", "); } code.append("a" + (i++)); } } private void generateFormalParams(Method method, StringBuffer code) { Class<?>[] params = method.getParameterTypes(); boolean addThisParam = !Modifier.isStatic(method.getModifiers()); if (addThisParam) { code.append(targetClass.getSimpleName() + " " + "thiz"); } int i = 0; for (Class<?> param : params) { if (i > 0 || addThisParam) { code.append(", "); } code.append(param.getSimpleName() + " a" + (i++)); } } private String capitalize(String name) { return Character.toUpperCase(name.charAt(0)) + name.substring(1); } private String getHeader() { return "package " + invokerPkg + ";\n" + "\n" + getImports() + "\n" + "/**\n" + " * Class containing one method for each method in the " + targetClass.getName() + "\n" + " * containing code calling that method.\n" + " */\n" + "@SuppressWarnings({\"unchecked\",\"rawtypes\"})" + "public class " + invokerClassName + "{\n" + "\n"; } private String getImports() { StringBuffer code = new StringBuffer(); for (String imp : imports) { code.append("import " + imp + ";\n"); } return code.toString(); } }