Refine layer customization for Maven and Gradle
Simplify layer customization logic for both Maven and Gradle and refactor some internals of the Gradle plugin. Both Maven and Gradle now use a simpler customization format that consists of `application`, `dependencies` and `layer order` sections. The `application`, `dependencies` configurations support one or more `into` blocks that are used to select content for a specific layer. Closes gh-20526pull/20830/head
parent
14718f3e8a
commit
7bc7d86ad4
@ -1,237 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.tasks.Input;
|
||||
|
||||
import org.springframework.boot.loader.tools.layer.application.FilteredResourceStrategy;
|
||||
import org.springframework.boot.loader.tools.layer.application.LocationFilter;
|
||||
import org.springframework.boot.loader.tools.layer.application.ResourceFilter;
|
||||
import org.springframework.boot.loader.tools.layer.application.ResourceStrategy;
|
||||
import org.springframework.boot.loader.tools.layer.library.CoordinateFilter;
|
||||
import org.springframework.boot.loader.tools.layer.library.FilteredLibraryStrategy;
|
||||
import org.springframework.boot.loader.tools.layer.library.LibraryFilter;
|
||||
import org.springframework.boot.loader.tools.layer.library.LibraryStrategy;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Encapsulates the configuration for a layered jar.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class LayerConfiguration {
|
||||
|
||||
private boolean includeLayerTools = true;
|
||||
|
||||
private List<String> layersOrder = new ArrayList<>();
|
||||
|
||||
private List<ResourceStrategy> resourceStrategies = new ArrayList<>();
|
||||
|
||||
private List<LibraryStrategy> libraryStrategies = new ArrayList<>();
|
||||
|
||||
private StrategySpec strategySpec;
|
||||
|
||||
/**
|
||||
* Whether to include the layer tools jar.
|
||||
* @return true if layer tools is included
|
||||
*/
|
||||
@Input
|
||||
public boolean isIncludeLayerTools() {
|
||||
return this.includeLayerTools;
|
||||
}
|
||||
|
||||
public void setIncludeLayerTools(boolean includeLayerTools) {
|
||||
this.includeLayerTools = includeLayerTools;
|
||||
}
|
||||
|
||||
@Input
|
||||
public List<String> getLayersOrder() {
|
||||
return this.layersOrder;
|
||||
}
|
||||
|
||||
public void layersOrder(String... layers) {
|
||||
this.layersOrder = Arrays.asList(layers);
|
||||
}
|
||||
|
||||
public void layersOrder(List<String> layers) {
|
||||
this.layersOrder = layers;
|
||||
}
|
||||
|
||||
@Input
|
||||
public List<ResourceStrategy> getApplication() {
|
||||
return this.resourceStrategies;
|
||||
}
|
||||
|
||||
public void application(ResourceStrategy... resourceStrategies) {
|
||||
assertLayersOrderConfigured();
|
||||
this.resourceStrategies = Arrays.asList(resourceStrategies);
|
||||
}
|
||||
|
||||
public void application(Action<LayerConfiguration> config) {
|
||||
assertLayersOrderConfigured();
|
||||
this.strategySpec = StrategySpec.forResources();
|
||||
config.execute(this);
|
||||
}
|
||||
|
||||
@Input
|
||||
public List<LibraryStrategy> getLibraries() {
|
||||
return this.libraryStrategies;
|
||||
}
|
||||
|
||||
public void libraries(LibraryStrategy... strategies) {
|
||||
assertLayersOrderConfigured();
|
||||
this.libraryStrategies = Arrays.asList(strategies);
|
||||
}
|
||||
|
||||
public void libraries(Action<LayerConfiguration> configure) {
|
||||
assertLayersOrderConfigured();
|
||||
this.strategySpec = StrategySpec.forLibraries();
|
||||
configure.execute(this);
|
||||
}
|
||||
|
||||
private void assertLayersOrderConfigured() {
|
||||
Assert.state(!this.layersOrder.isEmpty(), "'layersOrder' must be configured before filters can be applied.");
|
||||
}
|
||||
|
||||
public void layerContent(String layerName, Action<LayerConfiguration> config) {
|
||||
this.strategySpec.newStrategy();
|
||||
config.execute(this);
|
||||
if (this.strategySpec.isLibrariesStrategy()) {
|
||||
this.libraryStrategies.add(new FilteredLibraryStrategy(layerName, this.strategySpec.libraryFilters()));
|
||||
}
|
||||
else {
|
||||
this.resourceStrategies.add(new FilteredResourceStrategy(layerName, this.strategySpec.resourceFilters()));
|
||||
}
|
||||
}
|
||||
|
||||
public void coordinates(Action<LayerConfiguration> config) {
|
||||
Assert.state(this.strategySpec.isLibrariesStrategy(),
|
||||
"The 'coordinates' filter must be used only with libraries");
|
||||
this.strategySpec.newFilter();
|
||||
config.execute(this);
|
||||
this.strategySpec
|
||||
.addLibraryFilter(new CoordinateFilter(this.strategySpec.includes(), this.strategySpec.excludes()));
|
||||
}
|
||||
|
||||
public void locations(Action<LayerConfiguration> config) {
|
||||
Assert.state(this.strategySpec.isResourcesStrategy(),
|
||||
"The 'locations' filter must be used only with application");
|
||||
this.strategySpec.newFilter();
|
||||
config.execute(this);
|
||||
this.strategySpec
|
||||
.addResourceFilter(new LocationFilter(this.strategySpec.includes(), this.strategySpec.excludes()));
|
||||
}
|
||||
|
||||
public void include(String... includes) {
|
||||
this.strategySpec.include(includes);
|
||||
}
|
||||
|
||||
public void exclude(String... excludes) {
|
||||
this.strategySpec.exclude(excludes);
|
||||
}
|
||||
|
||||
private static final class StrategySpec {
|
||||
|
||||
private final TYPE type;
|
||||
|
||||
private List<LibraryFilter> libraryFilters;
|
||||
|
||||
private List<ResourceFilter> resourceFilters;
|
||||
|
||||
private List<String> filterIncludes;
|
||||
|
||||
private List<String> filterExcludes;
|
||||
|
||||
private StrategySpec(TYPE type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
private boolean isLibrariesStrategy() {
|
||||
return this.type == TYPE.LIBRARIES;
|
||||
}
|
||||
|
||||
private boolean isResourcesStrategy() {
|
||||
return this.type == TYPE.RESOURCES;
|
||||
}
|
||||
|
||||
private void newStrategy() {
|
||||
this.libraryFilters = new ArrayList<>();
|
||||
this.resourceFilters = new ArrayList<>();
|
||||
newFilter();
|
||||
}
|
||||
|
||||
private void newFilter() {
|
||||
this.filterIncludes = new ArrayList<>();
|
||||
this.filterExcludes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private List<LibraryFilter> libraryFilters() {
|
||||
return this.libraryFilters;
|
||||
}
|
||||
|
||||
private void addLibraryFilter(LibraryFilter filter) {
|
||||
this.libraryFilters.add(filter);
|
||||
}
|
||||
|
||||
private List<ResourceFilter> resourceFilters() {
|
||||
return this.resourceFilters;
|
||||
}
|
||||
|
||||
private void addResourceFilter(ResourceFilter filter) {
|
||||
this.resourceFilters.add(filter);
|
||||
}
|
||||
|
||||
private List<String> includes() {
|
||||
return this.filterIncludes;
|
||||
}
|
||||
|
||||
private void include(String... includes) {
|
||||
this.filterIncludes.addAll(Arrays.asList(includes));
|
||||
}
|
||||
|
||||
private void exclude(String... excludes) {
|
||||
this.filterIncludes.addAll(Arrays.asList(excludes));
|
||||
}
|
||||
|
||||
private List<String> excludes() {
|
||||
return this.filterExcludes;
|
||||
}
|
||||
|
||||
private static StrategySpec forLibraries() {
|
||||
return new StrategySpec(TYPE.LIBRARIES);
|
||||
}
|
||||
|
||||
private static StrategySpec forResources() {
|
||||
return new StrategySpec(TYPE.RESOURCES);
|
||||
}
|
||||
|
||||
private enum TYPE {
|
||||
|
||||
LIBRARIES, RESOURCES;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.gradle.api.artifacts.ArtifactCollection;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.component.ComponentIdentifier;
|
||||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
|
||||
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
|
||||
import org.gradle.api.file.FileCopyDetails;
|
||||
import org.gradle.api.specs.Spec;
|
||||
|
||||
import org.springframework.boot.loader.tools.JarModeLibrary;
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
import org.springframework.boot.loader.tools.Layers;
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||
|
||||
/**
|
||||
* Resolver backed by a {@link LayeredSpec} that provides the destination {@link Layer}
|
||||
* for each copied {@link FileCopyDetails}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
* @see BootZipCopyAction
|
||||
*/
|
||||
class LayerResolver {
|
||||
|
||||
private static final String BOOT_INF_FOLDER = "BOOT-INF/";
|
||||
|
||||
private final ResolvedDependencies resolvedDependencies;
|
||||
|
||||
private final LayeredSpec layeredConfiguration;
|
||||
|
||||
private final Spec<FileCopyDetails> librarySpec;
|
||||
|
||||
LayerResolver(Iterable<Configuration> configurations, LayeredSpec layeredConfiguration,
|
||||
Spec<FileCopyDetails> librarySpec) {
|
||||
this.resolvedDependencies = new ResolvedDependencies(configurations);
|
||||
this.layeredConfiguration = layeredConfiguration;
|
||||
this.librarySpec = librarySpec;
|
||||
}
|
||||
|
||||
String getPath(JarModeLibrary jarModeLibrary) {
|
||||
Layers layers = this.layeredConfiguration.asLayers();
|
||||
Layer layer = layers.getLayer(jarModeLibrary);
|
||||
if (layer != null) {
|
||||
return BOOT_INF_FOLDER + "layers/" + layer + "/lib/" + jarModeLibrary.getName();
|
||||
}
|
||||
return BOOT_INF_FOLDER + "lib/" + jarModeLibrary.getName();
|
||||
}
|
||||
|
||||
String getPath(FileCopyDetails details) {
|
||||
String path = details.getRelativePath().getPathString();
|
||||
Layer layer = getLayer(details);
|
||||
if (layer == null || !path.startsWith(BOOT_INF_FOLDER)) {
|
||||
return path;
|
||||
}
|
||||
path = path.substring(BOOT_INF_FOLDER.length());
|
||||
return BOOT_INF_FOLDER + "layers/" + layer + "/" + path;
|
||||
}
|
||||
|
||||
Layer getLayer(FileCopyDetails details) {
|
||||
Layers layers = this.layeredConfiguration.asLayers();
|
||||
try {
|
||||
if (this.librarySpec.isSatisfiedBy(details)) {
|
||||
return layers.getLayer(asLibrary(details));
|
||||
}
|
||||
return layers.getLayer(details.getSourcePath());
|
||||
}
|
||||
catch (UnsupportedOperationException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
List<String> getLayerNames() {
|
||||
return this.layeredConfiguration.asLayers().stream().map(Layer::toString).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Library asLibrary(FileCopyDetails details) {
|
||||
File file = details.getFile();
|
||||
LibraryCoordinates coordinates = this.resolvedDependencies.find(file);
|
||||
return new Library(null, file, null, coordinates, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks and provides details of resolved dependencies in the project so we can find
|
||||
* {@link LibraryCoordinates}.
|
||||
*/
|
||||
private static class ResolvedDependencies {
|
||||
|
||||
private final Map<Configuration, ResolvedConfigurationDependencies> configurationDependencies = new LinkedHashMap<>();
|
||||
|
||||
ResolvedDependencies(Iterable<Configuration> configurations) {
|
||||
configurations.forEach(this::processConfiguration);
|
||||
}
|
||||
|
||||
private void processConfiguration(Configuration configuration) {
|
||||
if (configuration.isCanBeResolved()) {
|
||||
this.configurationDependencies.put(configuration,
|
||||
new ResolvedConfigurationDependencies(configuration.getIncoming().getArtifacts()));
|
||||
}
|
||||
}
|
||||
|
||||
LibraryCoordinates find(File file) {
|
||||
for (ResolvedConfigurationDependencies dependencies : this.configurationDependencies.values()) {
|
||||
LibraryCoordinates coordinates = dependencies.find(file);
|
||||
if (coordinates != null) {
|
||||
return coordinates;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores details of resolved configuration dependencies.
|
||||
*/
|
||||
private static class ResolvedConfigurationDependencies {
|
||||
|
||||
private final Map<File, LibraryCoordinates> artifactCoordinates = new LinkedHashMap<>();
|
||||
|
||||
ResolvedConfigurationDependencies(ArtifactCollection resolvedDependencies) {
|
||||
if (resolvedDependencies != null) {
|
||||
for (ResolvedArtifactResult resolvedArtifact : resolvedDependencies.getArtifacts()) {
|
||||
ComponentIdentifier identifier = resolvedArtifact.getId().getComponentIdentifier();
|
||||
if (identifier instanceof ModuleComponentIdentifier) {
|
||||
this.artifactCoordinates.put(resolvedArtifact.getFile(),
|
||||
new ModuleComponentIdentifierLibraryCoordinates(
|
||||
(ModuleComponentIdentifier) identifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LibraryCoordinates find(File file) {
|
||||
return this.artifactCoordinates.get(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts a {@link ModuleComponentIdentifier} to {@link LibraryCoordinates}.
|
||||
*/
|
||||
private static class ModuleComponentIdentifierLibraryCoordinates implements LibraryCoordinates {
|
||||
|
||||
private final ModuleComponentIdentifier identifier;
|
||||
|
||||
ModuleComponentIdentifierLibraryCoordinates(ModuleComponentIdentifier identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupId() {
|
||||
return this.identifier.getGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArtifactId() {
|
||||
return this.identifier.getModule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return this.identifier.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.identifier.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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.springframework.boot.gradle.tasks.bundling;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import groovy.lang.Closure;
|
||||
import org.gradle.api.Action;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.util.ConfigureUtil;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
import org.springframework.boot.loader.tools.Layers;
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.layer.ApplicationContentFilter;
|
||||
import org.springframework.boot.loader.tools.layer.ContentFilter;
|
||||
import org.springframework.boot.loader.tools.layer.ContentSelector;
|
||||
import org.springframework.boot.loader.tools.layer.CustomLayers;
|
||||
import org.springframework.boot.loader.tools.layer.IncludeExcludeContentSelector;
|
||||
import org.springframework.boot.loader.tools.layer.LibraryContentFilter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Encapsulates the configuration for a layered jar.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class LayeredSpec {
|
||||
|
||||
private boolean includeLayerTools = true;
|
||||
|
||||
private ApplicationSpec application = new ApplicationSpec();
|
||||
|
||||
private DependenciesSpec dependencies = new DependenciesSpec();
|
||||
|
||||
@Optional
|
||||
private List<String> layerOrder;
|
||||
|
||||
private Layers layers;
|
||||
|
||||
@Input
|
||||
public boolean isIncludeLayerTools() {
|
||||
return this.includeLayerTools;
|
||||
}
|
||||
|
||||
public void setIncludeLayerTools(boolean includeLayerTools) {
|
||||
this.includeLayerTools = includeLayerTools;
|
||||
}
|
||||
|
||||
@Input
|
||||
public ApplicationSpec getApplication() {
|
||||
return this.application;
|
||||
}
|
||||
|
||||
public void application(ApplicationSpec spec) {
|
||||
this.application = spec;
|
||||
}
|
||||
|
||||
public void application(Closure<?> closure) {
|
||||
application(ConfigureUtil.configureUsing(closure));
|
||||
}
|
||||
|
||||
public void application(Action<ApplicationSpec> action) {
|
||||
action.execute(this.application);
|
||||
}
|
||||
|
||||
@Input
|
||||
public DependenciesSpec getDependencies() {
|
||||
return this.dependencies;
|
||||
}
|
||||
|
||||
public void dependencies(DependenciesSpec spec) {
|
||||
this.dependencies = spec;
|
||||
}
|
||||
|
||||
public void dependencies(Closure<?> closure) {
|
||||
dependencies(ConfigureUtil.configureUsing(closure));
|
||||
}
|
||||
|
||||
public void dependencies(Action<DependenciesSpec> action) {
|
||||
action.execute(this.dependencies);
|
||||
}
|
||||
|
||||
@Input
|
||||
public List<String> getLayerOrder() {
|
||||
return this.layerOrder;
|
||||
}
|
||||
|
||||
public void layerOrder(String... layerOrder) {
|
||||
this.layerOrder = Arrays.asList(layerOrder);
|
||||
}
|
||||
|
||||
public void layerOrder(List<String> layerOrder) {
|
||||
this.layerOrder = layerOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this configuration as a {@link Layers} instance. This method should only be
|
||||
* called when the configuration is complete and will no longer be changed.
|
||||
* @return the layers
|
||||
*/
|
||||
Layers asLayers() {
|
||||
Layers layers = this.layers;
|
||||
if (layers == null) {
|
||||
layers = createLayers();
|
||||
this.layers = layers;
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
private Layers createLayers() {
|
||||
if (this.layerOrder == null || this.layerOrder.isEmpty()) {
|
||||
Assert.state(this.application.isEmpty() && this.dependencies.isEmpty(),
|
||||
"The 'layerOrder' must be defined when using custom layering");
|
||||
return Layers.IMPLICIT;
|
||||
}
|
||||
List<Layer> layers = this.layerOrder.stream().map(Layer::new).collect(Collectors.toList());
|
||||
return new CustomLayers(layers, this.application.asSelectors(), this.dependencies.asSelectors());
|
||||
}
|
||||
|
||||
public abstract static class IntoLayersSpec implements Serializable {
|
||||
|
||||
private final List<IntoLayerSpec> intoLayers;
|
||||
|
||||
boolean isEmpty() {
|
||||
return this.intoLayers.isEmpty();
|
||||
}
|
||||
|
||||
IntoLayersSpec(IntoLayerSpec... spec) {
|
||||
this.intoLayers = new ArrayList<>(Arrays.asList(spec));
|
||||
}
|
||||
|
||||
public void intoLayer(String layer) {
|
||||
this.intoLayers.add(new IntoLayerSpec(layer));
|
||||
}
|
||||
|
||||
public void intoLayer(String layer, Closure<?> closure) {
|
||||
intoLayer(layer, ConfigureUtil.configureUsing(closure));
|
||||
}
|
||||
|
||||
public void intoLayer(String layer, Action<IntoLayerSpec> action) {
|
||||
IntoLayerSpec spec = new IntoLayerSpec(layer);
|
||||
action.execute(spec);
|
||||
this.intoLayers.add(spec);
|
||||
}
|
||||
|
||||
<T> List<ContentSelector<T>> asSelectors(Function<String, ContentFilter<T>> filterFactory) {
|
||||
return this.intoLayers.stream().map((content) -> content.asSelector(filterFactory))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class IntoLayerSpec implements Serializable {
|
||||
|
||||
private final String intoLayer;
|
||||
|
||||
private final List<String> includes = new ArrayList<>();
|
||||
|
||||
private final List<String> excludes = new ArrayList<>();
|
||||
|
||||
public IntoLayerSpec(String intoLayer) {
|
||||
this.intoLayer = intoLayer;
|
||||
}
|
||||
|
||||
public void include(String... patterns) {
|
||||
this.includes.addAll(Arrays.asList(patterns));
|
||||
}
|
||||
|
||||
public void exclude(String... patterns) {
|
||||
this.includes.addAll(Arrays.asList(patterns));
|
||||
}
|
||||
|
||||
<T> ContentSelector<T> asSelector(Function<String, ContentFilter<T>> filterFactory) {
|
||||
Layer layer = new Layer(this.intoLayer);
|
||||
return new IncludeExcludeContentSelector<>(layer, this.includes, this.excludes, filterFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ApplicationSpec extends IntoLayersSpec {
|
||||
|
||||
public ApplicationSpec(IntoLayerSpec... contents) {
|
||||
super(contents);
|
||||
}
|
||||
|
||||
List<ContentSelector<String>> asSelectors() {
|
||||
return asSelectors(ApplicationContentFilter::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class DependenciesSpec extends IntoLayersSpec {
|
||||
|
||||
public DependenciesSpec(IntoLayerSpec... contents) {
|
||||
super(contents);
|
||||
}
|
||||
|
||||
List<ContentSelector<Library>> asSelectors() {
|
||||
return asSelectors(LibraryContentFilter::new);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools;
|
||||
|
||||
/**
|
||||
* Encapsulates information about the artifact coordinates of a library.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class DefaultLibraryCoordinates implements LibraryCoordinates {
|
||||
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
|
||||
private final String version;
|
||||
|
||||
/**
|
||||
* Create a new instance from discrete elements.
|
||||
* @param groupId the group ID
|
||||
* @param artifactId the artifact ID
|
||||
* @param version the version
|
||||
*/
|
||||
DefaultLibraryCoordinates(String groupId, String artifactId, String version) {
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the group ID of the coordinates.
|
||||
* @return the group ID
|
||||
*/
|
||||
@Override
|
||||
public String getGroupId() {
|
||||
return this.groupId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the artifact ID of the coordinates.
|
||||
* @return the artifact ID
|
||||
*/
|
||||
@Override
|
||||
public String getArtifactId() {
|
||||
return this.artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version of the coordinates.
|
||||
* @return the version
|
||||
*/
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the coordinates in the form {@code groupId:artifactId:version}.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return LibraryCoordinates.toStandardNotationString(this);
|
||||
}
|
||||
|
||||
}
|
22
spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/layer/application/LocationFilter.java → spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/layer/ApplicationContentFilter.java
22
spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/layer/application/LocationFilter.java → spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/layer/ApplicationContentFilter.java
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ContentSelector} backed by {@code include}/{@code exclude} {@link ContentFilter
|
||||
* filters}.
|
||||
*
|
||||
* @param <T> the content type
|
||||
* @author Madhura Bhave
|
||||
* @author Phillip Webb
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class IncludeExcludeContentSelector<T> implements ContentSelector<T> {
|
||||
|
||||
private final Layer layer;
|
||||
|
||||
private final List<ContentFilter<T>> includes;
|
||||
|
||||
private final List<ContentFilter<T>> excludes;
|
||||
|
||||
public IncludeExcludeContentSelector(Layer layer, List<ContentFilter<T>> includes,
|
||||
List<ContentFilter<T>> excludes) {
|
||||
this(layer, includes, excludes, Function.identity());
|
||||
}
|
||||
|
||||
public <S> IncludeExcludeContentSelector(Layer layer, List<S> includes, List<S> excludes,
|
||||
Function<S, ContentFilter<T>> filterFactory) {
|
||||
Assert.notNull(layer, "Layer must not be null");
|
||||
Assert.notNull(filterFactory, "FilterFactory must not be null");
|
||||
this.layer = layer;
|
||||
this.includes = (includes != null) ? adapt(includes, filterFactory) : Collections.emptyList();
|
||||
this.excludes = (excludes != null) ? adapt(excludes, filterFactory) : Collections.emptyList();
|
||||
}
|
||||
|
||||
private <S> List<ContentFilter<T>> adapt(List<S> list, Function<S, ContentFilter<T>> mapper) {
|
||||
return list.stream().map(mapper).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layer getLayer() {
|
||||
return this.layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(T item) {
|
||||
return isIncluded(item) && !isExcluded(item);
|
||||
}
|
||||
|
||||
private boolean isIncluded(T item) {
|
||||
if (this.includes.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (ContentFilter<T> include : this.includes) {
|
||||
if (include.matches(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isExcluded(T item) {
|
||||
if (this.excludes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (ContentFilter<T> exclude : this.excludes) {
|
||||
if (exclude.matches(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ContentFilter} that matches {@link Library} items based on a coordinates
|
||||
* pattern.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class LibraryContentFilter implements ContentFilter<Library> {
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
public LibraryContentFilter(String coordinatesPattern) {
|
||||
Assert.hasText(coordinatesPattern, "CoordinatesPattern must not be empty");
|
||||
StringBuilder regex = new StringBuilder();
|
||||
for (int i = 0; i < coordinatesPattern.length(); i++) {
|
||||
char c = coordinatesPattern.charAt(i);
|
||||
if (c == '.') {
|
||||
regex.append("\\.");
|
||||
}
|
||||
else if (c == '*') {
|
||||
regex.append(".*");
|
||||
}
|
||||
else {
|
||||
regex.append(c);
|
||||
}
|
||||
}
|
||||
this.pattern = Pattern.compile(regex.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Library library) {
|
||||
return this.pattern.matcher(LibraryCoordinates.toStandardNotationString(library.getCoordinates())).matches();
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.application;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link ResourceFilter} implementations.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public abstract class AbstractResourceFilter implements ResourceFilter {
|
||||
|
||||
private final List<String> includes = new ArrayList<>();
|
||||
|
||||
private final List<String> excludes = new ArrayList<>();
|
||||
|
||||
public AbstractResourceFilter(List<String> includes, List<String> excludes) {
|
||||
this.includes.addAll(includes);
|
||||
this.excludes.addAll(excludes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResourceIncluded(String resourceName) {
|
||||
return isMatch(resourceName, this.includes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResourceExcluded(String resourceName) {
|
||||
return isMatch(resourceName, this.excludes);
|
||||
}
|
||||
|
||||
protected abstract boolean isMatch(String resourceName, List<String> toMatch);
|
||||
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.application;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link ResourceStrategy} with custom filters.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class FilteredResourceStrategy implements ResourceStrategy {
|
||||
|
||||
private final Layer layer;
|
||||
|
||||
private final List<ResourceFilter> filters = new ArrayList<>();
|
||||
|
||||
public FilteredResourceStrategy(String layer, List<ResourceFilter> filters) {
|
||||
Assert.notEmpty(filters, "Filters should not be empty for custom strategy.");
|
||||
this.layer = new Layer(layer);
|
||||
this.filters.addAll(filters);
|
||||
}
|
||||
|
||||
public Layer getLayer() {
|
||||
return this.layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layer getMatchingLayer(String resourceName) {
|
||||
boolean isIncluded = false;
|
||||
for (ResourceFilter filter : this.filters) {
|
||||
if (filter.isResourceExcluded(resourceName)) {
|
||||
return null;
|
||||
}
|
||||
if (!isIncluded && filter.isResourceIncluded(resourceName)) {
|
||||
isIncluded = true;
|
||||
}
|
||||
}
|
||||
return (isIncluded) ? this.layer : null;
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.application;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A filter that can tell if a resource has been included or excluded.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public interface ResourceFilter extends Serializable {
|
||||
|
||||
/**
|
||||
* Return true if the resource is included by the filter.
|
||||
* @param resourceName the resource name
|
||||
* @return true if the resource is included
|
||||
*/
|
||||
boolean isResourceIncluded(String resourceName);
|
||||
|
||||
/**
|
||||
* Return true if the resource is included by the filter.
|
||||
* @param resourceName the resource name
|
||||
* @return true if the resource is excluded
|
||||
*/
|
||||
boolean isResourceExcluded(String resourceName);
|
||||
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.application;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
|
||||
/**
|
||||
* A strategy used to match a resource to a layer.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public interface ResourceStrategy extends Serializable {
|
||||
|
||||
/**
|
||||
* Return a {@link Layer} for the given resource. If no matching layer is found,
|
||||
* {@code null} is returned.
|
||||
* @param resourceName the name of the resource
|
||||
* @return the matching layer or {@code null}
|
||||
*/
|
||||
Layer getMatchingLayer(String resourceName);
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.library;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||
|
||||
/**
|
||||
* An implementation of {@link LibraryFilter} based on the library's coordinates.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class CoordinateFilter implements LibraryFilter {
|
||||
|
||||
private static final String EMPTY_COORDINATES = "::";
|
||||
|
||||
private final List<Pattern> includes;
|
||||
|
||||
private final List<Pattern> excludes;
|
||||
|
||||
public CoordinateFilter(List<String> includes, List<String> excludes) {
|
||||
this.includes = includes.stream().map(this::asPattern).collect(Collectors.toList());
|
||||
this.excludes = excludes.stream().map(this::asPattern).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Pattern asPattern(String string) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < string.length(); i++) {
|
||||
char c = string.charAt(i);
|
||||
if (c == '.') {
|
||||
builder.append("\\.");
|
||||
}
|
||||
else if (c == '*') {
|
||||
builder.append(".*");
|
||||
}
|
||||
else {
|
||||
builder.append(c);
|
||||
}
|
||||
}
|
||||
return Pattern.compile(builder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLibraryIncluded(Library library) {
|
||||
return isMatch(library, this.includes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLibraryExcluded(Library library) {
|
||||
return isMatch(library, this.excludes);
|
||||
}
|
||||
|
||||
private boolean isMatch(Library library, List<Pattern> patterns) {
|
||||
LibraryCoordinates coordinates = library.getCoordinates();
|
||||
String input = (coordinates != null) ? coordinates.toString() : EMPTY_COORDINATES;
|
||||
for (Pattern pattern : patterns) {
|
||||
if (pattern.matcher(input).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.library;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link LibraryStrategy} with custom filters.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public class FilteredLibraryStrategy implements LibraryStrategy {
|
||||
|
||||
private final Layer layer;
|
||||
|
||||
private final List<LibraryFilter> filters = new ArrayList<>();
|
||||
|
||||
public FilteredLibraryStrategy(String layer, List<LibraryFilter> filters) {
|
||||
Assert.notEmpty(filters, "Filters should not be empty for custom strategy.");
|
||||
this.layer = new Layer(layer);
|
||||
this.filters.addAll(filters);
|
||||
}
|
||||
|
||||
public Layer getLayer() {
|
||||
return this.layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Layer getMatchingLayer(Library library) {
|
||||
boolean isIncluded = false;
|
||||
for (LibraryFilter filter : this.filters) {
|
||||
if (filter.isLibraryExcluded(library)) {
|
||||
return null;
|
||||
}
|
||||
if (!isIncluded && filter.isLibraryIncluded(library)) {
|
||||
isIncluded = true;
|
||||
}
|
||||
}
|
||||
return (isIncluded) ? this.layer : null;
|
||||
}
|
||||
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.library;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
|
||||
/**
|
||||
* A filter that can tell if a {@link Library} has been included or excluded.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @since 2.3.0
|
||||
*/
|
||||
public interface LibraryFilter extends Serializable {
|
||||
|
||||
/**
|
||||
* Return true if the {@link Library} is included by the filter.
|
||||
* @param library the library
|
||||
* @return true if the library is included
|
||||
*/
|
||||
boolean isLibraryIncluded(Library library);
|
||||
|
||||
/**
|
||||
* Return true if the {@link Library} is excluded by the filter.
|
||||
* @param library the library
|
||||
* @return true if the library is excluded
|
||||
*/
|
||||
boolean isLibraryExcluded(Library library);
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support for custom layers for everything in BOOT-INF/lib.
|
||||
*
|
||||
*/
|
||||
package org.springframework.boot.loader.tools.layer.library;
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link ApplicationContentFilter}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Stephane Nicoll
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ApplicationContentFilterTests {
|
||||
|
||||
@Test
|
||||
void createWhenPatternIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ApplicationContentFilter(null))
|
||||
.withMessage("Pattern must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenPatternIsEmptyThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new ApplicationContentFilter(""))
|
||||
.withMessage("Pattern must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenWildcardPatternMatchesReturnsTrue() {
|
||||
ApplicationContentFilter filter = new ApplicationContentFilter("META-INF/**");
|
||||
assertThat(filter.matches("META-INF/resources/application.yml")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenWildcardPatternDoesNotMatchReturnsFalse() {
|
||||
ApplicationContentFilter filter = new ApplicationContentFilter("META-INF/**");
|
||||
assertThat(filter.matches("src/main/resources/application.yml")).isFalse();
|
||||
}
|
||||
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||
import org.springframework.boot.loader.tools.layer.application.FilteredResourceStrategy;
|
||||
import org.springframework.boot.loader.tools.layer.application.LocationFilter;
|
||||
import org.springframework.boot.loader.tools.layer.library.CoordinateFilter;
|
||||
import org.springframework.boot.loader.tools.layer.library.FilteredLibraryStrategy;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link CustomLayers}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class CustomLayersTests {
|
||||
|
||||
@Test
|
||||
void customLayersAreAvailable() {
|
||||
Layer first = new Layer("first");
|
||||
Layer second = new Layer("second");
|
||||
CustomLayers customLayers = new CustomLayers(Arrays.asList(first, second), Collections.emptyList(),
|
||||
Collections.emptyList());
|
||||
List<Layer> actualLayers = new ArrayList<>();
|
||||
customLayers.iterator().forEachRemaining(actualLayers::add);
|
||||
assertThat(actualLayers).containsExactly(first, second);
|
||||
}
|
||||
|
||||
@Test
|
||||
void layerForResourceIsFound() {
|
||||
FilteredResourceStrategy resourceStrategy = new FilteredResourceStrategy("test", Collections
|
||||
.singletonList(new LocationFilter(Collections.singletonList("META-INF/**"), Collections.emptyList())));
|
||||
Layer targetLayer = new Layer("test");
|
||||
CustomLayers customLayers = new CustomLayers(Collections.singletonList(targetLayer),
|
||||
Collections.singletonList(resourceStrategy), Collections.emptyList());
|
||||
assertThat(customLayers.getLayer("META-INF/manifest.mf")).isNotNull().isEqualTo(targetLayer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void layerForResourceIsNotFound() {
|
||||
FilteredResourceStrategy resourceStrategy = new FilteredResourceStrategy("test", Collections
|
||||
.singletonList(new LocationFilter(Collections.singletonList("META-INF/**"), Collections.emptyList())));
|
||||
CustomLayers customLayers = new CustomLayers(Collections.singletonList(new Layer("test")),
|
||||
Collections.singletonList(resourceStrategy), Collections.emptyList());
|
||||
assertThatIllegalStateException().isThrownBy(() -> customLayers.getLayer("com/acme"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void layerForResourceIsNotInListedLayers() {
|
||||
FilteredResourceStrategy resourceStrategy = new FilteredResourceStrategy("test-not-listed", Collections
|
||||
.singletonList(new LocationFilter(Collections.singletonList("META-INF/**"), Collections.emptyList())));
|
||||
Layer targetLayer = new Layer("test");
|
||||
CustomLayers customLayers = new CustomLayers(Collections.singletonList(targetLayer),
|
||||
Collections.singletonList(resourceStrategy), Collections.emptyList());
|
||||
assertThatIllegalStateException().isThrownBy(() -> customLayers.getLayer("META-INF/manifest.mf"))
|
||||
.withMessageContaining("META-INF/manifest.mf").withMessageContaining("test-not-listed")
|
||||
.withMessageContaining("[test]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void layerForLibraryIsFound() {
|
||||
FilteredLibraryStrategy libraryStrategy = new FilteredLibraryStrategy("test", Collections
|
||||
.singletonList(new CoordinateFilter(Collections.singletonList("com.acme:*"), Collections.emptyList())));
|
||||
Layer targetLayer = new Layer("test");
|
||||
CustomLayers customLayers = new CustomLayers(Collections.singletonList(targetLayer), Collections.emptyList(),
|
||||
Collections.singletonList(libraryStrategy));
|
||||
assertThat(customLayers.getLayer(mockLibrary("com.acme:test"))).isNotNull().isEqualTo(targetLayer);
|
||||
}
|
||||
|
||||
@Test
|
||||
void layerForLibraryIsNotFound() {
|
||||
FilteredLibraryStrategy libraryStrategy = new FilteredLibraryStrategy("test", Collections
|
||||
.singletonList(new CoordinateFilter(Collections.singletonList("com.acme:*"), Collections.emptyList())));
|
||||
CustomLayers customLayers = new CustomLayers(Collections.singletonList(new Layer("test")),
|
||||
Collections.emptyList(), Collections.singletonList(libraryStrategy));
|
||||
assertThatIllegalStateException().isThrownBy(() -> customLayers.getLayer(mockLibrary("org.another:test")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void layerForLibraryIsNotInListedLayers() {
|
||||
FilteredLibraryStrategy libraryStrategy = new FilteredLibraryStrategy("test-not-listed", Collections
|
||||
.singletonList(new CoordinateFilter(Collections.singletonList("com.acme:*"), Collections.emptyList())));
|
||||
Layer targetLayer = new Layer("test");
|
||||
CustomLayers customLayers = new CustomLayers(Collections.singletonList(targetLayer), Collections.emptyList(),
|
||||
Collections.singletonList(libraryStrategy));
|
||||
assertThatIllegalStateException().isThrownBy(() -> customLayers.getLayer(mockLibrary("com.acme:test")))
|
||||
.withMessageContaining("com.acme:test").withMessageContaining("test-not-listed")
|
||||
.withMessageContaining("[test]");
|
||||
}
|
||||
|
||||
private Library mockLibrary(String coordinates) {
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates(coordinates));
|
||||
given(library.getName()).willReturn(coordinates);
|
||||
return library;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.loader.tools.Layer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link IncludeExcludeContentSelector}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class IncludeExcludeContentSelectorTests {
|
||||
|
||||
private static final Layer LAYER = new Layer("test");
|
||||
|
||||
@Test
|
||||
void createWhenLayerIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(
|
||||
() -> new IncludeExcludeContentSelector<>(null, Collections.emptyList(), Collections.emptyList()))
|
||||
.withMessage("Layer must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenFactoryIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new IncludeExcludeContentSelector<>(LAYER, null, null, null))
|
||||
.withMessage("FilterFactory must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLayerReturnsLayer() {
|
||||
IncludeExcludeContentSelector<?> selector = new IncludeExcludeContentSelector<>(LAYER, null, null);
|
||||
assertThat(selector.getLayer()).isEqualTo(LAYER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenEmptyIncludesAndEmptyExcludesReturnsTrue() {
|
||||
List<String> includes = Arrays.asList();
|
||||
List<String> excludes = Arrays.asList();
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("A")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenNullIncludesAndEmptyExcludesReturnsTrue() {
|
||||
List<String> includes = null;
|
||||
List<String> excludes = null;
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("A")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenEmptyIncludesAndNotExcludedReturnsTrue() {
|
||||
List<String> includes = Arrays.asList();
|
||||
List<String> excludes = Arrays.asList("B");
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("A")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenEmptyIncludesAndExcludedReturnsFalse() {
|
||||
List<String> includes = Arrays.asList();
|
||||
List<String> excludes = Arrays.asList("A");
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("A")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenIncludedAndEmptyExcludesReturnsTrue() {
|
||||
List<String> includes = Arrays.asList("A", "B");
|
||||
List<String> excludes = Arrays.asList();
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("B")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenIncludedAndNotExcludedReturnsTrue() {
|
||||
List<String> includes = Arrays.asList("A", "B");
|
||||
List<String> excludes = Arrays.asList("C", "D");
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("B")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsWhenIncludedAndExcludedReturnsFalse() {
|
||||
List<String> includes = Arrays.asList("A", "B");
|
||||
List<String> excludes = Arrays.asList("C", "D");
|
||||
IncludeExcludeContentSelector<String> selector = new IncludeExcludeContentSelector<>(LAYER, includes, excludes,
|
||||
TestContentsFilter::new);
|
||||
assertThat(selector.contains("C")).isFalse();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ContentFilter} used for testing.
|
||||
*/
|
||||
static class TestContentsFilter implements ContentFilter<String> {
|
||||
|
||||
private final String match;
|
||||
|
||||
TestContentsFilter(String match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String item) {
|
||||
return this.match.equals(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link LibraryContentFilter}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class LibraryContentFilterTests {
|
||||
|
||||
@Test
|
||||
void createWhenCoordinatesPatternIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new LibraryContentFilter(null))
|
||||
.withMessage("CoordinatesPattern must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenCoordinatesPatternIsEmptyThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new LibraryContentFilter(""))
|
||||
.withMessage("CoordinatesPattern must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenGroupIdIsNullAndToMatchHasWildcardReturnsTrue() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("*:*");
|
||||
assertThat(filter.matches(mockLibrary(null, null, null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenArtifactIdIsNullAndToMatchHasWildcardReturnsTrue() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:*");
|
||||
assertThat(filter.matches(mockLibrary("org.acme", null, null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenVersionIsNullAndToMatchHasWildcardReturnsTrue() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:something:*");
|
||||
assertThat(filter.matches(mockLibrary("org.acme", "something", null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenGroupIdDoesNotMatchReturnsFalse() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:*");
|
||||
assertThat(filter.matches(mockLibrary("other.foo", null, null))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenWhenArtifactIdDoesNotMatchReturnsFalse() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:test:*");
|
||||
assertThat(filter.matches(mockLibrary("org.acme", "other", null))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenArtifactIdMatchesReturnsTrue() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:test:*");
|
||||
assertThat(filter.matches(mockLibrary("org.acme", "test", null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenVersionDoesNotMatchReturnsFalse() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:test:*SNAPSHOT");
|
||||
assertThat(filter.matches(mockLibrary("org.acme", "test", "1.0.0"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenVersionMatchesReturnsTrue() {
|
||||
LibraryContentFilter filter = new LibraryContentFilter("org.acme:test:*SNAPSHOT");
|
||||
assertThat(filter.matches(mockLibrary("org.acme", "test", "1.0.0-SNAPSHOT"))).isTrue();
|
||||
}
|
||||
|
||||
private Library mockLibrary(String groupId, String artifactId, String version) {
|
||||
return mockLibrary(LibraryCoordinates.of(groupId, artifactId, version));
|
||||
}
|
||||
|
||||
private Library mockLibrary(LibraryCoordinates coordinates) {
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(coordinates);
|
||||
return library;
|
||||
}
|
||||
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.application;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link FilteredResourceStrategy}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class FilteredResourceStrategyTests {
|
||||
|
||||
@Test
|
||||
void createWhenFiltersNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new FilteredResourceStrategy("custom", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenFiltersEmptyShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FilteredResourceStrategy("custom", Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLayerShouldReturnLayerName() {
|
||||
FilteredResourceStrategy strategy = new FilteredResourceStrategy("custom",
|
||||
Collections.singletonList(new TestFilter1()));
|
||||
assertThat(strategy.getLayer().toString()).isEqualTo("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMatchingLayerWhenFilterMatchesIncludes() {
|
||||
FilteredResourceStrategy strategy = new FilteredResourceStrategy("custom",
|
||||
Collections.singletonList(new TestFilter1()));
|
||||
assertThat(strategy.getMatchingLayer("ABCD").toString()).isEqualTo("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenFilterMatchesIncludesAndExcludesFromSameFilter() {
|
||||
FilteredResourceStrategy strategy = new FilteredResourceStrategy("custom",
|
||||
Collections.singletonList(new TestFilter1()));
|
||||
assertThat(strategy.getMatchingLayer("AZ")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenFilterMatchesIncludesAndExcludesFromAnotherFilter() {
|
||||
List<ResourceFilter> filters = new ArrayList<>();
|
||||
filters.add(new TestFilter1());
|
||||
filters.add(new TestFilter2());
|
||||
FilteredResourceStrategy strategy = new FilteredResourceStrategy("custom", filters);
|
||||
assertThat(strategy.getMatchingLayer("AY")).isNull();
|
||||
}
|
||||
|
||||
private static class TestFilter1 implements ResourceFilter {
|
||||
|
||||
@Override
|
||||
public boolean isResourceIncluded(String resourceName) {
|
||||
return resourceName.startsWith("A");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResourceExcluded(String resourceName) {
|
||||
return resourceName.endsWith("Z");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestFilter2 implements ResourceFilter {
|
||||
|
||||
@Override
|
||||
public boolean isResourceIncluded(String resourceName) {
|
||||
return resourceName.startsWith("B");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResourceExcluded(String resourceName) {
|
||||
return resourceName.endsWith("Y");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.application;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link LocationFilter}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
class LocationFilterTests {
|
||||
|
||||
@Test
|
||||
void isResourceIncludedWhenPatternMatchesWithWildcard() {
|
||||
LocationFilter filter = new LocationFilter(Collections.singletonList("META-INF/**"), Collections.emptyList());
|
||||
assertThat(filter.isResourceIncluded("META-INF/resources/application.yml")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isResourceIncludedWhenPatternDoesNotMatch() {
|
||||
LocationFilter filter = new LocationFilter(Collections.singletonList("META-INF/**"), Collections.emptyList());
|
||||
assertThat(filter.isResourceIncluded("src/main/resources/application.yml")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isResourceExcludedWhenPatternMatchesWithWildcard() {
|
||||
LocationFilter filter = new LocationFilter(Collections.emptyList(), Collections.singletonList("META-INF/**"));
|
||||
assertThat(filter.isResourceExcluded("META-INF/resources/application.yml")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isResourceExcludedWhenPatternDoesNotMatch() {
|
||||
LocationFilter filter = new LocationFilter(Collections.emptyList(), Collections.singletonList("META-INF/**"));
|
||||
assertThat(filter.isResourceExcluded("src/main/resources/application.yml")).isFalse();
|
||||
}
|
||||
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.library;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryCoordinates;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link CoordinateFilter}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class CoordinateFilterTests {
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenGroupIdIsNullAndToMatchHasWildcard() {
|
||||
List<String> includes = Collections.singletonList("*:*");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates(null, null, null));
|
||||
assertThat(filter.isLibraryIncluded(library)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenArtifactIdIsNullAndToMatchHasWildcard() {
|
||||
List<String> includes = Collections.singletonList("org.acme:*");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("org.acme", null, null));
|
||||
assertThat(filter.isLibraryIncluded(library)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenVersionIsNullAndToMatchHasWildcard() {
|
||||
List<String> includes = Collections.singletonList("org.acme:something:*");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("org.acme", "something", null));
|
||||
assertThat(filter.isLibraryIncluded(library)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenGroupIdDoesNotMatch() {
|
||||
List<String> includes = Collections.singletonList("org.acme:*");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("other.foo", null, null));
|
||||
assertThat(filter.isLibraryIncluded(library)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenArtifactIdDoesNotMatch() {
|
||||
List<String> includes = Collections.singletonList("org.acme:test:*");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("org.acme", "other", null));
|
||||
assertThat(filter.isLibraryIncluded(library)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenArtifactIdMatches() {
|
||||
List<String> includes = Collections.singletonList("org.acme:test:*");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("org.acme", "test", null));
|
||||
assertThat(filter.isLibraryIncluded(library)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenVersionDoesNotMatch() {
|
||||
List<String> includes = Collections.singletonList("org.acme:test:*SNAPSHOT");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("org.acme", "test", "1.0.0"));
|
||||
assertThat(filter.isLibraryIncluded(library)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLibraryIncludedWhenVersionMatches() {
|
||||
List<String> includes = Collections.singletonList("org.acme:test:*SNAPSHOT");
|
||||
CoordinateFilter filter = new CoordinateFilter(includes, Collections.emptyList());
|
||||
Library library = mock(Library.class);
|
||||
given(library.getCoordinates()).willReturn(new LibraryCoordinates("org.acme", "test", "1.0.0-SNAPSHOT"));
|
||||
assertThat(filter.isLibraryIncluded(library)).isTrue();
|
||||
}
|
||||
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* 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.springframework.boot.loader.tools.layer.library;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.loader.tools.Library;
|
||||
import org.springframework.boot.loader.tools.LibraryScope;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link FilteredLibraryStrategy}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class FilteredLibraryStrategyTests {
|
||||
|
||||
@Test
|
||||
void createWhenFiltersNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new FilteredLibraryStrategy("custom", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createWhenFiltersEmptyShouldThrowException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> new FilteredLibraryStrategy("custom", Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getLayerShouldReturnLayerName() {
|
||||
FilteredLibraryStrategy strategy = new FilteredLibraryStrategy("custom",
|
||||
Collections.singletonList(new TestFilter1Library()));
|
||||
assertThat(strategy.getLayer().toString()).isEqualTo("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getMatchingLayerWhenFilterMatchesIncludes() {
|
||||
FilteredLibraryStrategy strategy = new FilteredLibraryStrategy("custom",
|
||||
Collections.singletonList(new TestFilter1Library()));
|
||||
Library library = mockLibrary("A-Compile", LibraryScope.COMPILE);
|
||||
assertThat(strategy.getMatchingLayer(library).toString()).isEqualTo("custom");
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenFilterMatchesIncludesAndExcludesFromSameFilter() {
|
||||
FilteredLibraryStrategy strategy = new FilteredLibraryStrategy("custom",
|
||||
Collections.singletonList(new TestFilter1Library()));
|
||||
Library library = mockLibrary("A-Runtime", LibraryScope.RUNTIME);
|
||||
assertThat(strategy.getMatchingLayer(library)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesWhenFilterMatchesIncludesAndExcludesFromAnotherFilter() {
|
||||
List<LibraryFilter> filters = new ArrayList<>();
|
||||
filters.add(new TestFilter1Library());
|
||||
filters.add(new TestFilter2Library());
|
||||
FilteredLibraryStrategy strategy = new FilteredLibraryStrategy("custom", filters);
|
||||
Library library = mockLibrary("A-Provided", LibraryScope.PROVIDED);
|
||||
assertThat(strategy.getMatchingLayer(library)).isNull();
|
||||
}
|
||||
|
||||
private Library mockLibrary(String name, LibraryScope runtime) {
|
||||
Library library = mock(Library.class);
|
||||
given(library.getName()).willReturn(name);
|
||||
given(library.getScope()).willReturn(runtime);
|
||||
return library;
|
||||
}
|
||||
|
||||
private static class TestFilter1Library implements LibraryFilter {
|
||||
|
||||
@Override
|
||||
public boolean isLibraryIncluded(Library library) {
|
||||
return library.getName().contains("A");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLibraryExcluded(Library library) {
|
||||
return library.getScope().equals(LibraryScope.RUNTIME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestFilter2Library implements LibraryFilter {
|
||||
|
||||
@Override
|
||||
public boolean isLibraryIncluded(Library library) {
|
||||
return library.getName().contains("B");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLibraryExcluded(Library library) {
|
||||
return library.getScope().equals(LibraryScope.PROVIDED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,35 +1,23 @@
|
||||
<layers-configuration xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/layers/layers-configuration-2.3.xsd">
|
||||
<layers>
|
||||
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/layers/layers-2.3.xsd">
|
||||
<application>
|
||||
<into layer="configuration">
|
||||
<include>**/application*.*</include>
|
||||
</into>
|
||||
<into layer="application" />
|
||||
</application>
|
||||
<dependencies>
|
||||
<into layer="snapshot-dependencies">
|
||||
<include>*:*:*-SNAPSHOT</include>
|
||||
</into>
|
||||
<into layer="my-dependencies-name" />
|
||||
</dependencies>
|
||||
<layerOrder>
|
||||
<layer>configuration</layer>
|
||||
<layer>application</layer>
|
||||
<layer>snapshot-dependencies</layer>
|
||||
<layer>my-dependencies-name</layer>
|
||||
</layers>
|
||||
<libraries>
|
||||
<layer-content layer="snapshot-dependencies">
|
||||
<coordinates>
|
||||
<include>*:*:*-SNAPSHOT</include>
|
||||
</coordinates>
|
||||
</layer-content>
|
||||
<layer-content layer="my-dependencies-name">
|
||||
<coordinates>
|
||||
<include>*:*:*</include>
|
||||
</coordinates>
|
||||
</layer-content>
|
||||
</libraries>
|
||||
<application>
|
||||
<layer-content layer="configuration">
|
||||
<locations>
|
||||
<include>**/application*.*</include>
|
||||
</locations>
|
||||
</layer-content>
|
||||
<layer-content layer="application">
|
||||
<locations>
|
||||
<include>**</include>
|
||||
</locations>
|
||||
</layer-content>
|
||||
</application>
|
||||
</layers-configuration>
|
||||
</layerOrder>
|
||||
</layers>
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<xsd:schema elementFormDefault="qualified"
|
||||
xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://www.springframework.org/schema/boot/layers">
|
||||
<xsd:element name="layers" type="layersType" />
|
||||
<xsd:complexType name="layersType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="application" type="applicationType" />
|
||||
<xsd:element name="dependencies" type="dependenciesType" />
|
||||
<xsd:element name="layerOrder" type="layerOrderType" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="applicationType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The 'into layer' selections that should be applied to application classes and resources.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence maxOccurs="unbounded">
|
||||
<xsd:element name="into" type="intoType" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="dependenciesType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The 'into layer' selections that should be applied to dependencies.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence maxOccurs="unbounded">
|
||||
<xsd:element name="into" type="intoType" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="layerOrderType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The order that layers should be added (starting with the least frequently changed layer).
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="layer" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The layer name.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:minLength value="1" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="intoType">
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element type="xsd:string" name="include"
|
||||
minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Pattern of the elements to include.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element type="xsd:string" name="exclude"
|
||||
minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Pattern of the elements to exclude.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:attribute type="xsd:string" name="layer"
|
||||
use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
@ -1,96 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<xsd:schema elementFormDefault="qualified"
|
||||
xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://www.springframework.org/schema/boot/layers">
|
||||
<xsd:element name="layers-configuration" type="layersConfigurationType"/>
|
||||
<xsd:complexType name="layersConfigurationType">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="layersType" name="layers"/>
|
||||
<xsd:element type="librariesType" name="libraries" minOccurs="0"/>
|
||||
<xsd:element type="applicationType" name="application" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="layersType">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="xsd:string" name="layer" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of a layer. Each layer in the configuration must be referenced once and the
|
||||
order matches how the content is likely to change. Put layers that are frequently
|
||||
updated first, layers that are more stable (such as non-snapshot dependencies) last.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="librariesType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Strategies that should be applied to libraries. If no strategies are defined, two
|
||||
layers are created out-of-the-box. A "snapshot-dependencies" layer with SNAPSHOT
|
||||
libraries and a "dependencies" layer with all the other libraries.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element type="librariesLayerContentType" name="layer-content">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Strategy to apply on libraries.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="librariesLayerContentType" mixed="true">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="filterType" name="coordinates" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute type="xsd:string" name="layer" use="required"/>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="applicationType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Strategies that should be applied to application classes and resources. If no strategies are defined, a single
|
||||
"application" layer is created out-of-the-box.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element type="applicationLayerContentType" name="layer-content" maxOccurs="unbounded"
|
||||
minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Strategy to apply on application classes and resources.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
<xsd:complexType name="applicationLayerContentType" mixed="true">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="filterType" name="locations" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute type="xsd:string" name="layer" use="required"/>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="filterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element type="xsd:string" name="exclude" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Pattern of the elements to exclude. An exclude pattern takes precedence over an
|
||||
include pattern and must be declared first.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
<xsd:element type="xsd:string" name="include" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Pattern of the elements to include.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
@ -0,0 +1,11 @@
|
||||
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers.xsd">
|
||||
<application>
|
||||
<into layer="my-layer" />
|
||||
</application>
|
||||
<layerOrder>
|
||||
<layer>my-layer</layer>
|
||||
</layerOrder>
|
||||
</layers>
|
@ -0,0 +1,11 @@
|
||||
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers-2.3.xsd">
|
||||
<dependencies>
|
||||
<into layer="my-deps" />
|
||||
</dependencies>
|
||||
<layerOrder>
|
||||
<layer>my-deps</layer>
|
||||
</layerOrder>
|
||||
</layers>
|
@ -1,47 +1,32 @@
|
||||
<layers-configuration xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers-configuration-2.3.xsd">
|
||||
<layers>
|
||||
<layer>configuration</layer>
|
||||
<layer>application</layer>
|
||||
<layer>my-resources</layer>
|
||||
<layer>snapshot-dependencies</layer>
|
||||
<layer>my-deps</layer>
|
||||
<layer>my-dependencies-name</layer>
|
||||
</layers>
|
||||
<libraries>
|
||||
<layer-content layer="snapshot-dependencies">
|
||||
<coordinates>
|
||||
<include>*:*:*-SNAPSHOT</include>
|
||||
</coordinates>
|
||||
</layer-content>
|
||||
<layer-content layer="my-deps">
|
||||
<coordinates>
|
||||
<include>com.acme:*</include>
|
||||
</coordinates>
|
||||
</layer-content>
|
||||
<layer-content layer="my-dependencies-name">
|
||||
<coordinates>
|
||||
<include>*:*:*</include>
|
||||
</coordinates>
|
||||
</layer-content>
|
||||
</libraries>
|
||||
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers-2.3.xsd">
|
||||
<application>
|
||||
<layer-content layer="my-resources">
|
||||
<locations>
|
||||
<include>META-INF/resources/**</include>
|
||||
</locations>
|
||||
</layer-content>
|
||||
<layer-content layer="configuration">
|
||||
<locations>
|
||||
<include>**/application*.*</include>
|
||||
</locations>
|
||||
</layer-content>
|
||||
<layer-content layer="application">
|
||||
<locations>
|
||||
<include>**</include>
|
||||
</locations>
|
||||
</layer-content>
|
||||
<into layer="my-resources">
|
||||
<include>META-INF/resources/**</include>
|
||||
<exclude>*.properties</exclude>
|
||||
</into>
|
||||
<into layer="configuration">
|
||||
<include>**/application*.*</include>
|
||||
</into>
|
||||
<into layer="application" />
|
||||
</application>
|
||||
</layers-configuration>
|
||||
<dependencies>
|
||||
<into layer="snapshot-dependencies">
|
||||
<include>*:*:*-SNAPSHOT</include>
|
||||
</into>
|
||||
<into layer="my-deps">
|
||||
<include>com.acme:*</include>
|
||||
</into>
|
||||
<into layer="my-dependencies-name"/>
|
||||
</dependencies>
|
||||
<layerOrder>
|
||||
<layer>my-deps</layer>
|
||||
<layer>my-dependencies-name</layer>
|
||||
<layer>snapshot-dependencies</layer>
|
||||
<layer>my-resources</layer>
|
||||
<layer>configuration</layer>
|
||||
<layer>application</layer>
|
||||
</layerOrder>
|
||||
</layers>
|
@ -1,11 +0,0 @@
|
||||
<layers-configuration xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers-configuration-2.3.xsd">
|
||||
<layers>
|
||||
<layer>my-deps</layer>
|
||||
</layers>
|
||||
<libraries>
|
||||
<layer-content layer="my-deps"/>
|
||||
</libraries>
|
||||
</layers-configuration>
|
@ -1,11 +1,11 @@
|
||||
<layers-configuration xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers-configuration-2.3.xsd">
|
||||
<layers>
|
||||
<layer>my-layer</layer>
|
||||
</layers>
|
||||
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||
https://www.springframework.org/schema/boot/layers/layers-2.3.xsd">
|
||||
<application>
|
||||
<layer-content layer="my-layer"/>
|
||||
<into layer="my-layer" />
|
||||
</application>
|
||||
</layers-configuration>
|
||||
<layerOrder>
|
||||
<layer>my-layer</layer>
|
||||
</layerOrder>
|
||||
</layers>
|
Loading…
Reference in New Issue