Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
import org.androidannotations.generation.CodeModelGenerator;
import org.androidannotations.helper.AndroidManifest;
import org.androidannotations.helper.AndroidManifestFinder;
import org.androidannotations.helper.Option;
import org.androidannotations.helper.TimeStats;
import org.androidannotations.model.AndroidRes;
import org.androidannotations.model.AndroidSystemServices;
Expand Down Expand Up @@ -355,19 +356,29 @@ private void processThrowing(Set<? extends TypeElement> annotations, RoundEnviro

AnnotationElementsHolder extractedModel = extractAnnotations(annotations, roundEnv);

AndroidManifest androidManifest = extractAndroidManifest();
Option<AndroidManifest> androidManifestOption = extractAndroidManifest();

IRClass rClass = findRClasses(androidManifest);
if (androidManifestOption.isAbsent()) {
return;
}

AndroidManifest androidManifest = androidManifestOption.get();

Option<IRClass> rClassOption = findRClasses(androidManifest);

if (rClassOption.isAbsent()) {
return;
}

IRClass rClass = rClassOption.get();

AndroidSystemServices androidSystemServices = new AndroidSystemServices();

AnnotationElements validatedModel = validateAnnotations(extractedModel, rClass, androidSystemServices, androidManifest);

if (validatedModel != null) {
ProcessResult processResult = processAnnotations(validatedModel, rClass, androidSystemServices, androidManifest);
ProcessResult processResult = processAnnotations(validatedModel, rClass, androidSystemServices, androidManifest);

generateSources(processResult);
}
generateSources(processResult);
}

