/**
* Copyright 2011-2015 John Ericksen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.androidtransfuse.util;
import org.androidtransfuse.TransfuseAnalysisException;
import javax.annotation.processing.Filer;
import javax.inject.Inject;
import javax.inject.Named;
import javax.tools.JavaFileObject;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Copied respectfully from the AndroidAnnotations project:
* com.googlecode.androidannotations.helper.AndroidManifestFinder
*
* Original Header:
*
* Copyright (C) 2010-2011 eBusiness Information, Excilys Group
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @author John Ericksen
*/
public class ManifestLocator {
public static final String ANDROID_MANIFEST_FILE_OPTION = "androidManifestFile";
private static final int MAX_PARENTS_FROM_SOURCE_FOLDER = 10;
private final String androidManifestFilePath;
private final Filer filer;
private final Logger log;
@Inject
public ManifestLocator(Filer filer, Logger log, @Named(ANDROID_MANIFEST_FILE_OPTION) String androidManifestFilePath) {
this.filer = filer;
this.log = log;
this.androidManifestFilePath = androidManifestFilePath;
}
public File findManifest() {
File androidManifestFile;
try {
if (androidManifestFilePath != null) {
androidManifestFile = new File(androidManifestFilePath);
if (!androidManifestFile.exists()) {
log.error("Could not find the AndroidManifest.xml file specified by option " + ANDROID_MANIFEST_FILE_OPTION + " [" + androidManifestFilePath + "]");
} else {
log.debug("AndroidManifest.xml file found: " + androidManifestFile.toString());
}
} else {
// Backwards compatibility
androidManifestFile = findManifestFileThrowing();
}
} catch (URISyntaxException e) {
log.error("URISyntaxException while trying to load manifest", e);
throw new TransfuseAnalysisException("URISyntaxException while trying to load manifest", e);
} catch (IOException e) {
log.error("IOException while trying to load manifest", e);
throw new TransfuseAnalysisException("IOException while trying to load manifest", e);
}
return androidManifestFile;
}
/**
* 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.
*/
private File findManifestFileThrowing() throws IOException, URISyntaxException {
JavaFileObject dummySourceFile = filer.createSourceFile("dummy" + System.currentTimeMillis());
String dummySourceFilePath = dummySourceFile.toUri().toString();
if (dummySourceFilePath.startsWith("file:")) {
if (!dummySourceFilePath.startsWith("file://")) {
dummySourceFilePath = "file://" + dummySourceFilePath.substring("file:".length());
}
} else {
dummySourceFilePath = "file://" + dummySourceFilePath;
}
log.debug("Dummy source file: " + dummySourceFilePath);
URI cleanURI = new URI(dummySourceFilePath);
File dummyFile = new File(cleanURI);
File sourcesGenerationFolder = dummyFile.getParentFile();
File projectRoot = sourcesGenerationFolder.getParentFile();
File androidManifestFile = new File (projectRoot, "AndroidManifest.xml");
for (int i = 0; i < MAX_PARENTS_FROM_SOURCE_FOLDER; i++) {
if (androidManifestFile.exists()) {
break;
} else {
if (projectRoot.getParentFile() != null) {
projectRoot = projectRoot.getParentFile();
androidManifestFile = new File(projectRoot, "AndroidManifest.xml");
} else {
break;
}
}
}
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 + ")");
} else {
log.debug("AndroidManifest.xml file found: " + androidManifestFile.toString());
}
return androidManifestFile;
}
}