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"
|
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||||
https://www.springframework.org/schema/layers/layers-configuration-2.3.xsd">
|
https://www.springframework.org/schema/layers/layers-2.3.xsd">
|
||||||
<layers>
|
<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>configuration</layer>
|
||||||
<layer>application</layer>
|
<layer>application</layer>
|
||||||
<layer>snapshot-dependencies</layer>
|
<layer>snapshot-dependencies</layer>
|
||||||
<layer>my-dependencies-name</layer>
|
<layer>my-dependencies-name</layer>
|
||||||
</layers>
|
</layerOrder>
|
||||||
<libraries>
|
</layers>
|
||||||
<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>
|
|
@ -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"
|
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||||
https://www.springframework.org/schema/boot/layers/layers-configuration-2.3.xsd">
|
https://www.springframework.org/schema/boot/layers/layers-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>
|
|
||||||
<application>
|
<application>
|
||||||
<layer-content layer="my-resources">
|
<into layer="my-resources">
|
||||||
<locations>
|
<include>META-INF/resources/**</include>
|
||||||
<include>META-INF/resources/**</include>
|
<exclude>*.properties</exclude>
|
||||||
</locations>
|
</into>
|
||||||
</layer-content>
|
<into layer="configuration">
|
||||||
<layer-content layer="configuration">
|
<include>**/application*.*</include>
|
||||||
<locations>
|
</into>
|
||||||
<include>**/application*.*</include>
|
<into layer="application" />
|
||||||
</locations>
|
|
||||||
</layer-content>
|
|
||||||
<layer-content layer="application">
|
|
||||||
<locations>
|
|
||||||
<include>**</include>
|
|
||||||
</locations>
|
|
||||||
</layer-content>
|
|
||||||
</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"
|
<layers xmlns="http://www.springframework.org/schema/boot/layers"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
xsi:schemaLocation="http://www.springframework.org/schema/boot/layers
|
||||||
https://www.springframework.org/schema/boot/layers/layers-configuration-2.3.xsd">
|
https://www.springframework.org/schema/boot/layers/layers-2.3.xsd">
|
||||||
<layers>
|
|
||||||
<layer>my-layer</layer>
|
|
||||||
</layers>
|
|
||||||
<application>
|
<application>
|
||||||
<layer-content layer="my-layer"/>
|
<into layer="my-layer" />
|
||||||
</application>
|
</application>
|
||||||
</layers-configuration>
|
<layerOrder>
|
||||||
|
<layer>my-layer</layer>
|
||||||
|
</layerOrder>
|
||||||
|
</layers>
|
Loading…
Reference in New Issue