private boolean nothingToDo(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Expand All @@ -382,39 +393,39 @@ private AnnotationElementsHolder extractAnnotations(Set<? extends TypeElement> a
return extractedModel;
}

private AndroidManifest extractAndroidManifest() {
private Option<AndroidManifest> extractAndroidManifest() {
timeStats.start("Extract Manifest");
AndroidManifestFinder finder = new AndroidManifestFinder(processingEnv);
AndroidManifest manifest = finder.extractAndroidManifest();
Option<AndroidManifest> manifest = finder.extractAndroidManifest();
timeStats.stop("Extract Manifest");
return manifest;
}

private IRClass findRClasses(AndroidManifest androidManifest) throws IOException {
private Option<IRClass> findRClasses(AndroidManifest androidManifest) throws IOException {
timeStats.start("Find R Classes");
ProjectRClassFinder rClassFinder = new ProjectRClassFinder(processingEnv);
IRClass rClass = rClassFinder.find(androidManifest);

Option<IRClass> rClass = rClassFinder.find(androidManifest);

AndroidRClassFinder androidRClassFinder = new AndroidRClassFinder(processingEnv);

IRClass androidRClass = androidRClassFinder.find();
Option<IRClass> androidRClass = androidRClassFinder.find();

CoumpoundRClass coumpoundRClass = new CoumpoundRClass(rClass, androidRClass);
if (rClass.isAbsent() || androidRClass.isAbsent()) {
return Option.absent();
}

IRClass coumpoundRClass = new CoumpoundRClass(rClass.get(), androidRClass.get());

timeStats.stop("Find R Classes");

return coumpoundRClass;
return Option.of(coumpoundRClass);
}

private AnnotationElements validateAnnotations(AnnotationElementsHolder extractedModel, IRClass rClass, AndroidSystemServices androidSystemServices, AndroidManifest androidManifest) {
timeStats.start("Validate Annotations");
AnnotationElements validatedAnnotations;
if (rClass != null) {
ModelValidator modelValidator = buildModelValidator(rClass, androidSystemServices, androidManifest);
validatedAnnotations = modelValidator.validate(extractedModel);
} else {
validatedAnnotations = null;
}
ModelValidator modelValidator = buildModelValidator(rClass, androidSystemServices, androidManifest);
AnnotationElements validatedAnnotations = modelValidator.validate(extractedModel);
timeStats.stop("Validate Annotations");
return validatedAnnotations;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,14 @@ public AndroidManifestFinder(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}

public AndroidManifest extractAndroidManifest() {
try {
return extractAndroidManifestThrowing();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e);
public Option<AndroidManifest> extractAndroidManifest() {
Option<File> androidManifestFileOption = findManifestFile();

if (androidManifestFileOption.isAbsent()) {
return Option.absent();
}
}

private AndroidManifest extractAndroidManifestThrowing() throws Exception {
File androidManifestFile = findManifestFileThrowing();
File androidManifestFile = androidManifestFileOption.get();

String projectDirectory = androidManifestFile.getParent();

Expand All @@ -71,39 +66,41 @@ private AndroidManifest extractAndroidManifestThrowing() throws Exception {
boolean libraryProject = false;
if (projectProperties.exists()) {
Properties properties = new Properties();
properties.load(new FileInputStream(projectProperties));

if (properties.containsKey("android.library")) {
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);
try {
properties.load(new FileInputStream(projectProperties));
if (properties.containsKey("android.library")) {
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);
}
} catch (IOException ignored) {
}

}

return parseThrowing(androidManifestFile, libraryProject);
return parse(androidManifestFile, libraryProject);
}

private File findManifestFileThrowing() throws Exception {
private Option<File> findManifestFile() {
if (processingEnv.getOptions().containsKey(ANDROID_MANIFEST_FILE_OPTION)) {
return findManifestInSpecifiedPath();
} else {
return findManifestInParentsDirectories();
}
}

private File findManifestInSpecifiedPath() {
private Option<File> findManifestInSpecifiedPath() {
String path = processingEnv.getOptions().get(ANDROID_MANIFEST_FILE_OPTION);
File androidManifestFile = new File(path);
Messager messager = processingEnv.getMessager();
if (!androidManifestFile.exists()) {
throw new IllegalStateException("Could not find the AndroidManifest.xml file in specified path : " + path);
messager.printMessage(Kind.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());
}
return androidManifestFile;
return Option.of(androidManifestFile);
}

/**
Expand All @@ -113,10 +110,18 @@ private File findManifestInSpecifiedPath() {
* find the AndroidManifest.xml file. Any better solution will be
* appreciated.
*/
private File findManifestInParentsDirectories() throws IOException, URISyntaxException {
private Option<File> findManifestInParentsDirectories() {
Filer filer = processingEnv.getFiler();

JavaFileObject dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis());
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");
return Option.absent();
}
String dummySourceFilePath = dummySourceFile.toUri().toString();

if (dummySourceFilePath.startsWith("file:")) {
Expand All @@ -127,10 +132,13 @@ private File findManifestInParentsDirectories() throws IOException, URISyntaxExc
dummySourceFilePath = "file://" + dummySourceFilePath;
}

Messager messager = processingEnv.getMessager();
messager.printMessage(Kind.NOTE, "Dummy source file: " + dummySourceFilePath);

URI cleanURI = new URI(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);

Expand All @@ -153,27 +161,36 @@ private File findManifestInParentsDirectories() throws IOException, URISyntaxExc
}

if (!androidManifestFile.exists()) {
throw new IllegalStateException("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 + ")");
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 + ")");
return Option.absent();
} else {
messager.printMessage(Kind.NOTE, "AndroidManifest.xml file found: " + androidManifestFile.toString());
}

return androidManifestFile;
return Option.of(androidManifestFile);
}

private AndroidManifest parseThrowing(File androidManifestFile, boolean libraryProject) throws Exception {
private Option<AndroidManifest> parse(File androidManifestFile, boolean libraryProject) {

DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(androidManifestFile);

Document doc;
try {
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);
return Option.absent();
}

Element documentElement = doc.getDocumentElement();
documentElement.normalize();

String applicationPackage = documentElement.getAttribute("package");

if (libraryProject) {
return AndroidManifest.createLibraryManifest(applicationPackage);
return Option.of(AndroidManifest.createLibraryManifest(applicationPackage));
}

NodeList applicationNodes = documentElement.getElementsByTagName("application");
Expand Down Expand Up @@ -214,7 +231,7 @@ private AndroidManifest parseThrowing(File androidManifestFile, boolean libraryP
componentQualifiedNames.addAll(receiverQualifiedNames);
componentQualifiedNames.addAll(providerQualifiedNames);

return AndroidManifest.createManifest(applicationPackage, applicationQualifiedName, componentQualifiedNames);
return Option.of(AndroidManifest.createManifest(applicationPackage, applicationQualifiedName, componentQualifiedNames));
}

private List<String> extractComponentNames(String applicationPackage, NodeList componentNodes) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.androidannotations.helper;

/**
* I'd love to use Guava's Optional, but we're trying to keep the dependency
* level to a minimum.
*/
public class Option<T> {

private static final Option<?> ABSENT = new Option<Object>(null, false);

public static <T> Option<T> of(T value) {
return new Option<T>(value, true);
}

@SuppressWarnings("unchecked")
public static <T> Option<T> absent() {
return (Option<T>) ABSENT;
}

private final T reference;

private final boolean isPresent;

private Option(T reference, boolean isPresent) {
this.reference = reference;
this.isPresent = isPresent;
}

public boolean isPresent() {
return isPresent;
}

public boolean isAbsent() {
return !isPresent;
}

public T get() {
if (!isPresent) {
throw new IllegalStateException("value is absent");
}
return reference;
}

public T getOr(T defaultValue) {
if (isPresent) {
return reference;
} else {
return defaultValue;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
*/
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 org.androidannotations.helper.Option;

public class AndroidRClassFinder {

Expand All @@ -26,9 +30,13 @@ public AndroidRClassFinder(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}

public IRClass find() {
public Option<IRClass> find() {
TypeElement androidRType = processingEnv.getElementUtils().getTypeElement("android.R");
return new RClass(androidRType);
if (androidRType == null) {
Messager messager = processingEnv.getMessager();
messager.printMessage(Kind.ERROR, "The android.R class cannot be found");
return Option.absent();
}
return Option.<IRClass> of(new RClass(androidRType));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,4 @@ public String rName() {

IRInnerClass get(Res res);

final IRClass EMPTY_R_CLASS = new IRClass() {
@Override
public IRInnerClass get(Res res) {
return IRInnerClass.EMPTY_R_INNER_CLASS;
}
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javax.tools.Diagnostic.Kind;

import org.androidannotations.helper.AndroidManifest;
import org.androidannotations.helper.Option;

public class ProjectRClassFinder {

Expand All @@ -31,19 +32,18 @@ public ProjectRClassFinder(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}

public IRClass find(AndroidManifest manifest) {
public Option<IRClass> find(AndroidManifest manifest) {

Elements elementUtils = processingEnv.getElementUtils();
String rClass = manifest.getApplicationPackage() + ".R";
TypeElement rType = elementUtils.getTypeElement(rClass);

if (rType == null) {
Messager messager = processingEnv.getMessager();
messager.printMessage(Kind.WARNING, "The AndroidManifest.xml file was found, but not the compiled R class: " + rClass);
return IRClass.EMPTY_R_CLASS;
messager.printMessage(Kind.ERROR, "The generated " + rClass + " class cannot be found");
return Option.absent();
}

return new RClass(rType);
return Option.<IRClass> of(new RClass(rType));
}

}
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.