org.grails.cli.command.archive.ResourceMatcher Maven / Gradle / Ivy
/*
* Copyright 2012-2020 the original author or authors.
*
* 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
*
* https://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.grails.cli.command.archive;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
/**
* Used to match resources for inclusion in a CLI application's jar file.
*
* @author Andy Wilkinson
*/
class ResourceMatcher {
private static final String[] DEFAULT_INCLUDES = { "public/**", "resources/**", "static/**", "templates/**",
"META-INF/**", "*" };
private static final String[] DEFAULT_EXCLUDES = { ".*", "repository/**", "build/**", "target/**", "**/*.jar",
"**/*.groovy" };
private final AntPathMatcher pathMatcher = new AntPathMatcher();
private final List includes;
private final List excludes;
ResourceMatcher(List includes, List excludes) {
this.includes = getOptions(includes, DEFAULT_INCLUDES);
this.excludes = getOptions(excludes, DEFAULT_EXCLUDES);
}
List find(List roots) throws IOException {
List matchedResources = new ArrayList<>();
for (File root : roots) {
if (root.isFile()) {
matchedResources.add(new MatchedResource(root));
}
else {
matchedResources.addAll(findInDirectory(root));
}
}
return matchedResources;
}
private List findInDirectory(File directory) throws IOException {
List matchedResources = new ArrayList<>();
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(
new DirectoryResourceLoader(directory));
for (String include : this.includes) {
for (Resource candidate : resolver.getResources(include)) {
File file = candidate.getFile();
if (file.isFile()) {
MatchedResource matchedResource = new MatchedResource(directory, file);
if (!isExcluded(matchedResource)) {
matchedResources.add(matchedResource);
}
}
}
}
return matchedResources;
}
private boolean isExcluded(MatchedResource matchedResource) {
for (String exclude : this.excludes) {
if (this.pathMatcher.match(exclude, matchedResource.getName())) {
return true;
}
}
return false;
}
private List getOptions(List values, String[] defaults) {
Set result = new LinkedHashSet<>();
Set minus = new LinkedHashSet<>();
boolean deltasFound = false;
for (String value : values) {
if (value.startsWith("+")) {
deltasFound = true;
value = value.substring(1);
result.add(value);
}
else if (value.startsWith("-")) {
deltasFound = true;
value = value.substring(1);
minus.add(value);
}
else if (!value.trim().isEmpty()) {
result.add(value);
}
}
for (String value : defaults) {
if (!minus.contains(value) || !deltasFound) {
result.add(value);
}
}
return new ArrayList<>(result);
}
/**
* {@link ResourceLoader} to get load resource from a directory.
*/
private static class DirectoryResourceLoader extends DefaultResourceLoader {
private final File rootDirectory;
DirectoryResourceLoader(File root) throws MalformedURLException {
super(new DirectoryClassLoader(root));
this.rootDirectory = root;
}
@Override
protected Resource getResourceByPath(String path) {
return new FileSystemResource(new File(this.rootDirectory, path));
}
}
/**
* {@link ClassLoader} backed by a directory.
*/
private static class DirectoryClassLoader extends URLClassLoader {
DirectoryClassLoader(File rootDirectory) throws MalformedURLException {
super(new URL[] { rootDirectory.toURI().toURL() });
}
@Override
public Enumeration getResources(String name) throws IOException {
return findResources(name);
}
@Override
public URL getResource(String name) {
return findResource(name);
}
}
/**
* A single matched resource.
*/
public static final class MatchedResource {
private final File file;
private final String name;
private final boolean root;
private MatchedResource(File file) {
this.name = file.getName();
this.file = file;
this.root = this.name.endsWith(".jar");
}
private MatchedResource(File rootDirectory, File file) {
String filePath = file.getAbsolutePath();
String rootDirectoryPath = rootDirectory.getAbsolutePath();
this.name = StringUtils.cleanPath(filePath.substring(rootDirectoryPath.length() + 1));
this.file = file;
this.root = false;
}
private MatchedResource(File resourceFile, String path, boolean root) {
this.file = resourceFile;
this.name = path;
this.root = root;
}
public String getName() {
return this.name;
}
public File getFile() {
return this.file;
}
public boolean isRoot() {
return this.root;
}
@Override
public String toString() {
return this.file.getAbsolutePath();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy