All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.scalecube.config.source.ClassPathConfigSource Maven / Gradle / Ivy
package io.scalecube.config.source;
import io.scalecube.config.ConfigProperty;
import io.scalecube.config.utils.ThrowableUtil;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.function.Predicate;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
public final class ClassPathConfigSource extends FilteredPathConfigSource {
private static final String CLASSPATH = System.getProperty("java.class.path");
private static final String PATH_SEPARATOR = System.getProperty("path.separator");
private static final String CLASSPATH_ATTIBUTE_MANIFEST_SEPARATOR = " ";
private Map loadedConfig;
/**
* Constructor.
*
* @param predicate predicate to match configuration files
*/
public ClassPathConfigSource(Predicate predicate) {
this(Collections.singletonList(predicate));
}
/**
* Constructor.
*
* @param predicates list of predicates to match configuration files
*/
public ClassPathConfigSource(List> predicates) {
super(predicates);
}
/**
* Factory method to create {@code ClassPathConfigSource} instance using filename plus its
* prefixPatterns.
*
* @param filename filename for template of configuration property file
* @param prefixPattern pattern of prefix
* @return new {@code ClassPathConfigSource} instance
*/
public static ClassPathConfigSource createWithPattern(String filename, String prefixPattern) {
return createWithPattern(filename, Collections.singletonList(prefixPattern));
}
/**
* Factory method to create {@code ClassPathConfigSource} instance using filename plus its
* prefixPatterns.
*
* @param filename filename for template of configuration property file
* @param prefixPatterns list of prefixPatterns (comma separated list of strings)
* @return new {@code ClassPathConfigSource} instance
*/
public static ClassPathConfigSource createWithPattern(
String filename, List prefixPatterns) {
Objects.requireNonNull(filename, "ClassPathConfigSource: filename is required");
Objects.requireNonNull(prefixPatterns, "ClassPathConfigSource: prefixPatterns is required");
return new ClassPathConfigSource(preparePatternPredicates(filename, prefixPatterns));
}
@Override
public Map loadConfig() {
if (loadedConfig != null) {
return loadedConfig;
}
Collection pathCollection = new ArrayList<>();
getClassPathEntries(getClass().getClassLoader()).stream()
.filter(uri -> uri.getScheme().equals("file"))
.forEach(
uri -> {
File file = new File(uri);
if (!file.exists()) {
return;
}
try {
if (file.isDirectory()) {
Set currentPath =
new HashSet<>(Collections.singleton(file.getCanonicalFile()));
scanDirectory(file, "", currentPath, pathCollection);
} else {
scanJar(file, pathCollection);
}
} catch (Exception e) {
throw ThrowableUtil.propagate(e);
}
});
Map result = new TreeMap<>();
filterAndCollectInOrder(
predicates.iterator(),
loadConfigMap(pathCollection),
(path, map) ->
map.entrySet()
.forEach(
entry ->
result.putIfAbsent(
entry.getKey(),
LoadedConfigProperty.withNameAndValue(entry)
.origin(path.toString())
.build())));
return loadedConfig = result;
}
private static Collection getClassPathEntries(ClassLoader classloader) {
Collection entries = new LinkedHashSet<>();
ClassLoader parent = classloader.getParent();
if (parent != null) {
entries.addAll(getClassPathEntries(parent));
}
for (URL url : getClassLoaderUrls(classloader)) {
if (url.getProtocol().equals("file")) {
entries.add(toFile(url).toURI());
}
}
return new LinkedHashSet<>(entries);
}
private static File toFile(URL url) {
if (!url.getProtocol().equals("file")) {
throw new IllegalArgumentException("Unsupported protocol in url: " + url);
}
try {
return new File(url.toURI());
} catch (URISyntaxException e) {
return new File(url.getPath());
}
}
private static Collection getClassLoaderUrls(ClassLoader classloader) {
if (classloader instanceof URLClassLoader) {
return Arrays.stream(((URLClassLoader) classloader).getURLs()).collect(Collectors.toSet());
}
if (classloader.equals(ClassLoader.getSystemClassLoader())) {
return parseJavaClassPath();
}
return Collections.emptySet();
}
private static Collection parseJavaClassPath() {
Collection urls = new LinkedHashSet<>();
for (String entry : CLASSPATH.split(PATH_SEPARATOR)) {
try {
try {
urls.add(new File(entry).toURI().toURL());
} catch (SecurityException e) {
throw ThrowableUtil.propagate(e);
}
} catch (MalformedURLException ex) {
throw ThrowableUtil.propagate(ex);
}
}
return new LinkedHashSet<>(urls);
}
private static void scanDirectory(
File directory, String prefix, Set currentPath, Collection collector)
throws IOException {
File[] files = directory.listFiles();
if (files == null) {
return;
}
for (File f : files) {
String name = f.getName();
if (f.isDirectory()) {
File deref = f.getCanonicalFile();
if (currentPath.add(deref)) {
scanDirectory(deref, prefix + name + "/", currentPath, collector);
currentPath.remove(deref);
}
} else {
String resourceName = prefix + name;
if (!resourceName.equals(JarFile.MANIFEST_NAME)) {
collector.add(f.toPath());
}
}
}
}
private static void scanJar(File file, Collection collector) throws IOException {
try (JarFile jarFile = new JarFile(file)) {
for (File path : getClassPathFromManifest(file, jarFile.getManifest())) {
if (collector.add(path.getCanonicalFile().toPath())) {
scanFrom(path, collector);
}
}
scanJarFile(jarFile, file.toPath(), collector);
}
}
private static void scanJarFile(JarFile file, Path path, Collection collector)
throws IOException {
try (FileSystem zipfs = FileSystems.newFileSystem(path, (ClassLoader) null)) {
Enumeration entries = file.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (entry.isDirectory() || entry.getName().equals(JarFile.MANIFEST_NAME)) {
continue;
}
collector.add(zipfs.getPath(entry.getName()));
}
}
}
private static Set getClassPathFromManifest(File jarFile, Manifest manifest) {
Set result = new LinkedHashSet<>();
if (manifest == null) {
return result;
}
String classpathAttribute =
manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH.toString());
if (classpathAttribute == null) {
return result;
}
for (String path : classpathAttribute.split(CLASSPATH_ATTIBUTE_MANIFEST_SEPARATOR)) {
URL url;
try {
url = new URL(jarFile.toURI().toURL(), path);
} catch (MalformedURLException e) {
throw ThrowableUtil.propagate(e);
}
if (url.getProtocol().equals("file")) {
result.add(toFile(url));
}
}
return result;
}
private static void scanFrom(File file, Collection collector) throws IOException {
try {
if (!file.exists()) {
return;
}
} catch (SecurityException e) {
throw ThrowableUtil.propagate(e);
}
if (file.isDirectory()) {
Set currentPath = new HashSet<>(Collections.singleton(file.getCanonicalFile()));
scanDirectory(file, "", currentPath, collector);
} else {
scanJar(file, collector);
}
}
@Override
public String toString() {
return new StringJoiner(", ", ClassPathConfigSource.class.getSimpleName() + "[", "]")
.add("classLoader=" + getClass().getClassLoader())
.toString();
}
}