Skip to content

Commit 6133b7b

Browse files
committed
Merge pull request androidannotations#1543 from WonderCsabo/1478_betterAndroidManifestFinder
Use a better AndroidManifest.xml finder
2 parents 88dbd21 + a411a69 commit 6133b7b

8 files changed

Lines changed: 224 additions & 61 deletions

File tree

‎AndroidAnnotations/androidannotations-core/androidannotations-test/pom.xml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@
100100
<arg>-Atrace=true</arg>
101101
<arg>-AlogLevel=WARNING</arg>
102102
<arg>-AlogFile=${project.build.directory}/functional-test.log</arg>
103-
<arg>-AandroidManifestFile=${project.basedir}/src/main/AndroidManifest.xml</arg>
104103
</compilerArgs>
105104
</configuration>
106105
</plugin>

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/helper/AndroidManifestFinder.java‎

Lines changed: 99 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@
2222
import java.io.FileNotFoundException;
2323
import java.io.IOException;
2424
import java.util.ArrayList;
25+
import java.util.Arrays;
26+
import java.util.Collections;
2527
import java.util.List;
2628
import java.util.Properties;
29+
import java.util.regex.Matcher;
30+
import java.util.regex.Pattern;
2731

2832
import javax.lang.model.util.Elements;
2933
import javax.xml.parsers.DocumentBuilder;
@@ -46,7 +50,6 @@ public class AndroidManifestFinder {
4650
public static final Option OPTION_MANIFEST = new Option("androidManifestFile", null);
4751

4852
private static final Logger LOGGER = LoggerFactory.getLogger(AndroidManifestFinder.class);
49-
private static final int MAX_PARENTS_FROM_SOURCE_FOLDER = 10;
5053

5154
private final AndroidAnnotationsEnvironment environment;
5255

@@ -88,7 +91,7 @@ private File findManifestFile() throws FileNotFoundException {
8891
if (androidManifestFile != null) {
8992
return findManifestInSpecifiedPath(androidManifestFile);
9093
} else {
91-
return findManifestInParentsDirectories();
94+
return findManifestInKnownPaths();
9295
}
9396
}
9497

@@ -103,43 +106,110 @@ private File findManifestInSpecifiedPath(String androidManifestPath) throws File
103106
return androidManifestFile;
104107
}
105108

