org.conqat.lib.commons.resources.ResourceUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of teamscale-lib-commons Show documentation
Show all versions of teamscale-lib-commons Show documentation
Provides common utility functions
/*
* Copyright (c) CQSE GmbH
*
* 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.conqat.lib.commons.resources;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.conqat.lib.commons.collections.CollectionUtils;
import org.conqat.lib.commons.filesystem.ClassPathUtils;
import org.conqat.lib.commons.filesystem.FileSystemUtils;
import org.conqat.lib.commons.string.StringUtils;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
import nonapi.io.github.classgraph.scanspec.AcceptReject;
/**
* Helper class for listing resources in a given path.
*/
public class ResourceUtils {
/**
* List of allowed classpath prefixes for scanning. May be extended externally, if necessary.
*/
public static final Set ALLOWED_CLASSPATH_PREFIXES = CollectionUtils.asHashSet("org.conqat",
"com.teamscale", "eu.cqse");
/**
* Lists all resources in the given path (non-recursive). Only resources and no resource folders
* will be returned.
*
* @param path
* The path to list resources from. An empty string means the root of the contextClass'
* package.
*/
public static List listResources(Class contextClass, String path) {
return listResources(contextClass, path, false);
}
/**
* Lists all resources in the given path (recursively). Only resources and no resource folders will
* be returned.
*
* @param path
* The path to list resources from. An empty string means the root of the contextClass'
* package.
*/
public static List listResourcesRecursively(Class contextClass, String path) {
return listResources(contextClass, path, true);
}
/**
* Gets the path to resources of given context class (relative to src/main/resources folder).
*
* @param contextClass
* The class for which path to resources should be returned
*/
public static String getPackageResourcePath(Class contextClass) {
return contextClass.getPackage().getName().replace('.', FileSystemUtils.UNIX_SEPARATOR);
}
/**
* Lists resources in the given path and wraps them into {@link Resource} objects.
*/
private static List listResources(Class contextClass, String path, boolean recursive) {
return CollectionUtils.map(listResourceNames(contextClass, path, recursive),
resourcePath -> Resource.of(contextClass, resourcePath));
}
/**
* Lists the sub-paths contained in the given path relative to the contextClass.
*/
private static List listResourceNames(Class contextClass, String path, boolean recursive) {
String packageName = contextClass.getPackage().getName();
String contextPath = AcceptReject.packageNameToPath(packageName);
String fullPath = determineAbsoluteResourcePath(contextPath, path);
ClassGraph classGraph = new ClassGraph();
List classPathOverride = getFilteredClassPath(contextClass, packageName);
if (!classPathOverride.isEmpty()) {
classGraph = classGraph.overrideClasspath(classPathOverride);
}
if (recursive) {
classGraph = classGraph.acceptPaths(fullPath);
} else {
classGraph = classGraph.acceptPathsNonRecursive(fullPath);
}
Set resources = new HashSet<>();
try (ScanResult scanResult = classGraph.scan()) {
scanResult.getAllResources().nonClassFilesOnly().forEach(res -> {
String resourceFullPath = res.getPath();
if (path.startsWith("/")) {
resources.add('/' + resourceFullPath);
} else {
resources.add(StringUtils.stripPrefix(resourceFullPath, contextPath + '/'));
}
});
}
return new ArrayList<>(resources);
}
/** Return whether the provided class is part of the allowed prefixes. */
private static boolean isClassInAllowedPrefixes(Class contextClass) {
return ALLOWED_CLASSPATH_PREFIXES.contains(StringUtils.getFirstParts(contextClass.getName(), 2, '.'));
}
private static List getFilteredClassPath(Class contextClass, String packageName) {
List classpathEntries = ClassPathUtils.getClassPathEntries();
if (!isClassInAllowedPrefixes(contextClass)) {
String packagePrefix = StringUtils.getFirstParts(packageName, 3, '.');
return CollectionUtils.filter(classpathEntries, classpathEntry -> classpathEntry.contains(packagePrefix));
}
return CollectionUtils.filter(classpathEntries,
classpathEntry -> StringUtils.containsOneOf(classpathEntry, ALLOWED_CLASSPATH_PREFIXES));
}
private static String determineAbsoluteResourcePath(String contextPath, String path) {
String fullPath;
if (path.startsWith("/")) {
return path;
}
fullPath = contextPath;
if (!StringUtils.isEmpty(path)) {
fullPath += '/' + path;
}
return fullPath;
}
}