All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.conqat.lib.commons.resources.ResourceUtils Maven / Gradle / Ivy

There is a newer version: 2024.7.2
Show newest version
/*
 * 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;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy