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.
org.gradle.api.internal.file.copy.DefaultCopySpec Maven / Gradle / Ivy
/*
* Copyright 2010 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
*
* 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.gradle.api.internal.file.copy;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import groovy.lang.Closure;
import org.gradle.api.Action;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.NonExtensible;
import org.gradle.api.Transformer;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.ConfigurableFilePermissions;
import org.gradle.api.file.CopyProcessingSpec;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.DuplicatesStrategy;
import org.gradle.api.file.ExpandDetails;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileCopyDetails;
import org.gradle.api.file.FilePermissions;
import org.gradle.api.file.FileTree;
import org.gradle.api.file.FileTreeElement;
import org.gradle.api.file.RelativePath;
import org.gradle.api.internal.file.DefaultConfigurableFilePermissions;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.file.FileTreeInternal;
import org.gradle.api.internal.file.pattern.PatternMatcher;
import org.gradle.api.internal.file.pattern.PatternMatcherFactory;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.util.PatternFilterable;
import org.gradle.api.tasks.util.PatternSet;
import org.gradle.internal.Actions;
import org.gradle.internal.Cast;
import org.gradle.internal.Factory;
import org.gradle.internal.deprecation.DeprecationLogger;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.typeconversion.NotationParser;
import org.gradle.util.internal.ClosureBackedAction;
import org.gradle.util.internal.ConfigureUtil;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.io.File;
import java.io.FilterReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Pattern;
@NonExtensible
public class DefaultCopySpec implements CopySpecInternal {
private static final NotationParser PATH_NOTATION_PARSER = PathNotationConverter.parser();
protected final Factory patternSetFactory;
protected final FileCollectionFactory fileCollectionFactory;
protected final Instantiator instantiator;
private final ObjectFactory objectFactory;
private final ConfigurableFileCollection sourcePaths;
private final PatternSet patternSet;
private final List childSpecs = new LinkedList<>();
private final List childSpecsInAdditionOrder = new LinkedList<>();
private final List> copyActions = new LinkedList<>();
private final Property dirPermissions;
private final Property filePermissions;
private Object destDir;
private boolean hasCustomActions;
private Boolean caseSensitive;
private Boolean includeEmptyDirs;
private DuplicatesStrategy duplicatesStrategy = DuplicatesStrategy.INHERIT;
private String filteringCharset;
private final List listeners = new LinkedList<>();
private PatternFilterable preserve = new PatternSet();
@Inject
public DefaultCopySpec(FileCollectionFactory fileCollectionFactory, ObjectFactory objectFactory, Instantiator instantiator, Factory patternSetFactory) {
this(fileCollectionFactory, objectFactory, instantiator, patternSetFactory, patternSetFactory.create());
}
public DefaultCopySpec(FileCollectionFactory fileCollectionFactory, ObjectFactory objectFactory, Instantiator instantiator, Factory patternSetFactory, PatternSet patternSet) {
this.sourcePaths = fileCollectionFactory.configurableFiles();
this.fileCollectionFactory = fileCollectionFactory;
this.objectFactory = objectFactory;
this.instantiator = instantiator;
this.patternSetFactory = patternSetFactory;
this.patternSet = patternSet;
this.filePermissions = objectFactory.property(ConfigurableFilePermissions.class);
this.dirPermissions = objectFactory.property(ConfigurableFilePermissions.class);
}
public DefaultCopySpec(FileCollectionFactory fileCollectionFactory, ObjectFactory objectFactory, Instantiator instantiator, Factory patternSetFactory, @Nullable String destPath, FileCollection source, PatternSet patternSet, Collection extends Action super FileCopyDetails>> copyActions, Collection children) {
this(fileCollectionFactory, objectFactory, instantiator, patternSetFactory, patternSet);
sourcePaths.from(source);
destDir = destPath;
this.copyActions.addAll(copyActions);
for (CopySpecInternal child : children) {
addChildSpec(child);
}
}
@Override
public boolean hasCustomActions() {
if (hasCustomActions) {
return true;
}
for (CopySpecInternal childSpec : childSpecs) {
if (childSpec.hasCustomActions()) {
return true;
}
}
return false;
}
public List> getCopyActions() {
return copyActions;
}
@Override
public CopySpec with(CopySpec... copySpecs) {
for (CopySpec copySpec : copySpecs) {
CopySpecInternal copySpecInternal;
if (copySpec instanceof CopySpecSource) {
CopySpecSource copySpecSource = (CopySpecSource) copySpec;
copySpecInternal = copySpecSource.getRootSpec();
} else {
copySpecInternal = (CopySpecInternal) copySpec;
}
addChildSpec(copySpecInternal);
}
return this;
}
@Override
public CopySpec from(Object... sourcePaths) {
this.sourcePaths.from(sourcePaths);
return this;
}
@Override
public CopySpec from(Object sourcePath, Closure c) {
return from(sourcePath, new ClosureBackedAction<>(c));
}
@Override
public CopySpec from(Object sourcePath, Action super CopySpec> configureAction) {
Preconditions.checkNotNull(configureAction, "Gradle does not allow passing null for the configuration action for CopySpec.from().");
CopySpecInternal child = addChild();
child.from(sourcePath);
CopySpecWrapper wrapper = instantiator.newInstance(CopySpecWrapper.class, child);
configureAction.execute(wrapper);
return wrapper;
}
@Override
public CopySpecInternal addFirst() {
return addChildAtPosition(0);
}
protected CopySpecInternal addChildAtPosition(int position) {
DefaultCopySpec child = instantiator.newInstance(SingleParentCopySpec.class, fileCollectionFactory, objectFactory, instantiator, patternSetFactory, buildRootResolver());
addChildSpec(position, child);
return child;
}
@Override
public CopySpecInternal addChild() {
DefaultCopySpec child = new SingleParentCopySpec(fileCollectionFactory, objectFactory, instantiator, patternSetFactory, buildRootResolver());
addChildSpec(child);
return child;
}
@Override
public CopySpecInternal addChildBeforeSpec(CopySpecInternal childSpec) {
int position = childSpecs.indexOf(childSpec);
return position != -1 ? addChildAtPosition(position) : addChild();
}
protected void addChildSpec(CopySpecInternal childSpec) {
addChildSpec(childSpecs.size(), childSpec);
}
protected void addChildSpec(int index, CopySpecInternal childSpec) {
childSpecs.add(index, childSpec);
// We need a consistent index here
final int additionIndex = childSpecsInAdditionOrder.size();
childSpecsInAdditionOrder.add(childSpec);
// In case more descendants are added to downward hierarchy, make sure they'll notify us
childSpec.addChildSpecListener((path, spec) -> {
CopySpecAddress childPath = new DefaultCopySpecAddress(null, DefaultCopySpec.this, additionIndex).append(path);
fireChildSpecListeners(childPath, spec);
});
// Notify upwards of currently existing descendant spec hierarchy
childSpec.visit(new DefaultCopySpecAddress(null, this, additionIndex), this::fireChildSpecListeners);
}
private void fireChildSpecListeners(CopySpecAddress path, CopySpecInternal spec) {
for (CopySpecListener listener : listeners) {
listener.childSpecAdded(path, spec);
}
}
@Override
public void visit(CopySpecAddress parentPath, CopySpecVisitor visitor) {
visitor.visit(parentPath, this);
int childIndex = 0;
for (CopySpecInternal childSpec : childSpecsInAdditionOrder) {
CopySpecAddress childPath = parentPath.append(this, childIndex);
childSpec.visit(childPath, visitor);
childIndex++;
}
}
@Override
public void addChildSpecListener(CopySpecListener copySpecListener) {
this.listeners.add(copySpecListener);
}
@VisibleForTesting
public Set getSourcePaths() {
return sourcePaths.getFrom();
}
@Nullable
public String getDestPath() {
return destDir == null ? null : PATH_NOTATION_PARSER.parseNotation(destDir);
}
@Override
@Nullable
public File getDestinationDir() {
if (destDir instanceof File) {
return (File) destDir;
} else {
return destDir == null ? null : new File(PATH_NOTATION_PARSER.parseNotation(destDir));
}
}
@Override
public CopySpec into(Object destDir) {
this.destDir = destDir;
return this;
}
@Override
public CopySpec into(Object destPath, Closure configureClosure) {
return into(destPath, new ClosureBackedAction<>(configureClosure));
}
@Override
public CopySpec into(Object destPath, Action super CopySpec> copySpec) {
Preconditions.checkNotNull(copySpec, "Gradle does not allow passing null for the configuration action for CopySpec.into().");
CopySpecInternal child = addChild();
child.into(destPath);
CopySpecWrapper wrapper = instantiator.newInstance(CopySpecWrapper.class, child);
copySpec.execute(wrapper);
return wrapper;
}
@Override
public boolean isCaseSensitive() {
return buildRootResolver().isCaseSensitive();
}
@Override
public void setCaseSensitive(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}
@Override
public boolean getIncludeEmptyDirs() {
return buildRootResolver().getIncludeEmptyDirs();
}
@Override
public void setIncludeEmptyDirs(boolean includeEmptyDirs) {
this.includeEmptyDirs = includeEmptyDirs;
}
public DuplicatesStrategy getDuplicatesStrategyForThisSpec() {
return duplicatesStrategy;
}
@Override
public DuplicatesStrategy getDuplicatesStrategy() {
return buildRootResolver().getDuplicatesStrategy();
}
@Override
public void setDuplicatesStrategy(DuplicatesStrategy strategy) {
this.duplicatesStrategy = strategy;
}
@Override
public CopySpec filesMatching(String pattern, Action super FileCopyDetails> action) {
PatternMatcher matcher = PatternMatcherFactory.getPatternMatcher(true, isCaseSensitive(), pattern);
return eachFile(new MatchingCopyAction(matcher, action));
}
@Override
public CopySpec filesMatching(Iterable patterns, Action super FileCopyDetails> action) {
if (!patterns.iterator().hasNext()) {
throw new InvalidUserDataException("must provide at least one pattern to match");
}
PatternMatcher matcher = PatternMatcherFactory.getPatternsMatcher(true, isCaseSensitive(), patterns);
return eachFile(new MatchingCopyAction(matcher, action));
}
@Override
public CopySpec filesNotMatching(String pattern, Action super FileCopyDetails> action) {
PatternMatcher matcher = PatternMatcherFactory.getPatternMatcher(true, isCaseSensitive(), pattern);
return eachFile(new MatchingCopyAction(matcher.negate(), action));
}
@Override
public CopySpec filesNotMatching(Iterable patterns, Action super FileCopyDetails> action) {
if (!patterns.iterator().hasNext()) {
throw new InvalidUserDataException("must provide at least one pattern to not match");
}
PatternMatcher matcher = PatternMatcherFactory.getPatternsMatcher(true, isCaseSensitive(), patterns);
return eachFile(new MatchingCopyAction(matcher.negate(), action));
}
public PatternSet getPatterns() {
return patternSet;
}
@Override
public CopySpec include(String... includes) {
patternSet.include(includes);
return this;
}
@Override
public CopySpec include(Iterable includes) {
patternSet.include(includes);
return this;
}
@Override
public CopySpec include(Spec includeSpec) {
patternSet.include(includeSpec);
return this;
}
@Override
public CopySpec include(Closure includeSpec) {
patternSet.include(includeSpec);
return this;
}
@Override
public Set getIncludes() {
return patternSet.getIncludes();
}
@Override
public CopySpec setIncludes(Iterable includes) {
patternSet.setIncludes(includes);
return this;
}
@Override
public CopySpec exclude(String... excludes) {
patternSet.exclude(excludes);
return this;
}
@Override
public CopySpec exclude(Iterable excludes) {
patternSet.exclude(excludes);
return this;
}
@Override
public CopySpec exclude(Spec excludeSpec) {
patternSet.exclude(excludeSpec);
return this;
}
@Override
public CopySpec exclude(Closure excludeSpec) {
patternSet.exclude(excludeSpec);
return this;
}
@Override
public Set getExcludes() {
return patternSet.getExcludes();
}
@Override
public CopySpec setExcludes(Iterable excludes) {
patternSet.setExcludes(excludes);
return this;
}
@Override
public CopySpec rename(String sourceRegEx, String replaceWith) {
appendCopyAction(new RenamingCopyAction(new RegExpNameMapper(sourceRegEx, replaceWith)));
return this;
}
@Override
public CopySpec rename(Pattern sourceRegEx, String replaceWith) {
appendCopyAction(new RenamingCopyAction(new RegExpNameMapper(sourceRegEx, replaceWith)));
return this;
}
@Override
public CopySpec filter(final Class extends FilterReader> filterType) {
appendCopyAction(new TypeBackedFilterAction(filterType));
return this;
}
@Override
public CopySpec filter(final Closure closure) {
return filter(new ClosureBackedTransformer(closure));
}
@Override
public CopySpec filter(final Transformer transformer) {
appendCopyAction(new TransformerBackedFilterAction(transformer));
return this;
}
@Override
public CopySpec filter(final Map properties, final Class extends FilterReader> filterType) {
appendCopyAction(new MapTypeBackedFilterAction(properties, filterType));
return this;
}
@Override
public CopySpec expand(Map properties) {
appendCopyAction(new MapBackedExpandAction(properties, Actions.doNothing()));
return this;
}
@Override
public CopySpec expand(final Map properties, final Action super ExpandDetails> action) {
appendCopyAction(new MapBackedExpandAction(properties, action));
return this;
}
@Override
public CopySpec rename(Closure closure) {
return rename(new ClosureBackedTransformer(closure));
}
@Override
public CopySpec rename(Transformer renamer) {
appendCopyAction(new RenamingCopyAction(renamer));
return this;
}
@Override
@Deprecated
public Integer getDirMode() {
DeprecationLogger.deprecateMethod(CopyProcessingSpec.class, "getDirMode()")
.replaceWith("getDirPermissions()")
.willBeRemovedInGradle9()
.withUpgradeGuideSection(8, "unix_file_permissions_deprecated")
.nagUser();
return getMode(buildRootResolver().getDirPermissions());
}
@Override
@Deprecated
public Integer getFileMode() {
DeprecationLogger.deprecateMethod(CopyProcessingSpec.class, "getFileMode()")
.replaceWith("getFilePermissions()")
.willBeRemovedInGradle9()
.withUpgradeGuideSection(8, "unix_file_permissions_deprecated")
.nagUser();
return getMode(buildRootResolver().getFilePermissions());
}
@Nullable
private Integer getMode(Provider permissions) {
return permissions.map(FilePermissions::toUnixNumeric).getOrNull();
}
@Override
@Deprecated
public CopyProcessingSpec setDirMode(@Nullable Integer mode) {
DeprecationLogger.deprecateMethod(CopyProcessingSpec.class, "setDirMode(Integer)")
.replaceWith("dirPermissions(Action)")
.willBeRemovedInGradle9()
.withUpgradeGuideSection(8, "unix_file_permissions_deprecated")
.nagUser();
dirPermissions.set(mode == null ? null : objectFactory.newInstance(DefaultConfigurableFilePermissions.class, objectFactory, mode));
return this;
}
@Override
@Deprecated
public CopyProcessingSpec setFileMode(@Nullable Integer mode) {
DeprecationLogger.deprecateMethod(CopyProcessingSpec.class, "setFileMode(Integer)")
.replaceWith("filePermissions(Action)")
.willBeRemovedInGradle9()
.withUpgradeGuideSection(8, "unix_file_permissions_deprecated")
.nagUser();
filePermissions.set(mode == null ? null : objectFactory.newInstance(DefaultConfigurableFilePermissions.class, objectFactory, mode));
return this;
}
@Override
public Property getFilePermissions() {
return filePermissions;
}
@Override
public CopyProcessingSpec filePermissions(Action super ConfigurableFilePermissions> configureAction) {
DefaultConfigurableFilePermissions permissions = objectFactory.newInstance(DefaultConfigurableFilePermissions.class, objectFactory, DefaultConfigurableFilePermissions.getDefaultUnixNumeric(false));
configureAction.execute(permissions);
filePermissions.set(permissions);
return this;
}
@Override
public Property getDirPermissions() {
return dirPermissions;
}
@Override
public CopyProcessingSpec dirPermissions(Action super ConfigurableFilePermissions> configureAction) {
DefaultConfigurableFilePermissions permissions = objectFactory.newInstance(DefaultConfigurableFilePermissions.class, objectFactory, DefaultConfigurableFilePermissions.getDefaultUnixNumeric(true));
configureAction.execute(permissions);
dirPermissions.set(permissions);
return this;
}
@Override
public CopySpec eachFile(Action super FileCopyDetails> action) {
appendCopyAction(action);
return this;
}
private void appendCopyAction(Action super FileCopyDetails> action) {
hasCustomActions = true;
copyActions.add(action);
}
@Override
public void appendCachingSafeCopyAction(Action super FileCopyDetails> action) {
copyActions.add(action);
}
@Override
public PatternFilterable getPreserve() {
return preserve;
}
@Override
public CopySpecInternal preserve(Action super PatternFilterable> action) {
action.execute(this.preserve);
return this;
}
@Override
public CopySpec eachFile(Closure closure) {
appendCopyAction(ConfigureUtil.configureUsing(closure));
return this;
}
@Override
public Collection getChildren() {
return childSpecs;
}
@Override
public void walk(Action super CopySpecResolver> action) {
buildRootResolver().walk(action);
}
@Override
public CopySpecResolver buildResolverRelativeToParent(CopySpecResolver parent) {
return this.new DefaultCopySpecResolver(parent);
}
@Override
public CopySpecResolver buildRootResolver() {
return this.new DefaultCopySpecResolver(null);
}
public FileCollection getSourceRootsForThisSpec() {
return sourcePaths;
}
@Override
public String getFilteringCharset() {
return buildRootResolver().getFilteringCharset();
}
@Override
public void setFilteringCharset(String charset) {
Preconditions.checkNotNull(charset, "filteringCharset must not be null");
if (!Charset.isSupported(charset)) {
throw new InvalidUserDataException(String.format("filteringCharset %s is not supported by your JVM", charset));
}
this.filteringCharset = charset;
}
private static class MapBackedExpandAction implements Action {
private final Map properties;
private final Action super ExpandDetails> action;
public MapBackedExpandAction(Map properties, Action super ExpandDetails> action) {
this.properties = properties;
this.action = action;
}
@Override
public void execute(FileCopyDetails fileCopyDetails) {
fileCopyDetails.expand(properties, action);
}
}
private static class TypeBackedFilterAction implements Action {
private final Class extends FilterReader> filterType;
public TypeBackedFilterAction(Class extends FilterReader> filterType) {
this.filterType = filterType;
}
@Override
public void execute(FileCopyDetails fileCopyDetails) {
fileCopyDetails.filter(filterType);
}
}
private static class TransformerBackedFilterAction implements Action {
private final Transformer transformer;
public TransformerBackedFilterAction(Transformer transformer) {
this.transformer = transformer;
}
@Override
public void execute(FileCopyDetails fileCopyDetails) {
fileCopyDetails.filter(transformer);
}
}
private static class MapTypeBackedFilterAction implements Action {
private final Map properties;
private final Class extends FilterReader> filterType;
public MapTypeBackedFilterAction(Map properties, Class extends FilterReader> filterType) {
this.properties = properties;
this.filterType = filterType;
}
@Override
public void execute(FileCopyDetails fileCopyDetails) {
fileCopyDetails.filter(properties, filterType);
}
}
public class DefaultCopySpecResolver implements CopySpecResolver {
@Nullable
private final CopySpecResolver parentResolver;
private DefaultCopySpecResolver(@Nullable CopySpecResolver parent) {
this.parentResolver = parent;
}
@Override
public RelativePath getDestPath() {
RelativePath parentPath;
if (parentResolver == null) {
parentPath = new RelativePath(false);
} else {
parentPath = parentResolver.getDestPath();
}
String path = DefaultCopySpec.this.getDestPath();
if (path == null) {
return parentPath;
}
if (path.startsWith("/") || path.startsWith(File.separator)) {
return RelativePath.parse(false, path);
}
return RelativePath.parse(false, parentPath, path);
}
@Override
public FileTree getSource() {
return getSourceRootsForThisSpec().getAsFileTree().matching(this.getPatternSet());
}
@Override
public FileTree getAllSource() {
final ImmutableList.Builder builder = ImmutableList.builder();
walk(copySpecResolver -> builder.add(Cast.uncheckedCast(copySpecResolver.getSource())));
return fileCollectionFactory.treeOf(builder.build());
}
@Override
public Collection extends Action super FileCopyDetails>> getAllCopyActions() {
if (parentResolver == null) {
return copyActions;
}
List> allActions = new ArrayList<>();
allActions.addAll(parentResolver.getAllCopyActions());
allActions.addAll(copyActions);
return allActions;
}
@Override
public List getAllIncludes() {
List result = new ArrayList<>();
if (parentResolver != null) {
result.addAll(parentResolver.getAllIncludes());
}
result.addAll(patternSet.getIncludesView());
return result;
}
@Override
public List getAllExcludes() {
List result = new ArrayList<>();
if (parentResolver != null) {
result.addAll(parentResolver.getAllExcludes());
}
result.addAll(patternSet.getExcludesView());
return result;
}
@Override
public List> getAllExcludeSpecs() {
List> result = new ArrayList<>();
if (parentResolver != null) {
result.addAll(parentResolver.getAllExcludeSpecs());
}
result.addAll(patternSet.getExcludeSpecsView());
return result;
}
@Override
public DuplicatesStrategy getDuplicatesStrategy() {
if (duplicatesStrategy != DuplicatesStrategy.INHERIT) {
return duplicatesStrategy;
}
if (parentResolver != null) {
return parentResolver.getDuplicatesStrategy();
}
return DuplicatesStrategy.INCLUDE;
}
@Override
public boolean isDefaultDuplicateStrategy() {
if (duplicatesStrategy != DuplicatesStrategy.INHERIT) {
return false;
}
if (parentResolver != null) {
return parentResolver.isDefaultDuplicateStrategy();
}
return true;
}
@Override
public boolean isCaseSensitive() {
if (caseSensitive != null) {
return caseSensitive;
}
if (parentResolver != null) {
return parentResolver.isCaseSensitive();
}
return true;
}
@Override
@Deprecated
public Integer getFileMode() {
DeprecationLogger.deprecateMethod(CopySpecResolver.class, "getFileMode()")
.replaceWith("getImmutableFilePermissions()")
.willBeRemovedInGradle9()
.withUpgradeGuideSection(8, "unix_file_permissions_deprecated")
.nagUser();
return getMode(getImmutableFilePermissions());
}
@Override
@Deprecated
public Integer getDirMode() {
DeprecationLogger.deprecateMethod(CopySpecResolver.class, "getDirMode()")
.replaceWith("getImmutableDirPermissions()")
.willBeRemovedInGradle9()
.withUpgradeGuideSection(8, "unix_file_permissions_deprecated")
.nagUser();
return getMode(getImmutableDirPermissions());
}
@Nullable
private Integer getMode(Provider permissions) {
return permissions.map(FilePermissions::toUnixNumeric).getOrNull();
}
@Override
public Provider getFilePermissions() {
return filePermissions;
}
@Override
public Provider getImmutableFilePermissions() {
return getPermissions(filePermissions, CopySpecResolver::getImmutableFilePermissions);
}
@Override
public Provider getDirPermissions() {
return dirPermissions;
}
@Override
public Provider getImmutableDirPermissions() {
return getPermissions(dirPermissions, CopySpecResolver::getImmutableDirPermissions);
}
private Provider getPermissions(Property property, Function> parentMapper) {
if (property.isPresent() || parentResolver == null) {
property.finalizeValueOnRead();
return Cast.uncheckedCast(property);
}
return parentMapper.apply(parentResolver);
}
@Override
public boolean getIncludeEmptyDirs() {
if (includeEmptyDirs != null) {
return includeEmptyDirs;
}
if (parentResolver != null) {
return parentResolver.getIncludeEmptyDirs();
}
return true;
}
@Override
public List> getAllIncludeSpecs() {
List> result = new ArrayList<>();
if (parentResolver != null) {
result.addAll(parentResolver.getAllIncludeSpecs());
}
result.addAll(patternSet.getIncludeSpecsView());
return result;
}
public PatternSet getPatternSet() {
PatternSet patterns = patternSetFactory.create();
assert patterns != null;
patterns.setCaseSensitive(isCaseSensitive());
patterns.include(this.getAllIncludes());
patterns.includeSpecs(getAllIncludeSpecs());
patterns.exclude(this.getAllExcludes());
patterns.excludeSpecs(getAllExcludeSpecs());
return patterns;
}
@Override
public void walk(Action super CopySpecResolver> action) {
action.execute(this);
for (CopySpecInternal child : getChildren()) {
child.buildResolverRelativeToParent(this).walk(action);
}
}
@Override
public String getFilteringCharset() {
if (filteringCharset != null) {
return filteringCharset;
}
if (parentResolver != null) {
return parentResolver.getFilteringCharset();
}
return Charset.defaultCharset().name();
}
}
private static class DefaultCopySpecAddress implements CopySpecAddress {
private final DefaultCopySpecAddress parent;
private final CopySpecInternal spec;
private final int additionIndex;
public DefaultCopySpecAddress(@Nullable DefaultCopySpecAddress parent, CopySpecInternal spec, int additionIndex) {
this.parent = parent;
this.spec = spec;
this.additionIndex = additionIndex;
}
@Override
public CopySpecAddress getParent() {
return parent;
}
@Override
public CopySpecInternal getSpec() {
return spec;
}
@Override
public int getAdditionIndex() {
return additionIndex;
}
@Override
public DefaultCopySpecAddress append(CopySpecInternal spec, int additionIndex) {
return new DefaultCopySpecAddress(this, spec, additionIndex);
}
@Override
public DefaultCopySpecAddress append(CopySpecAddress relativeAddress) {
CopySpecAddress parent = relativeAddress.getParent();
DefaultCopySpecAddress newParent;
if (parent == null) {
newParent = this;
} else {
newParent = append(parent);
}
return new DefaultCopySpecAddress(newParent, relativeAddress.getSpec(), relativeAddress.getAdditionIndex());
}
@Override
public CopySpecResolver unroll(StringBuilder path) {
CopySpecResolver resolver;
if (parent != null) {
resolver = spec.buildResolverRelativeToParent(parent.unroll(path));
} else {
resolver = spec.buildRootResolver();
}
path.append("$").append(additionIndex + 1);
return resolver;
}
@Override
public String toString() {
String parentPath = parent == null
? ""
: parent.toString();
return parentPath + "$" + (additionIndex + 1);
}
}
}