Основываясь на технической статье , написанной Грегом Бриггсом, я написал следующее решение:
/**
* Loads all properties files under the given path, assuming it's under the classpath.
*
* @param clazz Any class that lives in the same place as the resources you want.
* @param parentFolderPath The profiles folder path, relative to the classpath.
* Should end with "/", but not start with one.
* Example: "properties/profiles/
* @return A set of all PropertyFile that represents all the properties files under the given path
* @throws IOException
*/
public static Set<PropertyFile> getPropertiesFromPath(Class<?> clazz, String parentFolderPath) throws IOException {
if (!parentFolderPath.endsWith("/")) {
throw new InvalidPathException(parentFolderPath, "Path must end with '/'");
}
Set<PropertyFile> retVal = Sets.newHashSet();
URL dirURL = clazz.getClassLoader().getResource(parentFolderPath);
if (dirURL != null && dirURL.getProtocol().equals("file")) { //IDE CASE
Resource profilesFolderResource = new ClassPathResource(parentFolderPath);
File profilesFolder = profilesFolderResource.getFile();
for (File propertiesFile : profilesFolder.listFiles()) {
Properties props = new Properties();
try (InputStream is = FileUtils.openInputStream(propertiesFile)) {
props.load(is);
PropertyFile propertyFile = new PropertyFile(propertiesFile.getName(), propertiesFile.getAbsolutePath(), props);
retVal.add(propertyFile);
}
}
return retVal;
} else if (dirURL.getProtocol().equals("jar")) { // A JAR PATH
String jarPath = getJarPathFromURL(dirURL); //strip out only the JAR file
JarFile jar = new JarFile(URLDecoder.decode(jarPath, Charsets.UTF_8.name()));
Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while (entries.hasMoreElements()) {
JarEntry jEntry = entries.nextElement();
String name = jEntry.getName();
if (isProfileFile(jEntry, parentFolderPath)) { //filter according to the path
Path pathOfFile = Paths.get(name);
String fileName = pathOfFile.toString().substring(pathOfFile.toString().lastIndexOf(File.separator) + 1);
Properties props = new Properties();
try (InputStream stream = jar.getInputStream(jEntry)) {
props.load(stream);
PropertyFile propertyFile = new PropertyFile(fileName, pathOfFile.toString(), props);
retVal.add(propertyFile);
}
}
}
return retVal;
}
throw new UnsupportedOperationException("Cannot list files for URL " + dirURL);
}
/**
* @param jarEntry
* @param parentFolderPath
* @return true if the file represented by the JarEntry
* is a properties file under the given parentFolderPath folder, else false
*/
private static boolean isProfileFile(JarEntry jarEntry, String parentFolderPath) {
boolean result = false;
String name = jarEntry.getName();
if (name.endsWith(PROPERTIES_SUFFIX)) {
Path pathOfFile = Paths.get(name);
Path pathOfParent = Paths.get(parentFolderPath);
String folderPath = pathOfFile.toString().substring(0, pathOfFile.toString().lastIndexOf(File.separator));
if (folderPath.endsWith(pathOfParent.toString())) {
result = true;
}
}
return result;
}
private static String getJarPathFromURL(URL dirURL) {
String jarPath;
int start = OSUtil.isWindows() ? dirURL.getPath().lastIndexOf(":") - 1 : dirURL.getPath().lastIndexOf(":") + 1;
//strip out only the JAR file
jarPath = dirURL.getPath().substring(start, dirURL.getPath().lastIndexOf("!"));
return jarPath;
}
public static class PropertyFile {
public String fileName;
public String filePath;
public Properties properties;
public PropertyFile(String fileName, String filePath, Properties properties) {
this.fileName = fileName;
this.filePath = filePath;
this.properties = properties;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PropertyFile)) return false;
PropertyFile that = (PropertyFile) o;
return Objects.equals(filePath, that.filePath);
}
@Override
public int hashCode() {
return Objects.hash(filePath);
}
@Override
public String toString() {
return "PropertyFile{" +
"fileName='" + fileName + '\'' +
", filePath='" + filePath + '\'' +
", properties=" + properties +
'}';
}
}