package org.bindgen.processor.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import javax.annotation.processing.ProcessingEnvironment;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import javax.tools.JavaFileManager.Location;
public class ConfUtil {
/** Attempts to load {@code fileName} and return its properties. */
public static Map<String, String> loadProperties(ProcessingEnvironment env, String fileName) {
Map<String, String> properties = new LinkedHashMap<String, String>();
// Eclipse, ant, and maven all act a little differently here, so try both source and class output
File file = null;
for (Location location : new Location[] { StandardLocation.SOURCE_OUTPUT, StandardLocation.CLASS_OUTPUT }) {
file = resolveBindgenPropertiesIfExists(location, env, fileName);
if (file != null) {
break;
}
}
if (file != null) {
Properties p = new Properties();
try {
p.load(new FileInputStream(file));
} catch (Exception e) {
e.printStackTrace();
}
for (Map.Entry<Object, Object> entry : p.entrySet()) {
properties.put((String) entry.getKey(), (String) entry.getValue());
}
}
return properties;
}
/** Finds a file by starting by <code>location</code> and walkig up.
*
* This uses a heuristic because in Eclipse we will not know what our
* working directory is (it is wherever Eclipse was started from), so
* project/workspace-relative paths will not work.
*
* As far as passing in a the properties location as a {@code -Afile=path}
* setting, Eclipse also lacks any {@code ${basepath}}-type interpolation
* in its APT key/value pairs (like Ant would be able to do). So only fixed
* values are accepted, meaning an absolute path, which would be too tied
* to any one developer's particular machine.
*
* The one thing the APT API gives us is the CLASS_OUTPUT (e.g. bin/apt).
* So we start there and walk up parent directories looking for
* {@code bindgen.properties} files.
*/
private static File resolveBindgenPropertiesIfExists(Location location, ProcessingEnvironment env, String fileName) {
// Find a dummy /bin/apt/dummy.txt path to start at
final String dummyPath;
try {
// We don't actually create this, we just want its URI
FileObject dummyFileObject = env.getFiler().getResource(location, "", "dummy.txt");
dummyPath = dummyFileObject.toUri().toString().replaceAll("file:", "");
} catch (IOException e1) {
return null;
}
// Walk up looking for a bindgen.properties
File current = new File(dummyPath).getParentFile();
while (current != null) {
File possible = new File(current, fileName);
if (possible.exists()) {
return possible;
}
current = current.getParentFile();
}
// Before giving up, try just grabbing it from the current directory
File possible = new File(fileName);
if (possible.exists()) {
return possible;
}
// No file found
return null;
}
}