import java.io.BufferedWriter; import java.io.FileWriter; import java.io.PrintWriter; import java.io.IOException; import com.sun.javadoc.*; public class Loglet { private final static String LOG_ANNOTATION = "Log"; private final static String LOG_VALUE = "value"; private final static String DEFAULT_LOG_LEVEL = "CONFIG"; public static boolean start(RootDoc root){ try { new Loglet(root); } catch (IOException ex) { ex.printStackTrace(); return false; } return true; } public Loglet(RootDoc root) throws IOException { ClassDoc[] classes = root.classes(); for (int i = 0; i < classes.length; i++) { if (checkAnnotation(classes[i])) { createProxy(classes[i]); createFactory(classes[i]); } } } private boolean checkAnnotation(ClassDoc cls) { if (checkAnnotation(cls.constructors()) || checkAnnotation(cls.methods())) { return true; } else { return false; } } private boolean checkAnnotation(ProgramElementDoc[] elements) { for (int i = 0; i < elements.length; i++) { AnnotationDesc[] annotations = elements[i].annotations(); for (int j = 0; j < annotations.length; j++) { AnnotationTypeDoc type = annotations[j].annotationType(); if (type.name().equals(LOG_ANNOTATION)) { return true; } } } return false; } private void createProxy(ClassDoc cls) throws IOException { String proxyName = cls.name() + "Proxy.java"; System.out.println("Proxy Name: " + proxyName); PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(proxyName))); writeHeader(cls, writer); writeConstructors(cls, writer); writeMethods(cls, writer); writeFooter(writer); writer.close(); } public void writeHeader(ClassDoc cls, PrintWriter writer) { writer.println("public class " + cls.name() + "Proxy extends " + cls.qualifiedName() + "{"); writer.println(" private static java.util.logging.Logger logger = java.util.logging.Logger.getLogger(\"" + cls.qualifiedName() + "\");"); } public void writeConstructors(ClassDoc cls, PrintWriter writer) { ConstructorDoc[] constructors = cls.constructors(); for (int i = 0; i < constructors.length; i++) { writeConstructor(cls, constructors[i], writer); } } public void writeConstructor(ClassDoc cls, ConstructorDoc constructor, PrintWriter writer) { if (checkModifier(constructor)) { return; } boolean logFlag = false; String level = DEFAULT_LOG_LEVEL; AnnotationDesc[] annotations = constructor.annotations(); for (int j = 0; j < annotations.length; j++) { AnnotationTypeDoc type = annotations[j].annotationType(); if (type.name().equals(LOG_ANNOTATION)) { logFlag = true; String tmpLevel = extractLogLevel(annotations[j]); if (tmpLevel != null) { level = tmpLevel; break; } } } Parameter[] params = constructor.parameters(); writer.print(constructor.modifiers() + " " + cls.name() + "Proxy("); writeParameterDefs(params, writer); writer.print(") "); writeExceptions(constructor, writer); writer.println(" {"); writer.print(" super("); writeParameters(params, writer); writer.println(");"); if (logFlag) { writePreLog(params, level, "Default Constructor", writer); } writer.println("}"); } public void writeMethods(ClassDoc cls, PrintWriter writer) { MethodDoc[] methods = cls.methods(); for (int i = 0; i < methods.length; i++) { writeMethod(methods[i], writer); } } public void writeMethod(MethodDoc method, PrintWriter writer) { if (checkModifier(method)) { return; } AnnotationDesc[] annotations = method.annotations(); if (annotations.length == 0) { return; } boolean logFlag = false; String level = DEFAULT_LOG_LEVEL; for (int j = 0; j < annotations.length; j++) { AnnotationTypeDoc type = annotations[j].annotationType(); if (type.name().equals(LOG_ANNOTATION)) { logFlag = true; String tmpLevel = extractLogLevel(annotations[j]); if (tmpLevel != null) { level = tmpLevel; break; } } } if (!logFlag) { return; } Parameter[] params = method.parameters(); writer.print(method.modifiers() + " " + method.returnType().qualifiedTypeName() + " " + method.name() + "("); writeParameterDefs(params, writer); writer.print(") "); writeExceptions(method, writer); writer.println(" {"); writePreLog(params, level, "calls " + method.name(), writer); if (!method.returnType().qualifiedTypeName().equals("void")) { writer.print(" " + method.returnType().qualifiedTypeName() + " result = "); } else { writer.print(" "); } writer.print("super." + method.name() + "("); writeParameters(params, writer); writer.println(");"); writePostLog(method, level, writer); writer.println("}"); } public void writeFooter(PrintWriter writer) { writer.println("}"); } private void createFactory(ClassDoc cls) throws IOException { String factoryName = cls.name() + "Factory.java"; System.out.println("Factory Name: " + factoryName); PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(factoryName))); writer.println("public class " + cls.name() + "Factory " + " {"); writeFactoryMethod(cls, writer); writeFooter(writer); writer.close(); } public void writeFactoryMethod(ClassDoc cls, PrintWriter writer) { ConstructorDoc[] constructors = cls.constructors(); for (int i = 0; i < constructors.length; i++) { if (!constructors[i].isPublic()) { continue; } Parameter[] params = constructors[i].parameters(); writer.print("public static " + cls.qualifiedName() + " create("); writeParameterDefs(params, writer); writer.print(") "); writeExceptions(constructors[i], writer); writer.println(" {"); writer.print(" return new " + cls.name() + "Proxy("); writeParameters(params, writer); writer.println(");"); writer.println("}"); } } private boolean checkModifier(ExecutableMemberDoc member) { return member.isPrivate() || member.isPackagePrivate() || member.isFinal(); } private String extractLogLevel(AnnotationDesc annotation) { AnnotationDesc.ElementValuePair[] members = annotation.elementValues(); for (int i = 0; i < members.length; i++) { if (members[i].element().name().equals(LOG_VALUE)) { return members[i].value().toString(); } } return null; } private void writeParameterDefs(Parameter[] params, PrintWriter writer) { if (params.length > 0) { for (int i = 0; i < params.length - 1; i++) { writer.print(params[i].type().qualifiedTypeName() + " " + params[i].name() +", "); } writer.print(params[params.length - 1].type().qualifiedTypeName() + " " + params[params.length - 1].name()); } } private void writeExceptions(ExecutableMemberDoc member, PrintWriter writer) { Type[] exceptions = member.thrownExceptionTypes(); if (exceptions.length > 0) { writer.print("throws "); for (int i = 0; i < exceptions.length - 1; i++) { writer.print(exceptions[i].qualifiedTypeName() + ", "); } writer.print(exceptions[exceptions.length - 1].qualifiedTypeName()); } } private void writeParameters(Parameter[] params, PrintWriter writer) { if (params.length > 0) { for (int i = 0; i < params.length - 1; i++) { writer.print(params[i].name() +", "); } writer.print(params[params.length - 1].name()); } } private void writePreLog(Parameter[] params, String level, String defaultMsg, PrintWriter writer) { writer.print(" logger.log(java.util.logging.Level." + level + ", "); if (params.length > 0) { writer.print("\"" + params[0].name() + ": \" + " + params[0].name()); for (int i = 1; i < params.length - 1; i++) { writer.print(" + \" " + params[i].name() + ": \" + " + params[i].name()); } writer.print(" + \" " + params[params.length - 1].name() + ": \" + " + params[params.length - 1].name()); } else { writer.print("\"" + defaultMsg + "\""); } writer.println(");"); } private void writePostLog(MethodDoc method, String level, PrintWriter writer) { writer.print(" logger.log(java.util.logging.Level." + level + ", \"return"); if (!method.returnType().qualifiedTypeName().equals("void")) { writer.println(": \" + result);"); writer.println(" return result;"); } else { writer.println("\");"); } } }