diff --git a/AndroidAnnotations/androidannotations/pom.xml b/AndroidAnnotations/androidannotations/pom.xml index 36e030f5a1..dde735fe95 100644 --- a/AndroidAnnotations/androidannotations/pom.xml +++ b/AndroidAnnotations/androidannotations/pom.xml @@ -1,109 +1,110 @@ - - 4.0.0 + + 4.0.0 - - org.androidannotations - androidannotations-parent - 3.0-SNAPSHOT - + + org.androidannotations + androidannotations-parent + 3.0-SNAPSHOT + - androidannotations - AndroidAnnotations Annotation Processor - The Annotation Processor jar that generates code + androidannotations + AndroidAnnotations Annotation Processor + The Annotation Processor jar that generates code - - - org.androidannotations - androidannotations-api - - - com.sun.codemodel - codemodel - - - junit - junit - - - com.google.guava - guava - - - com.google.android - android - 1.6_r2 - provided - - - - org.springframework.android - spring-android-rest-template - 1.0.0.RELEASE - test - - + + + org.androidannotations + androidannotations-api + + + com.sun.codemodel + codemodel + + + junit + junit + + + com.google.guava + guava + + + com.google.android + android + 1.6_r2 + provided + + + + org.springframework.android + spring-android-rest-template + 1.0.0.RELEASE + test + + - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.6 - 1.6 - -proc:none - - - - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - maven-source-plugin - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-resources-plugin - - + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + -proc:none + + + + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-resources-plugin + + - - - src/main/resources - - rebel.xml - - - - src/main/java - - org/androidannotations/api/** - - - - src/main/resources - true - - **/*.properties - - - - + + + src/main/resources + + rebel.xml + + + + src/main/java + + org/androidannotations/api/** + + + + src/main/resources + true + + **/*.properties + + + + diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java index d880430808..508c63f58b 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/AndroidAnnotationProcessor.java @@ -17,6 +17,9 @@ import static org.androidannotations.helper.AndroidManifestFinder.ANDROID_MANIFEST_FILE_OPTION; import static org.androidannotations.helper.ModelConstants.TRACE_OPTION; +import static org.androidannotations.logger.LoggerContext.LOG_APPENDER_CONSOLE; +import static org.androidannotations.logger.LoggerContext.LOG_FILE_OPTION; +import static org.androidannotations.logger.LoggerContext.LOG_LEVEL_OPTION; import static org.androidannotations.rclass.ProjectRClassFinder.RESOURCE_PACKAGE_NAME_OPTION; import java.io.FileNotFoundException; @@ -27,7 +30,6 @@ import java.util.Set; import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedOptions; @@ -35,7 +37,6 @@ import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; import org.androidannotations.annotations.EActivity; import org.androidannotations.exception.ProcessingException; @@ -46,7 +47,14 @@ import org.androidannotations.helper.AndroidManifestFinder; import org.androidannotations.helper.ErrorHelper; import org.androidannotations.helper.Option; -import org.androidannotations.model.*; +import org.androidannotations.logger.Level; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerContext; +import org.androidannotations.logger.LoggerFactory; +import org.androidannotations.model.AndroidSystemServices; +import org.androidannotations.model.AnnotationElements; +import org.androidannotations.model.AnnotationElementsHolder; +import org.androidannotations.model.ModelExtractor; import org.androidannotations.process.ModelProcessor; import org.androidannotations.process.ModelValidator; import org.androidannotations.process.TimeStats; @@ -56,9 +64,11 @@ import org.androidannotations.rclass.ProjectRClassFinder; @SupportedSourceVersion(SourceVersion.RELEASE_6) -@SupportedOptions({ TRACE_OPTION, ANDROID_MANIFEST_FILE_OPTION, RESOURCE_PACKAGE_NAME_OPTION }) +@SupportedOptions({ TRACE_OPTION, ANDROID_MANIFEST_FILE_OPTION, RESOURCE_PACKAGE_NAME_OPTION, LOG_FILE_OPTION, LOG_LEVEL_OPTION, LOG_APPENDER_CONSOLE }) public class AndroidAnnotationProcessor extends AbstractProcessor { + private static final Logger LOGGER = LoggerFactory.getLogger(AndroidAnnotationProcessor.class); + private final Properties properties = new Properties(); private final Properties propertiesApi = new Properties(); private final TimeStats timeStats = new TimeStats(); @@ -69,18 +79,19 @@ public class AndroidAnnotationProcessor extends AbstractProcessor { public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); - Messager messager = processingEnv.getMessager(); + // Configure Logger + LoggerContext loggerContext = LoggerContext.getInstance(); + loggerContext.setProcessingEnv(processingEnv); + + LOGGER.info("Initialize AndroidAnnotationProcessor with options {}", processingEnv.getOptions()); try { loadPropertyFile(); loadApiPropertyFile(); } catch (Exception e) { - messager.printMessage(Diagnostic.Kind.ERROR, "AndroidAnnotations processing failed: " + e.getMessage()); + LOGGER.error("Can't load API or core properties files", e); } - timeStats.setMessager(messager); - messager.printMessage(Diagnostic.Kind.NOTE, "Starting AndroidAnnotations annotation processing"); - annotationHandlers = new AnnotationHandlers(processingEnv); } @@ -89,6 +100,7 @@ private void checkApiAndCoreVersions() throws VersionMismatchException { String coreVersion = getAAProcessorVersion(); if (!apiVersion.equals(coreVersion)) { + LOGGER.error("AndroidAnnotation version for API ({}) and core ({}) doesn't match. Please check your classpath", apiVersion, coreVersion); throw new VersionMismatchException("AndroidAnnotation version for API (" + apiVersion + ") and core (" + coreVersion + ") doesn't match. Please check your classpath"); } } @@ -98,6 +110,13 @@ public boolean process(Set annotations, RoundEnvironment timeStats.clear(); timeStats.start("Whole Processing"); + Set rootElements = roundEnv.getRootElements(); + if (LOGGER.isLoggable(Level.TRACE)) { + LOGGER.trace("Start processing for {} annotations {} on {} elements {}", annotations.size(), annotations, rootElements.size(), rootElements); + } else { + LOGGER.info("Start processing for {} annotations on {} elements", annotations.size(), rootElements.size()); + } + try { checkApiAndCoreVersions(); processThrowing(annotations, roundEnv); @@ -108,6 +127,10 @@ public boolean process(Set annotations, RoundEnvironment } timeStats.stop("Whole Processing"); timeStats.logStats(); + + LOGGER.info("Finish processing"); + + LoggerContext.getInstance().close(); return true; } @@ -117,7 +140,8 @@ private void loadPropertyFile() throws FileNotFoundException { URL url = getClass().getClassLoader().getResource(filename); properties.load(url.openStream()); } catch (Exception e) { - throw new FileNotFoundException(filename + " couldn't be parsed."); + LOGGER.error("Core property file {} couldn't be parse"); + throw new FileNotFoundException("Core property file " + filename + " couldn't be parsed."); } } @@ -127,7 +151,8 @@ private void loadApiPropertyFile() throws FileNotFoundException { URL url = EActivity.class.getClassLoader().getResource(filename); propertiesApi.load(url.openStream()); } catch (Exception e) { - throw new FileNotFoundException(filename + " couldn't be parsed. Please check your classpath and verify that AA-API's version is at least 3.0"); + LOGGER.error("API property file {} couldn't be parse"); + throw new FileNotFoundException("API property file " + filename + " couldn't be parsed. Please check your classpath and verify that AA-API's version is at least 3.0"); } } @@ -147,19 +172,17 @@ private void processThrowing(Set annotations, RoundEnviro AnnotationElementsHolder extractedModel = extractAnnotations(annotations, roundEnv); Option androidManifestOption = extractAndroidManifest(); - if (androidManifestOption.isAbsent()) { return; } - AndroidManifest androidManifest = androidManifestOption.get(); - Option rClassOption = findRClasses(androidManifest); + LOGGER.info("AndroidManifest.xml found: {}", androidManifest); + Option rClassOption = findRClasses(androidManifest); if (rClassOption.isAbsent()) { return; } - IRClass rClass = rClassOption.get(); AndroidSystemServices androidSystemServices = new AndroidSystemServices(); @@ -222,7 +245,7 @@ private AnnotationElements validateAnnotations(AnnotationElementsHolder extracte return validatedAnnotations; } - private ModelProcessor.ProcessResult processAnnotations(AnnotationElements validatedModel) throws Exception { + private ModelProcessor.ProcessResult processAnnotations(AnnotationElements validatedModel) throws Exception { timeStats.start("Process Annotations"); annotationHandlers.setValidatedModel(validatedModel); ModelProcessor modelProcessor = new ModelProcessor(processingEnv, annotationHandlers); @@ -233,9 +256,8 @@ private ModelProcessor.ProcessResult processAnnotations(AnnotationElements valid private void generateSources(ModelProcessor.ProcessResult processResult) throws IOException { timeStats.start("Generate Sources"); - Messager messager = processingEnv.getMessager(); - messager.printMessage(Diagnostic.Kind.NOTE, "Number of files generated by AndroidAnnotations: " + processResult.codeModel.countArtifacts()); - CodeModelGenerator modelGenerator = new CodeModelGenerator(processingEnv.getFiler(), messager, getAAProcessorVersion()); + LOGGER.info("Number of files generated by AndroidAnnotations: {}", processResult.codeModel.countArtifacts()); + CodeModelGenerator modelGenerator = new CodeModelGenerator(processingEnv.getFiler(), getAAProcessorVersion()); modelGenerator.generate(processResult); timeStats.stop("Generate Sources"); } @@ -243,9 +265,6 @@ private void generateSources(ModelProcessor.ProcessResult processResult) throws private void handleException(Set annotations, RoundEnvironment roundEnv, ProcessingException e) { String errorMessage = errorHelper.getErrorMessage(processingEnv, e, getAAProcessorVersion()); - Messager messager = processingEnv.getMessager(); - messager.printMessage(Diagnostic.Kind.ERROR, errorMessage); - /* * Printing exception as an error on a random element. The exception is * not related to this element, but otherwise it wouldn't show up in @@ -255,7 +274,9 @@ private void handleException(Set annotations, RoundEnviro Iterator iterator = annotations.iterator(); if (iterator.hasNext()) { Element element = roundEnv.getElementsAnnotatedWith(iterator.next()).iterator().next(); - messager.printMessage(Diagnostic.Kind.ERROR, errorMessage, element); + LOGGER.error("Something went wront : {}", errorMessage, element); + } else { + LOGGER.error("Something went wront : {}", errorMessage); } } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/ApiCodeGenerator.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/ApiCodeGenerator.java index 5a8556060e..4c8dce3509 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/ApiCodeGenerator.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/ApiCodeGenerator.java @@ -25,10 +25,13 @@ import javax.lang.model.element.Element; import javax.tools.JavaFileObject; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; import org.androidannotations.process.OriginatingElements; public class ApiCodeGenerator { + private static final Logger LOGGER = LoggerFactory.getLogger(ApiCodeGenerator.class); private static final byte[] BUFFER = new byte[4096]; private static void copyStream(InputStream input, OutputStream output) throws IOException { @@ -46,6 +49,8 @@ public ApiCodeGenerator(Filer filer) { public void writeApiClasses(Set> apiClassesToGenerate, OriginatingElements originatingElements) { + LOGGER.info("Writting following API classes in project: {}", apiClassesToGenerate); + for (Class apiClassToGenerate : apiClassesToGenerate) { String canonicalApiClassName = apiClassToGenerate.getCanonicalName(); diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/CodeModelGenerator.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/CodeModelGenerator.java index 3108cd5e6c..b29c11ef8f 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/CodeModelGenerator.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/CodeModelGenerator.java @@ -18,7 +18,6 @@ import java.io.IOException; import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; import org.androidannotations.process.ModelProcessor; @@ -27,12 +26,10 @@ public class CodeModelGenerator { private final Filer filer; - private final Messager messager; private final String aaVersion; - public CodeModelGenerator(Filer filer, Messager messager, String aaVersion) { + public CodeModelGenerator(Filer filer, String aaVersion) { this.filer = filer; - this.messager = messager; this.aaVersion = aaVersion; } @@ -41,7 +38,7 @@ public void generate(ModelProcessor.ProcessResult processResult) throws IOExcept ApiCodeGenerator apiCodeGenerator = new ApiCodeGenerator(filer); apiCodeGenerator.writeApiClasses(processResult.apiClassesToGenerate, processResult.originatingElements); - SourceCodewriter sourceCodeWriter = new SourceCodewriter(filer, messager, processResult.originatingElements); + SourceCodewriter sourceCodeWriter = new SourceCodewriter(filer, processResult.originatingElements); PrologCodeWriter prologCodeWriter = new PrologCodeWriter(sourceCodeWriter, "DO NOT EDIT THIS FILE, IT HAS BEEN GENERATED USING AndroidAnnotations " + aaVersion + ".\n"); diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/SourceCodewriter.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/SourceCodewriter.java index 3c293af75e..449eef41b0 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/SourceCodewriter.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/generation/SourceCodewriter.java @@ -20,11 +20,11 @@ import javax.annotation.processing.Filer; import javax.annotation.processing.FilerException; -import javax.annotation.processing.Messager; import javax.lang.model.element.Element; -import javax.tools.Diagnostic.Kind; import javax.tools.JavaFileObject; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; import org.androidannotations.process.OriginatingElements; import com.sun.codemodel.CodeWriter; @@ -32,10 +32,9 @@ public class SourceCodewriter extends CodeWriter { - private final Filer filer; - private final Messager message; - private static final VoidOutputStream VOID_OUTPUT_STREAM = new VoidOutputStream(); + private static final Logger LOGGER = LoggerFactory.getLogger(SourceCodewriter.class); + private final Filer filer; private OriginatingElements originatingElements; private static class VoidOutputStream extends OutputStream { @@ -45,16 +44,15 @@ public void write(int arg0) throws IOException { } } - public SourceCodewriter(Filer filer, Messager message, OriginatingElements originatingElements) { + public SourceCodewriter(Filer filer, OriginatingElements originatingElements) { this.filer = filer; - this.message = message; this.originatingElements = originatingElements; } @Override public OutputStream openBinary(JPackage pkg, String fileName) throws IOException { String qualifiedClassName = toQualifiedClassName(pkg, fileName); - message.printMessage(Kind.NOTE, "Generating source file: " + qualifiedClassName); + LOGGER.debug("Generating class: {}", qualifiedClassName); Element[] classOriginatingElements = originatingElements.getClassOriginatingElements(qualifiedClassName); @@ -62,14 +60,14 @@ public OutputStream openBinary(JPackage pkg, String fileName) throws IOException JavaFileObject sourceFile; if (classOriginatingElements.length == 0) { - message.printMessage(Kind.NOTE, "Generating class with no originating element: " + qualifiedClassName); + LOGGER.info("Generating class with no originating element: {}", qualifiedClassName); } sourceFile = filer.createSourceFile(qualifiedClassName, classOriginatingElements); return sourceFile.openOutputStream(); } catch (FilerException e) { - message.printMessage(Kind.NOTE, "Could not generate source file for " + qualifiedClassName + ", message: " + e.getMessage()); + LOGGER.error("Could not generate source file for {}", qualifiedClassName, e.getMessage()); /* * This exception is expected, when some files are created twice. We * cannot delete existing files, unless using a dirty hack. Files a diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifest.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifest.java index e7bc87096a..c19d807791 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifest.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifest.java @@ -30,6 +30,11 @@ public class AndroidManifest { private final int maxSdkVersion; private final int targetSdkVersion; + @Override + public String toString() { + return "AndroidManifest [applicationPackage=" + applicationPackage + ", componentQualifiedNames=" + componentQualifiedNames + ", permissionQualifiedNames=" + permissionQualifiedNames + ", applicationClassName=" + applicationClassName + ", libraryProject=" + libraryProject + ", debugabble=" + debugabble + ", minSdkVersion=" + minSdkVersion + ", maxSdkVersion=" + maxSdkVersion + ", targetSdkVersion=" + targetSdkVersion + "]"; + } + public static AndroidManifest createManifest(String applicationPackage, String applicationClassName, List componentQualifiedNames, List permissionQualifiedNames, int minSdkVersion, int maxSdkVersion, int targetSdkVersion, boolean debugabble) { return new AndroidManifest(false, applicationPackage, applicationClassName, componentQualifiedNames, permissionQualifiedNames, minSdkVersion, maxSdkVersion, targetSdkVersion, debugabble); } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java index 6298d22425..3601f60b36 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AndroidManifestFinder.java @@ -18,21 +18,18 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Properties; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.util.Elements; -import javax.tools.Diagnostic.Kind; -import javax.tools.JavaFileObject; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; +import org.androidannotations.helper.FileHelper.FileHolder; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -43,6 +40,7 @@ public class AndroidManifestFinder { public static final String ANDROID_MANIFEST_FILE_OPTION = "androidManifestFile"; + private static final Logger LOGGER = LoggerFactory.getLogger(AndroidManifestFinder.class); private static final int MAX_PARENTS_FROM_SOURCE_FOLDER = 10; private ProcessingEnvironment processingEnv; @@ -73,8 +71,7 @@ public Option extractAndroidManifest() { String androidLibraryProperty = properties.getProperty("android.library"); libraryProject = androidLibraryProperty.equals("true"); - Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.NOTE, "Found android.library property in project.properties, value: " + libraryProject); + LOGGER.debug("Found android.library={} property in project.properties", libraryProject); } } catch (IOException ignored) { } @@ -94,12 +91,11 @@ private Option findManifestFile() { private Option findManifestInSpecifiedPath() { String path = processingEnv.getOptions().get(ANDROID_MANIFEST_FILE_OPTION); File androidManifestFile = new File(path); - Messager messager = processingEnv.getMessager(); if (!androidManifestFile.exists()) { - messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file in specified path : " + path); + LOGGER.error("Could not find the AndroidManifest.xml file in specified path : {}", path); return Option.absent(); } else { - messager.printMessage(Kind.NOTE, "AndroidManifest.xml file found: " + androidManifestFile.toString()); + LOGGER.debug("AndroidManifest.xml file found with specified path: {}", androidManifestFile.toString()); } return Option.of(androidManifestFile); } @@ -112,40 +108,13 @@ private Option findManifestInSpecifiedPath() { * appreciated. */ private Option findManifestInParentsDirectories() { - Filer filer = processingEnv.getFiler(); - - Messager messager = processingEnv.getMessager(); - - JavaFileObject dummySourceFile; - try { - dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis()); - } catch (IOException ignored) { - messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file, unable to create a dummy source file to locate the source folder"); + Option projectRootHolderOption = FileHelper.findRootProjectHolder(processingEnv); + if (projectRootHolderOption.isAbsent()) { return Option.absent(); } - String dummySourceFilePath = dummySourceFile.toUri().toString(); - - if (dummySourceFilePath.startsWith("file:")) { - if (!dummySourceFilePath.startsWith("file://")) { - dummySourceFilePath = "file://" + dummySourceFilePath.substring("file:".length()); - } - } else { - dummySourceFilePath = "file://" + dummySourceFilePath; - } - - URI cleanURI; - try { - cleanURI = new URI(dummySourceFilePath); - } catch (URISyntaxException e) { - messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file, path to dummy source file cannot be parsed: " + dummySourceFilePath); - return Option.absent(); - } - - File dummyFile = new File(cleanURI); - - File sourcesGenerationFolder = dummyFile.getParentFile(); - File projectRoot = sourcesGenerationFolder.getParentFile(); + FileHolder projectRootHolder = projectRootHolderOption.get(); + File projectRoot = projectRootHolder.projectRoot; File androidManifestFile = new File(projectRoot, "AndroidManifest.xml"); for (int i = 0; i < MAX_PARENTS_FROM_SOURCE_FOLDER; i++) { @@ -162,10 +131,10 @@ private Option findManifestInParentsDirectories() { } if (!androidManifestFile.exists()) { - messager.printMessage(Kind.ERROR, "Could not find the AndroidManifest.xml file, going up from path [" + sourcesGenerationFolder.getAbsolutePath() + "] found using dummy file [" + dummySourceFilePath + "] (max atempts: " + MAX_PARENTS_FROM_SOURCE_FOLDER + ")"); + LOGGER.error("Could not find the AndroidManifest.xml file, going up from path [{}] found using dummy file [] (max atempts: {})", projectRootHolder.sourcesGenerationFolder.getAbsolutePath(), projectRootHolder.dummySourceFilePath, MAX_PARENTS_FROM_SOURCE_FOLDER); return Option.absent(); } else { - messager.printMessage(Kind.NOTE, "AndroidManifest.xml file found: " + androidManifestFile.toString()); + LOGGER.debug("AndroidManifest.xml file found in parent folder {}: {}", projectRoot.getAbsolutePath(), androidManifestFile.toString()); } return Option.of(androidManifestFile); @@ -179,8 +148,7 @@ private Option parse(File androidManifestFile, boolean libraryP DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); doc = docBuilder.parse(androidManifestFile); } catch (Exception e) { - Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.ERROR, "Could not parse the AndroidManifest.xml file at path " + androidManifestFile); + LOGGER.error("Could not parse the AndroidManifest.xml file at path {}", androidManifestFile, e); return Option.absent(); } @@ -216,9 +184,8 @@ private Option parse(File androidManifestFile, boolean libraryP applicationClassQualifiedName = manifestNameToValidQualifiedName(applicationPackage, nameAttribute); if (applicationClassQualifiedName == null) { - Messager messager = processingEnv.getMessager(); if (nameAttribute != null) { - messager.printMessage(Kind.NOTE, String.format("The class application declared in the AndroidManifest.xml cannot be found in the compile path: [%s]", nameAttribute.getNodeValue())); + LOGGER.warn("The class application declared in the AndroidManifest.xml cannot be found in the compile path: [{}]", nameAttribute.getNodeValue()); } } @@ -281,11 +248,10 @@ private List extractComponentNames(String applicationPackage, NodeList c if (qualifiedName != null) { componentQualifiedNames.add(qualifiedName); } else { - Messager messager = processingEnv.getMessager(); if (nameAttribute != null) { - messager.printMessage(Kind.NOTE, String.format("A class activity declared in the AndroidManifest.xml cannot be found in the compile path: [%s]", nameAttribute.getNodeValue())); + LOGGER.warn("A class activity declared in the AndroidManifest.xml cannot be found in the compile path: [{}]", nameAttribute.getNodeValue()); } else { - messager.printMessage(Kind.NOTE, String.format("The %d activity node in the AndroidManifest.xml has no android:name attribute", i)); + LOGGER.warn("The {} activity node in the AndroidManifest.xml has no android:name attribute", i); } } } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java index ce17e56031..c582ad6d8e 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/AnnotationHelper.java @@ -37,12 +37,13 @@ import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; -import javax.tools.Diagnostic; import org.androidannotations.annotations.OnActivityResult; import org.androidannotations.annotations.OptionsItem; import org.androidannotations.annotations.ResId; -import org.androidannotations.holder.GeneratedClassHolder; +import org.androidannotations.logger.Level; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; import org.androidannotations.process.ProcessHolder; import org.androidannotations.rclass.IRInnerClass; import org.androidannotations.rclass.RInnerClass; @@ -51,6 +52,8 @@ public class AnnotationHelper { + private static final Logger LOGGER = LoggerFactory.getLogger(AnnotationHelper.class); + private final ProcessingEnvironment processingEnv; public AnnotationHelper(ProcessingEnvironment processingEnv) { @@ -94,24 +97,24 @@ public boolean isAnnotation(TypeElement annotation, String annotationName) { } public void printAnnotationError(Element annotatedElement, String annotationName, String message) { - printAnnotationMessage(Diagnostic.Kind.ERROR, annotatedElement, annotationName, message); + printAnnotationMessage(Level.ERROR, annotatedElement, annotationName, message); } public void printAnnotationWarning(Element annotatedElement, String annotationName, String message) { - printAnnotationMessage(Diagnostic.Kind.WARNING, annotatedElement, annotationName, message); + printAnnotationMessage(Level.WARN, annotatedElement, annotationName, message); } - public void printAnnotationMessage(Diagnostic.Kind diagnosticKind, Element annotatedElement, String annotationName, String message) { + public void printAnnotationMessage(Level level, Element annotatedElement, String annotationName, String message) { AnnotationMirror annotationMirror = findAnnotationMirror(annotatedElement, annotationName); if (annotationMirror != null) { - processingEnv.getMessager().printMessage(diagnosticKind, message, annotatedElement, annotationMirror); + LOGGER.log(level, message, annotatedElement, annotationMirror, null); } else { printError(annotatedElement, message); } } public void printError(Element element, String message) { - processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message, element); + LOGGER.error(message, element); } public boolean isPrivate(Element element) { diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/FileHelper.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/FileHelper.java new file mode 100644 index 0000000000..508be38db9 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/FileHelper.java @@ -0,0 +1,106 @@ +package org.androidannotations.helper; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.annotation.processing.Filer; +import javax.annotation.processing.ProcessingEnvironment; +import javax.tools.JavaFileObject; + +public class FileHelper { + + public static Option findRootProject(ProcessingEnvironment processingEnv) { + Option rootProjectHolder = findRootProjectHolder(processingEnv); + if (rootProjectHolder.isAbsent()) { + return Option.absent(); + } + + return Option.of(rootProjectHolder.get().projectRoot); + } + + /** + * We use a dirty trick to find the AndroidManifest.xml file, since it's not + * available in the classpath. The idea is quite simple : create a fake + * class file, retrieve its URI, and start going up in parent folders to + * find the AndroidManifest.xml file. Any better solution will be + * appreciated. + */ + public static Option findRootProjectHolder(ProcessingEnvironment processingEnv) { + Filer filer = processingEnv.getFiler(); + + JavaFileObject dummySourceFile; + try { + dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis()); + } catch (IOException ignored) { + return Option.absent(); + } + String dummySourceFilePath = dummySourceFile.toUri().toString(); + + if (dummySourceFilePath.startsWith("file:")) { + if (!dummySourceFilePath.startsWith("file://")) { + dummySourceFilePath = "file://" + dummySourceFilePath.substring("file:".length()); + } + } else { + dummySourceFilePath = "file://" + dummySourceFilePath; + } + + URI cleanURI; + try { + cleanURI = new URI(dummySourceFilePath); + } catch (URISyntaxException e) { + return Option.absent(); + } + + File dummyFile = new File(cleanURI); + File sourcesGenerationFolder = dummyFile.getParentFile(); + File projectRoot = sourcesGenerationFolder.getParentFile(); + + return Option.of(new FileHolder(dummySourceFilePath, sourcesGenerationFolder, projectRoot)); + } + + public static File resolveOutputDirectory(ProcessingEnvironment processingEnv) { + Option rootProjectOption = FileHelper.findRootProject(processingEnv); + if (rootProjectOption.isAbsent()) { + // Execution root folder + return null; + } + + File rootProject = rootProjectOption.get(); + + // Target folder - Maven + File targetFolder = new File(rootProject, "target"); + if (targetFolder.isDirectory() && targetFolder.canWrite()) { + return targetFolder; + } + + // Build folder - Gradle + File buildFolder = new File(rootProject, "build"); + if (buildFolder.isDirectory() && buildFolder.canWrite()) { + return buildFolder; + } + + // Bin folder - Eclipse + File binFolder = new File(rootProject, "bin"); + if (binFolder.isDirectory() && binFolder.canWrite()) { + return binFolder; + } + + // Fallback to projet root folder + return rootProject; + } + + static class FileHolder { + String dummySourceFilePath; + File sourcesGenerationFolder; + File projectRoot; + + public FileHolder(String dummySourceFilePath, File sourcesGenerationFolder, File projectRoot) { + this.dummySourceFilePath = dummySourceFilePath; + this.sourcesGenerationFolder = sourcesGenerationFolder; + this.projectRoot = projectRoot; + } + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Formatter.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Formatter.java new file mode 100644 index 0000000000..971213a359 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Formatter.java @@ -0,0 +1,90 @@ +package org.androidannotations.logger; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; + +public class Formatter { + + private static final DateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss.S"); + private static final String ARGS_PATTERN = "{}"; + private static final int ARGS_PATTERN_LENGTH = ARGS_PATTERN.length(); + + public String buildLog(Level level, String loggerName, String message, Throwable thr, Object... args) { + String fullMessage = buildFullMessage(message, args); + StringBuilder stringBuilder = new StringBuilder(fullMessage.length()); + + stringBuilder.append(DATE_FORMAT.format(new Date())) // + .append(" [").append(Thread.currentThread().getName()).append("]") // + .append(" ").append(level.name) // + .append(" ").append(loggerName) // + .append(":").append(getCallerLineNumber()) // + .append(" - ").append(fullMessage); + + // Stacktrace + if (thr != null) { + stringBuilder.append('\n').append(stackTraceToString(thr)); + } + + return stringBuilder.toString(); + } + + public String buildFullMessage(String message, Object... args) { + StringBuilder stringBuilder = new StringBuilder(message.length()); + int lastIndex = 0; + int argIndex = 0; + + while (true) { + int argPos = message.indexOf(ARGS_PATTERN, lastIndex); + if (argPos == -1) { + break; + } + + stringBuilder.append(message.substring(lastIndex, argPos)); + + lastIndex = argPos + ARGS_PATTERN_LENGTH; + + // add the argument, if we still have any + if (argIndex < args.length) { + stringBuilder.append(formatArgument(args[argIndex])); + argIndex++; + } + } + + stringBuilder.append(message.substring(lastIndex)); + + return stringBuilder.toString(); + } + + private String formatArgument(Object arg) { + if (arg != null && arg.getClass().isArray()) { + return Arrays.toString((Object[]) arg); + } + return arg.toString(); + } + + private String stackTraceToString(Throwable e) { + StringWriter writer = new StringWriter(); + PrintWriter pw = new PrintWriter(writer); + e.printStackTrace(pw); + return writer.toString(); + } + + private int getCallerLineNumber() { + boolean previousWasLogger = false; + String loggerClassName = Logger.class.getCanonicalName(); + + StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); + for (StackTraceElement stackTraceElement : stackTrace) { + if (stackTraceElement.getClassName().equals(loggerClassName)) { + previousWasLogger = true; + } else if (previousWasLogger) { + return stackTraceElement.getLineNumber(); + } + } + return -1; + } +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Level.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Level.java new file mode 100644 index 0000000000..e9096ac3a7 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Level.java @@ -0,0 +1,35 @@ +package org.androidannotations.logger; + +public enum Level { + TRACE(1, "TRACE"), // + DEBUG(2, "DEBUG"), // + INFO(3, "INFO "), // + WARN(4, "WARN "), // + ERROR(5, "ERROR"); + + public final int weight; + public final String name; + + private Level(int weight, String name) { + this.weight = weight; + this.name = name; + } + + public boolean isGreaterOrEquals(Level l) { + return weight >= l.weight; + } + + public boolean isSmaller(Level l) { + return weight < l.weight; + } + + public static Level parse(String name) { + for (Level level : values()) { + if (level.name().equalsIgnoreCase(name)) { + return level; + } + } + throw new IllegalArgumentException("Can't find Level matching " + name); + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Logger.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Logger.java new file mode 100644 index 0000000000..c88a0e21e7 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/Logger.java @@ -0,0 +1,84 @@ +package org.androidannotations.logger; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; + +public class Logger { + + private final LoggerContext loggerContext; + private final String name; + + public Logger(LoggerContext loggerContext, String name) { + this.loggerContext = loggerContext; + this.name = name; + } + + public void trace(String message, Object... args) { + trace(message, null, args); + } + + public void trace(String message, Element element, Object... args) { + log(Level.TRACE, message, element, null, null, args); + } + + public void debug(String message, Object... args) { + debug(message, null, args); + } + + public void debug(String message, Element element, Object... args) { + log(Level.DEBUG, message, element, null, null, args); + } + + public void info(String message, Object... args) { + info(message, null, args); + } + + public void info(String message, Element element, Object... args) { + log(Level.INFO, message, element, null, null, args); + } + + public void warn(String message, Object... args) { + warn(message, null, null, args); + } + + public void warn(String message, Throwable thr, Object... args) { + warn(message, null, thr, args); + } + + public void warn(String message, Element element, Object... args) { + warn(message, element, null, args); + } + + public void warn(String message, Element element, Throwable thr, Object... args) { + log(Level.WARN, message, element, null, thr, args); + } + + public void error(String message, Object... args) { + error(message, null, null, args); + } + + public void error(String message, Element element, Object... args) { + error(message, element, null, args); + } + + public void error(String message, Throwable thr, Object... args) { + error(message, null, thr, args); + } + + public void error(String message, Element element, Throwable thr, Object... args) { + log(Level.ERROR, message, element, null, thr, args); + } + + public boolean isLoggable(Level level) { + return level.isGreaterOrEquals(loggerContext.getCurrentLevel()); + } + + public void log(Level level, String message, Element element, AnnotationMirror annotationMirror, Throwable thr, Object... args) { + if (!isLoggable(level)) { + return; + } + + loggerContext.writeLog(level, name, message, element, annotationMirror, thr, args); + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/LoggerContext.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/LoggerContext.java new file mode 100644 index 0000000000..fbb8361c8c --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/LoggerContext.java @@ -0,0 +1,92 @@ +package org.androidannotations.logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; + +import org.androidannotations.logger.appender.Appender; +import org.androidannotations.logger.appender.ConsoleAppender; +import org.androidannotations.logger.appender.FileAppender; +import org.androidannotations.logger.appender.MessagerAppender; + +public class LoggerContext { + + public static final String LOG_FILE_OPTION = "logFile"; + public static final String LOG_LEVEL_OPTION = "logLevel"; + public static final String LOG_APPENDER_CONSOLE = "logAppenderConsole"; + private static LoggerContext INSTANCE = null; + private static final Level DEFAULT_LEVEL = Level.DEBUG; + + private Level currentLevel = DEFAULT_LEVEL; + private List appenders = new ArrayList(); + private Formatter formatter = new Formatter(); + + public static LoggerContext getInstance() { + if (INSTANCE == null) { + synchronized (LoggerContext.class) { + if (INSTANCE == null) { + INSTANCE = new LoggerContext(); + } + } + } + return INSTANCE; + } + + LoggerContext() { + appenders.add(new FileAppender()); + appenders.add(new MessagerAppender()); + } + + public void writeLog(Level level, String loggerName, String message, Element element, AnnotationMirror annotationMirror, Throwable thr, Object... args) { + String log = formatter.buildLog(level, loggerName, message, thr, args); + for (Appender appender : appenders) { + appender.append(level, element, annotationMirror, log); + } + } + + public Level getCurrentLevel() { + return currentLevel; + } + + public void setCurrentLevel(Level currentLevel) { + this.currentLevel = currentLevel; + } + + public void setProcessingEnv(ProcessingEnvironment processingEnv) { + for (Appender appender : appenders) { + appender.setProcessingEnv(processingEnv); + appender.open(); + } + + resolveLogLevel(processingEnv); + addConsoleAppender(processingEnv); + } + + public void close() { + for (Appender appender : appenders) { + appender.close(); + } + } + + private void resolveLogLevel(ProcessingEnvironment processingEnv) { + Map options = processingEnv.getOptions(); + if (options.containsKey(LOG_LEVEL_OPTION)) { + Level logLevel = Level.parse(options.get(LOG_LEVEL_OPTION)); + setCurrentLevel(logLevel); + } + } + + private void addConsoleAppender(ProcessingEnvironment processingEnv) { + Map options = processingEnv.getOptions(); + if (options.containsKey(LOG_APPENDER_CONSOLE)) { + if (Boolean.parseBoolean(options.get(LOG_APPENDER_CONSOLE))) { + appenders.add(new ConsoleAppender()); + } + } + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/LoggerFactory.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/LoggerFactory.java new file mode 100644 index 0000000000..77156f16c0 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/LoggerFactory.java @@ -0,0 +1,52 @@ +package org.androidannotations.logger; + +import java.util.HashMap; +import java.util.Map; + +public class LoggerFactory { + + private static final Map LOGGER_CACHE = new HashMap(); + + public static Logger getLogger(Class clazz) { + return getLogger(simpleLoggerName(clazz)); + } + + private static Logger getLogger(String name) { + if (name == null) { + throw new IllegalArgumentException("name argument cannot be null"); + } + + Logger logger = LOGGER_CACHE.get(name); + if (logger == null) { + logger = new Logger(LoggerContext.getInstance(), name); + LOGGER_CACHE.put(name, logger); + } + + return logger; + } + + private static String simpleLoggerName(Class clazz) { + Package classPackage = clazz.getPackage(); + if (classPackage == null) { + return clazz.getName(); + } + + StringBuilder stringBuilder = new StringBuilder(); + + String packageName = classPackage.getName(); + int lastIndex = 0; + while (true) { + stringBuilder.append(packageName.charAt(lastIndex)).append("."); + + lastIndex = packageName.indexOf('.', lastIndex); + if (lastIndex == -1) { + break; + } + lastIndex++; + } + + stringBuilder.append(clazz.getSimpleName()); + + return stringBuilder.toString(); + } +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/Appender.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/Appender.java new file mode 100644 index 0000000000..b9fdba1b37 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/Appender.java @@ -0,0 +1,23 @@ +package org.androidannotations.logger.appender; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; + +import org.androidannotations.logger.Level; + +public abstract class Appender { + + protected ProcessingEnvironment processingEnv; + + public void setProcessingEnv(ProcessingEnvironment processingEnv) { + this.processingEnv = processingEnv; + } + + public abstract void open(); + + public abstract void append(Level level, Element element, AnnotationMirror annotationMirror, String message); + + public abstract void close(); + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/ConsoleAppender.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/ConsoleAppender.java new file mode 100644 index 0000000000..96343982e7 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/ConsoleAppender.java @@ -0,0 +1,27 @@ +package org.androidannotations.logger.appender; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; + +import org.androidannotations.logger.Level; + +public class ConsoleAppender extends Appender { + + @Override + public void open() { + } + + @Override + public void append(Level level, Element element, AnnotationMirror annotationMirror, String message) { + if (level.isSmaller(Level.ERROR)) { + System.out.println(message); + } else { + System.err.println(message); + } + } + + @Override + public void close() { + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/FileAppender.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/FileAppender.java new file mode 100644 index 0000000000..909a553c45 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/FileAppender.java @@ -0,0 +1,100 @@ +package org.androidannotations.logger.appender; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.annotation.processing.Messager; +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.tools.Diagnostic.Kind; + +import org.androidannotations.helper.FileHelper; +import org.androidannotations.logger.Level; +import org.androidannotations.logger.LoggerContext; + +public class FileAppender extends Appender { + + private static final String DEFAULT_FILENAME = "androidannotations.log"; + + private File file; + private FileOutputStream outputStream; + + @Override + public synchronized void open() { + if (!isStreamOpened()) { + try { + outputStream = new FileOutputStream(file, true); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + } + + @Override + public synchronized void close() { + if (isStreamOpened()) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + outputStream = null; + } + } + + @Override + public synchronized void append(Level level, Element element, AnnotationMirror annotationMirror, String message) { + if (isStreamOpened()) { + try { + message += "\n"; + outputStream.write(message.getBytes()); + outputStream.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + @Override + public void setProcessingEnv(ProcessingEnvironment processingEnv) { + super.setProcessingEnv(processingEnv); + resolveLogFile(); + } + + private void resolveLogFile() { + Messager messager = processingEnv.getMessager(); + if (processingEnv.getOptions().containsKey(LoggerContext.LOG_FILE_OPTION)) { + file = resolveLogFileInSpecifiedPath(); + } else { + file = resolveLogFileInParentsDirectories(); + } + + if (file == null) { + messager.printMessage(Kind.WARNING, "Can't resolve log file"); + } else { + messager.printMessage(Kind.NOTE, "Resolve log file to " + file.getAbsolutePath()); + } + } + + private File resolveLogFileInSpecifiedPath() { + File outputDirectory = FileHelper.resolveOutputDirectory(processingEnv); + + String path = processingEnv.getOptions().get(LoggerContext.LOG_FILE_OPTION); + path = path.replace("{outputFolder}", outputDirectory.getAbsolutePath()); + + return new File(path); + } + + private File resolveLogFileInParentsDirectories() { + File outputDirectory = FileHelper.resolveOutputDirectory(processingEnv); + return new File(outputDirectory, DEFAULT_FILENAME); + } + + private boolean isStreamOpened() { + return outputStream != null; + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/MessagerAppender.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/MessagerAppender.java new file mode 100644 index 0000000000..53afade0ff --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/logger/appender/MessagerAppender.java @@ -0,0 +1,49 @@ +package org.androidannotations.logger.appender; + +import javax.annotation.processing.Messager; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.tools.Diagnostic.Kind; + +import org.androidannotations.logger.Level; + +public class MessagerAppender extends Appender { + + private Messager messager; + + @Override + public void open() { + messager = processingEnv.getMessager(); + } + + @Override + public void append(Level level, Element element, AnnotationMirror annotationMirror, String message) { + if (messager == null) { + return; + } + + Kind kind = resolveKind(level); + messager.printMessage(kind, message, element, annotationMirror); + } + + @Override + public void close() { + } + + private Kind resolveKind(Level level) { + switch (level) { + case TRACE: + return Kind.NOTE; + case DEBUG: + return Kind.NOTE; + case INFO: + return Kind.NOTE; + case WARN: + return Kind.WARNING; + case ERROR: + return Kind.ERROR; + } + return Kind.OTHER; + } + +} diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelProcessor.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelProcessor.java index cd0fe5b966..23a0def638 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelProcessor.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelProcessor.java @@ -23,11 +23,13 @@ import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import org.androidannotations.exception.ProcessingException; import org.androidannotations.handler.AnnotationHandler; import org.androidannotations.handler.AnnotationHandlers; import org.androidannotations.handler.GeneratingAnnotationHandler; import org.androidannotations.holder.GeneratedClassHolder; -import org.androidannotations.exception.ProcessingException; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; import org.androidannotations.model.AnnotationElements; import org.androidannotations.model.AnnotationElements.AnnotatedAndRootElements; @@ -35,6 +37,8 @@ public class ModelProcessor { + private static final Logger LOGGER = LoggerFactory.getLogger(ModelProcessor.class); + public static class ProcessResult { public final JCodeModel codeModel; @@ -66,9 +70,16 @@ public ProcessResult process(AnnotationElements validatedModel) throws Processin annotationHandlers.setProcessHolder(processHolder); + LOGGER.info("Processing root elements"); + for (GeneratingAnnotationHandler generatingAnnotationHandler : annotationHandlers.getGenerating()) { String annotationName = generatingAnnotationHandler.getTarget(); Set annotatedElements = validatedModel.getRootAnnotatedElements(annotationName); + + if (!annotatedElements.isEmpty()) { + LOGGER.debug("Processing root elements {}: {}", generatingAnnotationHandler.getClass().getSimpleName(), annotatedElements); + } + for (Element annotatedElement : annotatedElements) { /* * We do not generate code for abstract classes, because the @@ -80,6 +91,8 @@ public ProcessResult process(AnnotationElements validatedModel) throws Processin GeneratedClassHolder generatedClassHolder = generatingAnnotationHandler.createGeneratedClassHolder(processHolder, typeElement); processHolder.put(annotatedElement, generatedClassHolder); processThrowing(generatingAnnotationHandler, annotatedElement, generatedClassHolder); + } else { + LOGGER.trace("Skip element {} because it's abstract", annotatedElement); } } /* @@ -88,6 +101,8 @@ public ProcessResult process(AnnotationElements validatedModel) throws Processin */ } + LOGGER.info("Processing enclosed elements"); + for (AnnotationHandler annotationHandler : annotationHandlers.getDecorating()) { String annotationName = annotationHandler.getTarget(); @@ -96,6 +111,11 @@ public ProcessResult process(AnnotationElements validatedModel) throws Processin * elements, but uses the holder for the root element */ Set ancestorAnnotatedElements = validatedModel.getAncestorAnnotatedElements(annotationName); + + if (!ancestorAnnotatedElements.isEmpty()) { + LOGGER.debug("Processing enclosed elements with {}: {}", annotationHandler.getClass().getSimpleName(), ancestorAnnotatedElements); + } + for (AnnotatedAndRootElements elements : ancestorAnnotatedElements) { GeneratedClassHolder holder = processHolder.getGeneratedClassHolder(elements.rootTypeElement); /* @@ -125,6 +145,8 @@ public ProcessResult process(AnnotationElements validatedModel) throws Processin if (!isAbstractClass(enclosingElement)) { GeneratedClassHolder holder = processHolder.getGeneratedClassHolder(enclosingElement); processThrowing(annotationHandler, annotatedElement, holder); + } else { + LOGGER.trace("Skip element {} because enclosing element {} is abstract", annotatedElement, enclosingElement); } } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelValidator.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelValidator.java index cd9a3dcef3..cea319261e 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelValidator.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/ModelValidator.java @@ -20,14 +20,17 @@ import javax.lang.model.element.Element; +import org.androidannotations.exception.ProcessingException; import org.androidannotations.handler.AnnotationHandler; import org.androidannotations.handler.AnnotationHandlers; -import org.androidannotations.exception.ProcessingException; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; import org.androidannotations.model.AnnotationElements; import org.androidannotations.model.AnnotationElementsHolder; public class ModelValidator { + private static final Logger LOGGER = LoggerFactory.getLogger(ModelValidator.class); private AnnotationHandlers annotationHandlers; public ModelValidator(AnnotationHandlers annotationHandlers) { @@ -36,6 +39,8 @@ public ModelValidator(AnnotationHandlers annotationHandlers) { public AnnotationElements validate(AnnotationElementsHolder extractedModel) throws ProcessingException, Exception { + LOGGER.info("Validating elements"); + /* * We currently do not validate the elements on the ancestors, assuming * they've already been validated. This also means some checks such as @@ -44,6 +49,7 @@ public AnnotationElements validate(AnnotationElementsHolder extractedModel) thro AnnotationElementsHolder validatedElements = extractedModel.validatingHolder(); for (AnnotationHandler annotationHandler : annotationHandlers.get()) { + String validatorSimpleName = annotationHandler.getClass().getSimpleName(); String annotationName = annotationHandler.getTarget(); Set annotatedElements = extractedModel.getRootAnnotatedElements(annotationName); @@ -52,12 +58,19 @@ public AnnotationElements validate(AnnotationElementsHolder extractedModel) thro validatedElements.putRootAnnotatedElements(annotationName, validatedAnnotatedElements); + if (!annotatedElements.isEmpty()) { + LOGGER.debug("Validating with {}: {}", validatorSimpleName, annotatedElements); + } + for (Element annotatedElement : annotatedElements) { if (validateThrowing(annotationHandler, annotatedElement, validatedElements)) { validatedAnnotatedElements.add(annotatedElement); + } else { + LOGGER.warn("Element {} unvalidated by {}", annotatedElement, validatorSimpleName); } } } + return validatedElements; } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/TimeStats.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/TimeStats.java index e2f067d953..c507534996 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/TimeStats.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/process/TimeStats.java @@ -21,11 +21,13 @@ import java.util.List; import java.util.Map; -import javax.annotation.processing.Messager; -import javax.tools.Diagnostic; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; public class TimeStats { + private static final Logger LOGGER = LoggerFactory.getLogger(TimeStats.class); + private final Map measures = new HashMap(); private final List durations = new ArrayList(); @@ -44,8 +46,6 @@ public int compareTo(Duration o) { } } - private Messager messager; - public void start(String key) { long start = System.currentTimeMillis(); measures.put(key, start); @@ -62,7 +62,6 @@ public void stop(String key) { @Override public String toString() { - StringBuilder sb = new StringBuilder(); sb.append("Time measurements: "); @@ -79,13 +78,7 @@ public String toString() { } public void logStats() { - if (messager != null) { - messager.printMessage(Diagnostic.Kind.NOTE, toString()); - } - } - - public void setMessager(Messager messager) { - this.messager = messager; + LOGGER.info(toString()); } public void clear() { diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java index 21d1314e94..88c0ef155e 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/AndroidRClassFinder.java @@ -15,15 +15,18 @@ */ package org.androidannotations.rclass; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic.Kind; +import javax.lang.model.util.Elements; import org.androidannotations.helper.Option; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; public class AndroidRClassFinder { + private static final Logger LOGGER = LoggerFactory.getLogger(AndroidRClassFinder.class); + private final ProcessingEnvironment processingEnv; public AndroidRClassFinder(ProcessingEnvironment processingEnv) { @@ -31,12 +34,15 @@ public AndroidRClassFinder(ProcessingEnvironment processingEnv) { } public Option find() { - TypeElement androidRType = processingEnv.getElementUtils().getTypeElement("android.R"); + Elements elementUtils = processingEnv.getElementUtils(); + TypeElement androidRType = elementUtils.getTypeElement("android.R"); if (androidRType == null) { - Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.ERROR, "The android.R class cannot be found"); + LOGGER.error("The android.R class cannot be found"); return Option.absent(); } + + LOGGER.info("Found Android class: {}", androidRType.toString()); + return Option. of(new RClass(androidRType)); } } diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java index 32c22a8251..e21496e8c4 100644 --- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java +++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/rclass/ProjectRClassFinder.java @@ -15,18 +15,19 @@ */ package org.androidannotations.rclass; -import javax.annotation.processing.Messager; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; -import javax.tools.Diagnostic.Kind; import org.androidannotations.helper.AndroidManifest; import org.androidannotations.helper.Option; +import org.androidannotations.logger.Logger; +import org.androidannotations.logger.LoggerFactory; public class ProjectRClassFinder { public static final String RESOURCE_PACKAGE_NAME_OPTION = "resourcePackageName"; + private static final Logger LOGGER = LoggerFactory.getLogger(ProjectRClassFinder.class); private ProcessingEnvironment processingEnv; @@ -35,17 +36,17 @@ public ProjectRClassFinder(ProcessingEnvironment processingEnv) { } public Option find(AndroidManifest manifest) { - Elements elementUtils = processingEnv.getElementUtils(); String rClass = getRClassPackageName(manifest) + ".R"; TypeElement rType = elementUtils.getTypeElement(rClass); if (rType == null) { - Messager messager = processingEnv.getMessager(); - messager.printMessage(Kind.ERROR, "The generated " + rClass + " class cannot be found"); + LOGGER.error("The generated {} class cannot be found", rClass); return Option.absent(); } + LOGGER.info("Found project R class: {}", rType.toString()); + return Option. of(new RClass(rType)); } diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/logger/FormatterTest.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/logger/FormatterTest.java new file mode 100644 index 0000000000..b7c86d1593 --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/logger/FormatterTest.java @@ -0,0 +1,52 @@ +package org.androidannotations.logger; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; + +public class FormatterTest { + + private Formatter formatter = new Formatter(); + + class SomeObject { + String name; + + public SomeObject(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + + @Test + public void testBuildFullMessage_string() throws Exception { + Assert.assertEquals("This is a test", formatter.buildFullMessage("{} is a test", "This")); + Assert.assertEquals("This is a test", formatter.buildFullMessage("This is a {}", "test")); + Assert.assertEquals("This is a test", formatter.buildFullMessage("This {} {} test", "is", "a")); + Assert.assertEquals("This is a test", formatter.buildFullMessage("This {} a test", "is", "a")); + } + + @Test + public void testBuildFullMessage_int_array() throws Exception { + Integer[] values = new Integer[] { 1, 2 }; + Assert.assertEquals("Values = [1, 2]", formatter.buildFullMessage("Values = {}", new Object[] { values })); + } + + @Test + public void testBuildFullMessage_object_array() throws Exception { + SomeObject[] values = new SomeObject[] { new SomeObject("a"), new SomeObject("b") }; + Assert.assertEquals("Objects = [a, b]", formatter.buildFullMessage("Objects = {}", new Object[] { values })); + } + + @Test + public void testBuildFullMessage_list() throws Exception { + List values = Arrays.asList(new SomeObject("a"), new SomeObject("b")); + Assert.assertEquals("Objects = [a, b]", formatter.buildFullMessage("Objects = {}", values)); + } + +} diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/logger/LoggerTest.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/logger/LoggerTest.java new file mode 100644 index 0000000000..441c65c81f --- /dev/null +++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/logger/LoggerTest.java @@ -0,0 +1,20 @@ +package org.androidannotations.logger; + +import junit.framework.Assert; + +import org.junit.Test; + +public class LoggerTest { + + @Test + public void testIsLoggable() throws Exception { + LoggerContext loggerContext = LoggerContext.getInstance(); + loggerContext.setCurrentLevel(Level.INFO); + Logger logger = new Logger(loggerContext, getClass().getName()); + + Assert.assertFalse(logger.isLoggable(Level.DEBUG)); + Assert.assertTrue(logger.isLoggable(Level.INFO)); + Assert.assertTrue(logger.isLoggable(Level.WARN)); + } + +} diff --git a/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs b/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs index ef6fa98563..30bc889a84 100644 --- a/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs +++ b/AndroidAnnotations/functional-test-1-5/.settings/org.eclipse.jdt.apt.core.prefs @@ -1,5 +1,7 @@ eclipse.preferences.version=1 org.eclipse.jdt.apt.aptEnabled=true org.eclipse.jdt.apt.genSrcDir=.apt_generated +org.eclipse.jdt.apt.processorOptions/logFile={outputFolder}/functional-test.log +org.eclipse.jdt.apt.processorOptions/logLevel=DEBUG org.eclipse.jdt.apt.processorOptions/trace=true org.eclipse.jdt.apt.reconcileEnabled=true