106-
/**
107-
* We use a dirty trick to find the AndroidManifest.xml file, since it's not
108-
* available in the classpath. The idea is quite simple : create a fake
109-
* class file, retrieve its URI, and start going up in parent folders to
110-
* find the AndroidManifest.xml file. Any better solution will be
111-
* appreciated.
112-
*/
113-
private File findManifestInParentsDirectories() throws FileNotFoundException {
114-
FileHelper.FileHolder projectRootHolder = FileHelper.findRootProjectHolder(environment.getProcessingEnvironment());
115-
116-
File projectRoot = projectRootHolder.projectRoot;
117-
118-
File androidManifestFile = new File(projectRoot, "AndroidManifest.xml");
119-
for (int i = 0; i < MAX_PARENTS_FROM_SOURCE_FOLDER; i++) {
120-
if (androidManifestFile.exists()) {
109+
private File findManifestInKnownPaths() throws FileNotFoundException {
110+
FileHelper.FileHolder holder = FileHelper.findRootProjectHolder(environment.getProcessingEnvironment());
111+
return findManifestInKnownPathsStartingFromGenFolder(holder.sourcesGenerationFolder.getAbsolutePath());
112+
}
113+
114+
File findManifestInKnownPathsStartingFromGenFolder(String sourcesGenerationFolder) throws FileNotFoundException {
115+
Iterable<AndroidManifestFinderStrategy> strategies = Arrays.asList(new GradleAndroidManifestFinderStrategy(sourcesGenerationFolder),
116+
new MavenAndroidManifestFinderStrategy(sourcesGenerationFolder), new EclipseAndroidManifestFinderStrategy(sourcesGenerationFolder));
117+
118+
AndroidManifestFinderStrategy applyingStrategy = null;
119+
120+
for (AndroidManifestFinderStrategy strategy : strategies) {
121+
if (strategy.applies()) {
122+
applyingStrategy = strategy;
121123
break;
122-
} else {
123-
if (projectRoot.getParentFile() != null) {
124-
projectRoot = projectRoot.getParentFile();
125-
androidManifestFile = new File(projectRoot, "AndroidManifest.xml");
126-
} else {
127-
break;
128-
}
129124
}
130125
}
131126

132-
if (!androidManifestFile.exists()) {
133-
LOGGER.error("Could not find the AndroidManifest.xml file, going up from path [{}] found using dummy file [{}] (max atempts: {})",
134-
projectRootHolder.sourcesGenerationFolder.getAbsolutePath(), projectRootHolder.dummySourceFilePath, MAX_PARENTS_FROM_SOURCE_FOLDER);
135-
throw new FileNotFoundException();
127+
File androidManifestFile = null;
128+
129+
if (applyingStrategy != null) {
130+
androidManifestFile = applyingStrategy.findAndroidManifestFile();
131+
}
132+
133+
if (androidManifestFile != null) {
134+
LOGGER.debug("{} AndroidManifest.xml file found using generation folder {}: {}", applyingStrategy.name, sourcesGenerationFolder, androidManifestFile.toString());
136135
} else {
137-
LOGGER.debug("AndroidManifest.xml file found in parent folder {}: {}", projectRoot.getAbsolutePath(), androidManifestFile.toString());
136+
LOGGER.error("Could not find the AndroidManifest.xml file, using generation folder [{}])", sourcesGenerationFolder);
138137
}
139138

140139
return androidManifestFile;
141140
}
142141

142+
private static abstract class AndroidManifestFinderStrategy {
143+
final String name;
144+
145+
final Matcher matcher;
146+
147+
AndroidManifestFinderStrategy(String name, Pattern sourceFolderPattern, String sourceFolder) {
148+
this.name = name;
149+
this.matcher = sourceFolderPattern.matcher(sourceFolder);
150+
}
151+
152+
File findAndroidManifestFile() {
153+
for (String location : possibleLocations()) {
154+
File manifestFile = new File(matcher.group(1), location + "/AndroidManifest.xml");
155+
if (manifestFile.exists()) {
156+
return manifestFile;
157+
}
158+
}
159+
return null;
160+
}
161+
162+
boolean applies() {
163+
return matcher.matches();
164+
}
165+
166+
abstract Iterable<String> possibleLocations();
167+
}
168+
169+
private static class GradleAndroidManifestFinderStrategy extends AndroidManifestFinderStrategy {
170+
171+
static final Pattern GRADLE_GEN_FOLDER = Pattern.compile("^(.*?)build[\\\\/]generated[\\\\/]source[\\\\/]apt(.*)$");
172+
173+
GradleAndroidManifestFinderStrategy(String sourceFolder) {
174+
super("Gradle", GRADLE_GEN_FOLDER, sourceFolder);
175+
}
176+
177+
@Override
178+
Iterable<String> possibleLocations() {
179+
String gradleVariant = matcher.group(2);
180+
181+
return Arrays.asList("build/intermediates/manifests/full" + gradleVariant, "build/bundles" + gradleVariant);
182+
}
183+
}
184+
185+
private static class MavenAndroidManifestFinderStrategy extends AndroidManifestFinderStrategy {
186+
187+
static final Pattern MAVEN_GEN_FOLDER = Pattern.compile("^(.*?)target[\\\\/]generated-sources.*$");
188+
189+
MavenAndroidManifestFinderStrategy(String sourceFolder) {
190+
super("Maven", MAVEN_GEN_FOLDER, sourceFolder);
191+
}
192+
193+
@Override
194+
Iterable<String> possibleLocations() {
195+
return Arrays.asList("target", "src/main", "");
196+
}
197+
}
198+
199+
private static class EclipseAndroidManifestFinderStrategy extends AndroidManifestFinderStrategy {
200+
201+
static final Pattern ECLIPSE_GEN_FOLDER = Pattern.compile("^(.*?)\\.apt_generated.*$");
202+
203+
EclipseAndroidManifestFinderStrategy(String sourceFolder) {
204+
super("Eclipse", ECLIPSE_GEN_FOLDER, sourceFolder);
205+
}
206+
207+
@Override
208+
Iterable<String> possibleLocations() {
209+
return Collections.singleton("");
210+
}
211+
}
212+
143213
private AndroidManifest parse(File androidManifestFile, boolean libraryProject) throws AndroidManifestNotFoundException {
144214
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
145215

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright (C) 2010-2015 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.internal.helper;
17+
18+
import static org.junit.Assert.assertEquals;
19+
import static org.junit.Assert.fail;
20+
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
25+
import java.util.Arrays;
26+
import java.util.Objects;
27+
28+
import org.junit.Test;
29+
import org.junit.runner.RunWith;
30+
import org.junit.runners.Parameterized;
31+
32+
@RunWith(Parameterized.class)
33+
public class AndroidManifestFinderTest {
34+
35+
private static final String GRADLE_GEN_FOLDER = "build/generated/source/apt/debug";
36+
37+
private static final String MAVEN_GEN_FOLDER = "target/generated-sources/annotations";
38+
39+
private static final String ECLIPSE_GEN_FOLDER = ".apt_generated";
40+
41+
private final String genFolderPath;
42+
private final String manifestFolderPath;
43+
private final boolean shouldFind;
44+
45+
private Path tempDirectory;
46+
47+
public AndroidManifestFinderTest(String genFolderPath, String manifestFolderPath, boolean shouldFind) {
48+
this.genFolderPath = genFolderPath;
49+
this.manifestFolderPath = manifestFolderPath;
50+
this.shouldFind = shouldFind;
51+
}
52+
53+
@Parameterized.Parameters(name = "genFolderPath = {0}, manifestFolderPath = {1}, shouldFind = {2}")
54+
public static Iterable<Object[]> createTestData() {
55+
56+
Object[] gradleManifestFoundInManifests = { GRADLE_GEN_FOLDER, "build/intermediates/manifests/full/debug", true };
57+
Object[] gradleManifestFoundInBundles = { GRADLE_GEN_FOLDER, "build/bundles/debug", true };
58+
59+
Object[] mavenManifestFoundInTarget = { MAVEN_GEN_FOLDER, "target", true };
60+
Object[] mavenManifestFoundInSrc = { MAVEN_GEN_FOLDER, "src/main", true };
61+
Object[] mavenManifestFoundInRoot = { MAVEN_GEN_FOLDER, "", true };
62+
63+
Object[] eclipseManifestFound = { ECLIPSE_GEN_FOLDER, "", true };
64+
65+
Object[] gradleManifestNotFound = { GRADLE_GEN_FOLDER, "", false };
66+
67+
Object[] mavenManifestNotFound = { MAVEN_GEN_FOLDER, "something", false };
68+
69+
Object[] eclipseManifestNotFound = { ECLIPSE_GEN_FOLDER, "something", false };
70+
71+
Object[] noGeneratedFolderFound = { "", "", false };
72+
73+
return Arrays.asList(gradleManifestFoundInManifests, gradleManifestFoundInBundles, mavenManifestFoundInTarget, mavenManifestFoundInSrc, mavenManifestFoundInRoot, eclipseManifestFound,
74+
gradleManifestNotFound, mavenManifestNotFound, eclipseManifestNotFound, noGeneratedFolderFound);
75+
}
76+
77+
@Test
78+
public void testFindManifestInKnownPathsStartingFromGenFolder() throws IOException {
79+
AndroidManifestFinder finder = new AndroidManifestFinder(null);
80+
tempDirectory = Files.createTempDirectory("AA");
81+
82+
File genFolder = createGenFolder(genFolderPath);
83+
84+
File manifestFolder = new File(tempDirectory.toString(), manifestFolderPath);
85+
createFolder(manifestFolder);
86+
87+
File expectedManifest = new File(manifestFolder, "AndroidManifest.xml");
88+
createFile(expectedManifest);
89+
90+
File foundManifest = finder.findManifestInKnownPathsStartingFromGenFolder(genFolder.getAbsolutePath());
91+
92+
assertEquals(shouldFind, Objects.equals(expectedManifest, foundManifest));
93+
}
94+
95+
private File createGenFolder(String genFolder) {
96+
File genFolderFile = new File(tempDirectory.toString(), genFolder);
97+
createFolder(genFolderFile);
98+
99+
return genFolderFile;
100+
}
101+
102+
private void createFolder(File folder) {
103+
if (folder.exists()) {
104+
return;
105+
}
106+
107+
boolean folderCreated = folder.mkdirs();
108+
109+
if (!folderCreated) {
110+
fail("Could not create test folder: " + folder);
111+
}
112+
}
113+
114+
private void createFile(File file) throws IOException {
115+
if (file.exists()) {
116+
return;
117+
}
118+
119+
boolean fileCreated = file.createNewFile();
120+
121+
if (!fileCreated) {
122+
fail("Could not creates test manifest" + file);
123+
}
124+
}
125+
}

‎AndroidAnnotations/androidannotations-core/androidannotations/src/test/java/org/androidannotations/manifest/AndroidManifestFinderTest.java‎

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@
1515
*/
1616
package org.androidannotations.manifest;
1717

18-
import java.io.File;
19-
import java.io.IOException;
20-
import java.nio.file.Files;
21-
2218
import org.androidannotations.internal.AndroidAnnotationProcessor;
2319
import org.androidannotations.testutils.AAProcessorTestHelper;
2420
import org.junit.Before;
@@ -53,15 +49,6 @@ public void failsIfCannotFindSpecifiedManifest() {
5349
assertCompilationErrorCount(1, result);
5450
}
5551

56-
@Test
57-
public void findsManifestInGeneratedSourceParentFolder() throws Exception {
58-
deleteManifestFromParentOfOutputDirectory();
59-
copyManifestToParentOfOutputDirectory();
60-
CompileResult result = compileFiles(SomeClass.class);
61-
assertCompilationSuccessful(result);
62-
deleteManifestFromParentOfOutputDirectory();
63-
}
64-
6552
@Test
6653
public void failsIfCannotParseManifest() {
6754
addManifestProcessorParameter(AndroidManifestFinderTest.class, "ParseErrorManifest.xml");
@@ -70,18 +57,4 @@ public void failsIfCannotParseManifest() {
7057
assertCompilationErrorCount(1, result);
7158
}
7259

73-
private void deleteManifestFromParentOfOutputDirectory() {
74-
manifestFileInParentOfOutputDirectory().delete();
75-
}
76-
77-
private void copyManifestToParentOfOutputDirectory() throws IOException {
78-
Files.copy(AndroidManifestFinderTest.class.getResourceAsStream("AndroidManifest.xml"), manifestFileInParentOfOutputDirectory().toPath());
79-
}
80-
81-
private File manifestFileInParentOfOutputDirectory() {
82-
File outputDirectory = getOuputDirectory();
83-
File manifestFile = new File(outputDirectory.getParentFile(), "AndroidManifest.xml");
84-
return manifestFile;
85-
}
86-
8760
}

‎AndroidAnnotations/androidannotations-ormlite/ormlite-test/pom.xml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@
9898
<showWarnings>true</showWarnings>
9999
<compilerArgs>
100100
<arg>-AlogLevel=WARNING</arg>
101-
<arg>-AandroidManifestFile=${project.basedir}/src/main/AndroidManifest.xml</arg>
102101
</compilerArgs>
103102
</configuration>
104103
</plugin>

‎AndroidAnnotations/androidannotations-otto/otto-test/pom.xml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@
9090
<showWarnings>true</showWarnings>
9191
<compilerArgs>
9292
<arg>-AlogLevel=WARNING</arg>
93-
<arg>-AandroidManifestFile=${project.basedir}/src/main/AndroidManifest.xml</arg>
9493
</compilerArgs>
9594
</configuration>
9695
</plugin>

‎AndroidAnnotations/androidannotations-rest-spring/rest-spring-test/pom.xml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@
122122
<showWarnings>true</showWarnings>
123123
<compilerArgs>
124124
<arg>-AlogLevel=WARNING</arg>
125-
<arg>-AandroidManifestFile=${project.basedir}/src/main/AndroidManifest.xml</arg>
126125
</compilerArgs>
127126
</configuration>
128127
</plugin>

‎AndroidAnnotations/androidannotations-roboguice/roboguice-test/pom.xml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@
9898
<showWarnings>true</showWarnings>
9999
<compilerArgs>
100100
<arg>-AlogLevel=WARNING</arg>
101-
<arg>-AandroidManifestFile=${project.basedir}/src/main/AndroidManifest.xml</arg>
102101
</compilerArgs>
103102
</configuration>
104103
</plugin>

0 commit comments

Comments
 (0)