Polish
This commit is contained in:
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.jdbc;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcDb2Dialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcMySqlDialect;
|
||||
import org.springframework.data.jdbc.core.dialect.JdbcPostgresDialect;
|
||||
@@ -26,6 +24,7 @@ import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.dialect.H2Dialect;
|
||||
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
|
||||
import org.springframework.data.relational.core.dialect.MariaDbDialect;
|
||||
import org.springframework.data.relational.core.dialect.MySqlDialect;
|
||||
import org.springframework.data.relational.core.dialect.OracleDialect;
|
||||
|
||||
/**
|
||||
@@ -34,87 +33,56 @@ import org.springframework.data.relational.core.dialect.OracleDialect;
|
||||
* @author Jens Schauder
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public enum JdbcDatabaseDialect implements Supplier<Dialect> {
|
||||
public enum JdbcDatabaseDialect {
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcDb2Dialect}.
|
||||
*/
|
||||
DB2 {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return JdbcDb2Dialect.INSTANCE;
|
||||
}
|
||||
},
|
||||
DB2(JdbcDb2Dialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link H2Dialect}.
|
||||
*/
|
||||
H2 {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return H2Dialect.INSTANCE;
|
||||
}
|
||||
},
|
||||
H2(H2Dialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link HsqlDbDialect}.
|
||||
*/
|
||||
HSQL {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return HsqlDbDialect.INSTANCE;
|
||||
}
|
||||
},
|
||||
HSQL(HsqlDbDialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link MariaDbDialect}.
|
||||
*/
|
||||
MARIA {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return MariaDbDialect.INSTANCE;
|
||||
}
|
||||
},
|
||||
MARIA(MySqlDialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcMySqlDialect}.
|
||||
*/
|
||||
MYSQL {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return JdbcMySqlDialect.INSTANCE;
|
||||
}
|
||||
},
|
||||
MYSQL(MySqlDialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link OracleDialect}.
|
||||
*/
|
||||
ORACLE {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return OracleDialect.INSTANCE;
|
||||
|
||||
}
|
||||
},
|
||||
ORACLE(OracleDialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcPostgresDialect}.
|
||||
*/
|
||||
POSTGRESQL {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return JdbcPostgresDialect.INSTANCE;
|
||||
}
|
||||
},
|
||||
POSTGRESQL(JdbcPostgresDialect.INSTANCE),
|
||||
|
||||
/**
|
||||
* Provides an instance of {@link JdbcSqlServerDialect}.
|
||||
*/
|
||||
SQL_SERVER {
|
||||
@Override
|
||||
public Dialect get() {
|
||||
return JdbcSqlServerDialect.INSTANCE;
|
||||
}
|
||||
SQL_SERVER(JdbcSqlServerDialect.INSTANCE);
|
||||
|
||||
private final Dialect dialect;
|
||||
|
||||
JdbcDatabaseDialect(Dialect dialect) {
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
||||
final Dialect getDialect() {
|
||||
return this.dialect;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -148,10 +148,7 @@ public class JdbcRepositoriesAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
public Dialect jdbcDialect(NamedParameterJdbcOperations operations) {
|
||||
JdbcDatabaseDialect dialect = this.properties.getDialect();
|
||||
if (dialect != null) {
|
||||
return dialect.get();
|
||||
}
|
||||
return super.jdbcDialect(operations);
|
||||
return (dialect != null) ? dialect.getDialect() : super.jdbcDialect(operations);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -68,8 +68,7 @@ record BundleContentProperty(String name, String value) {
|
||||
|
||||
private Resource getResource() {
|
||||
Assert.state(!isPemContent(), "Value contains PEM content");
|
||||
ApplicationResourceLoader resourceLoader = new ApplicationResourceLoader();
|
||||
return resourceLoader.getResource(this.value);
|
||||
return new ApplicationResourceLoader().getResource(this.value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -109,7 +109,6 @@ class GraphQlWebFluxAutoConfigurationTests {
|
||||
.contentTypeCompatibleWith(MediaType.TEXT_EVENT_STREAM)
|
||||
.expectBody(String.class)
|
||||
.returnResult();
|
||||
|
||||
assertThat(result.getResponseBody()).contains("event:next",
|
||||
"data:{\"data\":{\"booksOnSale\":{\"id\":\"book-1\",\"name\":\"GraphQL for beginners\",\"pageCount\":100,\"author\":\"John GraphQL\"}}}",
|
||||
"event:next",
|
||||
|
||||
@@ -156,10 +156,8 @@ public abstract class BootJar extends Jar implements BootArchive {
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private boolean isIncludeJarmodeTools() {
|
||||
if (!this.getIncludeTools().get()) {
|
||||
return false;
|
||||
}
|
||||
return this.layered.getIncludeLayerTools().get();
|
||||
return Boolean.TRUE.equals(this.getIncludeTools().get())
|
||||
&& Boolean.TRUE.equals(this.layered.getIncludeLayerTools().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -130,10 +130,8 @@ public abstract class BootWar extends War implements BootArchive {
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private boolean isIncludeJarmodeTools() {
|
||||
if (!this.getIncludeTools().get()) {
|
||||
return false;
|
||||
}
|
||||
return this.layered.getIncludeLayerTools().get();
|
||||
return Boolean.TRUE.equals(this.getIncludeTools().get())
|
||||
&& Boolean.TRUE.equals(this.layered.getIncludeLayerTools().get());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -316,18 +316,13 @@ abstract class Command {
|
||||
}
|
||||
if (this.optionalValue) {
|
||||
String nextArg = args.peek();
|
||||
if (nextArg == null || nextArg.startsWith("--")) {
|
||||
return null;
|
||||
}
|
||||
return (nextArg != null && !nextArg.startsWith("--")) ? args.removeFirst() : null;
|
||||
}
|
||||
try {
|
||||
return args.removeFirst();
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return args.removeFirst();
|
||||
}
|
||||
catch (NoSuchElementException ex) {
|
||||
throw new MissingValueException(this.name);
|
||||
}
|
||||
catch (NoSuchElementException ex) {
|
||||
throw new MissingValueException(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -236,10 +236,7 @@ class ExtractCommand extends Command {
|
||||
}
|
||||
|
||||
private Layers getLayers() {
|
||||
if (this.layers != null) {
|
||||
return this.layers;
|
||||
}
|
||||
return Layers.get(this.context);
|
||||
return (this.layers != null) ? this.layers : Layers.get(this.context);
|
||||
}
|
||||
|
||||
private void createApplication(JarStructure jarStructure, FileResolver fileResolver, Map<Option, String> options)
|
||||
@@ -250,7 +247,7 @@ class ExtractCommand extends Command {
|
||||
}
|
||||
String librariesDirectory = getLibrariesDirectory(options);
|
||||
Manifest manifest = jarStructure.createLauncherManifest((library) -> librariesDirectory + library);
|
||||
mkDirs(file.getParentFile());
|
||||
mkdirs(file.getParentFile());
|
||||
try (JarOutputStream output = new JarOutputStream(new FileOutputStream(file), manifest)) {
|
||||
withJarEntries(this.context.getArchiveFile(), ((stream, jarEntry) -> {
|
||||
Entry entry = jarStructure.resolve(jarEntry);
|
||||
@@ -272,14 +269,11 @@ class ExtractCommand extends Command {
|
||||
}
|
||||
|
||||
private static boolean isType(Entry entry, Type type) {
|
||||
if (entry == null) {
|
||||
return false;
|
||||
}
|
||||
return entry.type() == type;
|
||||
return (entry != null) && entry.type() == type;
|
||||
}
|
||||
|
||||
private static void extractEntry(InputStream stream, JarEntry entry, File file) throws IOException {
|
||||
mkDirs(file.getParentFile());
|
||||
mkdirs(file.getParentFile());
|
||||
try (OutputStream out = new FileOutputStream(file)) {
|
||||
StreamUtils.copy(stream, out);
|
||||
}
|
||||
@@ -293,27 +287,18 @@ class ExtractCommand extends Command {
|
||||
}
|
||||
|
||||
private static FileTime getCreationTime(JarEntry entry) {
|
||||
if (entry.getCreationTime() != null) {
|
||||
return entry.getCreationTime();
|
||||
}
|
||||
return entry.getLastModifiedTime();
|
||||
return (entry.getCreationTime() != null) ? entry.getCreationTime() : entry.getLastModifiedTime();
|
||||
}
|
||||
|
||||
private static FileTime getLastAccessTime(JarEntry entry) {
|
||||
if (entry.getLastAccessTime() != null) {
|
||||
return entry.getLastAccessTime();
|
||||
}
|
||||
return getLastModifiedTime(entry);
|
||||
return (entry.getLastAccessTime() != null) ? entry.getLastAccessTime() : getLastModifiedTime(entry);
|
||||
}
|
||||
|
||||
private static FileTime getLastModifiedTime(JarEntry entry) {
|
||||
if (entry.getLastModifiedTime() != null) {
|
||||
return entry.getLastModifiedTime();
|
||||
}
|
||||
return entry.getCreationTime();
|
||||
return (entry.getLastModifiedTime() != null) ? entry.getLastModifiedTime() : entry.getCreationTime();
|
||||
}
|
||||
|
||||
private static void mkDirs(File file) throws IOException {
|
||||
private static void mkdirs(File file) throws IOException {
|
||||
if (!file.exists() && !file.mkdirs()) {
|
||||
throw new IOException("Unable to create directory " + file);
|
||||
}
|
||||
@@ -461,7 +446,7 @@ class ExtractCommand extends Command {
|
||||
public void createDirectories() throws IOException {
|
||||
for (String layer : this.layers) {
|
||||
if (shouldExtractLayer(layer)) {
|
||||
mkDirs(getLayerDirectory(layer));
|
||||
mkdirs(getLayerDirectory(layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -492,10 +477,7 @@ class ExtractCommand extends Command {
|
||||
}
|
||||
|
||||
private boolean shouldExtractLayer(String layer) {
|
||||
if (this.layersToExtract.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return this.layersToExtract.contains(layer);
|
||||
return this.layersToExtract.isEmpty() || this.layersToExtract.contains(layer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -65,10 +65,7 @@ class IndexedJarStructure implements JarStructure {
|
||||
|
||||
private static String getLocation(Manifest manifest, String attribute) {
|
||||
String location = getMandatoryAttribute(manifest, attribute);
|
||||
if (!location.endsWith("/")) {
|
||||
location = location + "/";
|
||||
}
|
||||
return location;
|
||||
return (!location.endsWith("/")) ? location + "/" : location;
|
||||
}
|
||||
|
||||
private static List<String> readIndexFile(String indexFile) {
|
||||
@@ -78,12 +75,8 @@ class IndexedJarStructure implements JarStructure {
|
||||
.toArray(String[]::new);
|
||||
List<String> classpathEntries = new ArrayList<>();
|
||||
for (String line : lines) {
|
||||
if (line.startsWith("- ")) {
|
||||
classpathEntries.add(line.substring(3, line.length() - 1));
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Classpath index file is malformed");
|
||||
}
|
||||
Assert.state(line.startsWith("- "), "Classpath index file is malformed");
|
||||
classpathEntries.add(line.substring(3, line.length() - 1));
|
||||
}
|
||||
Assert.state(!classpathEntries.isEmpty(), "Empty classpath index file loaded");
|
||||
return classpathEntries;
|
||||
@@ -99,10 +92,10 @@ class IndexedJarStructure implements JarStructure {
|
||||
if (this.classpathEntries.contains(name)) {
|
||||
return new Entry(name, toStructureDependency(name), Type.LIBRARY);
|
||||
}
|
||||
else if (name.startsWith(this.classesLocation)) {
|
||||
if (name.startsWith(this.classesLocation)) {
|
||||
return new Entry(name, name.substring(this.classesLocation.length()), Type.APPLICATION_CLASS_OR_RESOURCE);
|
||||
}
|
||||
else if (name.startsWith("org/springframework/boot/loader")) {
|
||||
if (name.startsWith("org/springframework/boot/loader")) {
|
||||
return new Entry(name, name, Type.LOADER);
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -68,11 +68,13 @@ interface JarStructure {
|
||||
* @param type of the entry
|
||||
*/
|
||||
record Entry(String originalLocation, String location, Type type) {
|
||||
|
||||
enum Type {
|
||||
|
||||
LIBRARY, APPLICATION_CLASS_OR_RESOURCE, LOADER
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,9 +44,11 @@ import org.springframework.util.StringUtils;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Base class for jar mode tests.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
abstract class AbstractTests {
|
||||
abstract class AbstractJarModeTests {
|
||||
|
||||
@TempDir
|
||||
File tempDir;
|
||||
@@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class ExtractCommandTests extends AbstractTests {
|
||||
class ExtractCommandTests extends AbstractJarModeTests {
|
||||
|
||||
private static final Instant CREATION_TIME = Instant.parse("2020-01-01T00:00:00Z");
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class ListLayersCommandTests extends AbstractTests {
|
||||
class ListLayersCommandTests extends AbstractJarModeTests {
|
||||
|
||||
@Test
|
||||
void shouldListLayers() throws IOException {
|
||||
|
||||
@@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class ToolsJarModeTests extends AbstractTests {
|
||||
class ToolsJarModeTests extends AbstractJarModeTests {
|
||||
|
||||
private ToolsJarMode mode;
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -362,7 +361,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
}
|
||||
args.add("-cp");
|
||||
if (needsClasspathArgFile()) {
|
||||
args.add("@" + writeClasspathArgFile(classpath.toString()));
|
||||
args.add("@" + ArgFile.create(classpath).path());
|
||||
}
|
||||
else {
|
||||
args.add(classpath.toString());
|
||||
@@ -389,12 +388,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
return os.toLowerCase(Locale.ROOT).contains("win");
|
||||
}
|
||||
|
||||
private Path writeClasspathArgFile(String classpath) throws IOException {
|
||||
ArgFile argFile = ArgFile.create();
|
||||
argFile.write(classpath);
|
||||
return argFile.getPath();
|
||||
}
|
||||
|
||||
protected URL[] getClassPathUrls() throws MojoExecutionException {
|
||||
try {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
@@ -473,30 +466,20 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
|
||||
}
|
||||
|
||||
static class ArgFile {
|
||||
record ArgFile(Path path) {
|
||||
|
||||
private final Path path;
|
||||
|
||||
ArgFile(Path path) {
|
||||
this.path = path;
|
||||
private void write(CharSequence content) throws IOException {
|
||||
Files.writeString(this.path, "\"" + escape(content) + "\"");
|
||||
}
|
||||
|
||||
void write(String content) throws IOException {
|
||||
String escaped = escape(content);
|
||||
Files.writeString(this.path, "\"" + escaped + "\"", StandardOpenOption.APPEND);
|
||||
private String escape(CharSequence content) {
|
||||
return content.toString().replace("\\", "\\\\");
|
||||
}
|
||||
|
||||
Path getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
private String escape(String content) {
|
||||
return content.replace("\\", "\\\\");
|
||||
}
|
||||
|
||||
static ArgFile create() throws IOException {
|
||||
Path file = Files.createTempFile("spring-boot-", ".argfile");
|
||||
return new ArgFile(file);
|
||||
static ArgFile create(CharSequence content) throws IOException {
|
||||
ArgFile argFile = new ArgFile(Files.createTempFile("spring-boot-", ".argfile"));
|
||||
argFile.write(content);
|
||||
return argFile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,11 +34,8 @@ class AbstractRunMojoTests {
|
||||
|
||||
@Test
|
||||
void argfileEscapesContent() throws IOException {
|
||||
ArgFile file = ArgFile.create();
|
||||
file.write("some \\ content");
|
||||
file.write("And even more content");
|
||||
assertThat(file.getPath()).content(StandardCharsets.UTF_8)
|
||||
.isEqualTo("\"some \\\\ content\"\"And even more content\"");
|
||||
ArgFile file = ArgFile.create("some \\ content");
|
||||
assertThat(file.path()).content(StandardCharsets.UTF_8).isEqualTo("\"some \\\\ content\"");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -97,10 +97,7 @@ class ConfigDataEnvironmentContributorPlaceholdersResolver implements Placeholde
|
||||
}
|
||||
|
||||
private String convertValueIfNecessary(Object value) {
|
||||
if (value instanceof String string) {
|
||||
return string;
|
||||
}
|
||||
return this.conversionService.convert(value, String.class);
|
||||
return (value instanceof String string) ? string : this.conversionService.convert(value, String.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.io.IOException;
|
||||
import org.springframework.boot.io.ApplicationResourceLoader;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
/**
|
||||
* {@link Converter} to convert from a {@link String} to a {@link File}. Supports basic
|
||||
@@ -33,11 +32,9 @@ import org.springframework.core.io.ResourceLoader;
|
||||
*/
|
||||
class StringToFileConverter implements Converter<String, File> {
|
||||
|
||||
private static final ResourceLoader resourceLoader = new ApplicationResourceLoader();
|
||||
|
||||
@Override
|
||||
public File convert(String source) {
|
||||
Resource resource = resourceLoader.getResource(source);
|
||||
Resource resource = new ApplicationResourceLoader().getResource(source);
|
||||
return getFile(resource);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,13 @@ import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.ProtocolResolver;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
/**
|
||||
* A {@link DefaultResourceLoader} with any {@link ProtocolResolver}s registered in a
|
||||
* {@code spring.factories} file applied to it. Plain paths without a qualifier will
|
||||
* resolve to file system resources. This is different from {@code DefaultResourceLoader},
|
||||
* which resolves unqualified paths to classpath resources.
|
||||
* A {@link DefaultResourceLoader} with any {@link ProtocolResolver ProtocolResolvers}
|
||||
* registered in a {@code spring.factories} file applied to it. Plain paths without a
|
||||
* qualifier will resolve to file system resources. This is different from
|
||||
* {@code DefaultResourceLoader}, which resolves unqualified paths to classpath resources.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @since 3.3.0
|
||||
@@ -37,8 +38,7 @@ public class ApplicationResourceLoader extends DefaultResourceLoader {
|
||||
* Create a new {@code ApplicationResourceLoader}.
|
||||
*/
|
||||
public ApplicationResourceLoader() {
|
||||
super();
|
||||
ProtocolResolvers.applyTo(this);
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,8 @@ public class ApplicationResourceLoader extends DefaultResourceLoader {
|
||||
*/
|
||||
public ApplicationResourceLoader(ClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
ProtocolResolvers.applyTo(this);
|
||||
SpringFactoriesLoader loader = SpringFactoriesLoader.forDefaultResourceLocation(classLoader);
|
||||
getProtocolResolvers().addAll(loader.load(ProtocolResolver.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.io;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ProtocolResolver;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ProtocolResolver} implementations that are loaded from a
|
||||
* {@code spring.factories} file.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
final class ProtocolResolvers {
|
||||
|
||||
private ProtocolResolvers() {
|
||||
}
|
||||
|
||||
static <T extends DefaultResourceLoader> void applyTo(T resourceLoader) {
|
||||
Assert.notNull(resourceLoader, "ResourceLoader must not be null");
|
||||
SpringFactoriesLoader loader = SpringFactoriesLoader
|
||||
.forDefaultResourceLocation(resourceLoader.getClassLoader());
|
||||
List<ProtocolResolver> resolvers = loader.load(ProtocolResolver.class);
|
||||
resourceLoader.getProtocolResolvers().addAll(resolvers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.boot.web.embedded.netty.SslServerCustomizer;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
import org.springframework.boot.web.server.Ssl.ClientAuth;
|
||||
import org.springframework.boot.web.server.Ssl.ServerNameSslBundle;
|
||||
import org.springframework.boot.web.server.WebServerSslBundle;
|
||||
import org.springframework.http.client.ReactorResourceFactory;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -207,8 +208,11 @@ public class NettyRSocketServerFactory implements RSocketServerFactory, Configur
|
||||
protected final Map<String, SslBundle> getServerNameSslBundles() {
|
||||
return this.ssl.getServerNameBundles()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Ssl.ServerNameSslBundle::serverName,
|
||||
(serverNameSslBundle) -> this.sslBundles.getBundle(serverNameSslBundle.bundle())));
|
||||
.collect(Collectors.toMap(Ssl.ServerNameSslBundle::serverName, this::getBundle));
|
||||
}
|
||||
|
||||
private SslBundle getBundle(ServerNameSslBundle serverNameSslBundle) {
|
||||
return this.sslBundles.getBundle(serverNameSslBundle.bundle());
|
||||
}
|
||||
|
||||
private InetSocketAddress getListenAddress() {
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.security.cert.CertificateException;
|
||||
import org.springframework.boot.io.ApplicationResourceLoader;
|
||||
import org.springframework.boot.ssl.SslStoreBundle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -115,8 +114,7 @@ public class JksSslStoreBundle implements SslStoreBundle {
|
||||
private void loadKeyStore(KeyStore store, String location, char[] password) {
|
||||
Assert.state(StringUtils.hasText(location), () -> "Location must not be empty or null");
|
||||
try {
|
||||
ResourceLoader resourceLoader = new ApplicationResourceLoader();
|
||||
Resource resource = resourceLoader.getResource(location);
|
||||
Resource resource = new ApplicationResourceLoader().getResource(location);
|
||||
try (InputStream stream = resource.getInputStream()) {
|
||||
store.load(stream, password);
|
||||
}
|
||||
|
||||
@@ -119,8 +119,7 @@ public final class PemContent {
|
||||
return new PemContent(content);
|
||||
}
|
||||
try {
|
||||
ApplicationResourceLoader resourceLoader = new ApplicationResourceLoader();
|
||||
Resource resource = resourceLoader.getResource(content);
|
||||
Resource resource = new ApplicationResourceLoader().getResource(content);
|
||||
return load(resource.getInputStream());
|
||||
}
|
||||
catch (IOException | UncheckedIOException ex) {
|
||||
|
||||
@@ -248,9 +248,7 @@ public class JettyServletWebServerFactory extends AbstractServletWebServerFactor
|
||||
}
|
||||
|
||||
private void customizeSsl(Server server, InetSocketAddress address) {
|
||||
if (!getSsl().getServerNameBundles().isEmpty()) {
|
||||
throw new IllegalArgumentException("Server name SSL bundles are not supported with Jetty");
|
||||
}
|
||||
Assert.state(getSsl().getServerNameBundles().isEmpty(), "Server name SSL bundles are not supported with Jetty");
|
||||
new SslServerCustomizer(getHttp2(), address, getSsl().getClientAuth(), getSslBundle()).customize(server);
|
||||
}
|
||||
|
||||
|
||||
@@ -182,10 +182,10 @@ public class NettyReactiveWebServerFactory extends AbstractReactiveWebServerFact
|
||||
return customizer.apply(httpServer);
|
||||
}
|
||||
|
||||
private void addBundleUpdateHandler(String hostName, String bundleName, SslServerCustomizer customizer) {
|
||||
private void addBundleUpdateHandler(String serverName, String bundleName, SslServerCustomizer customizer) {
|
||||
if (StringUtils.hasText(bundleName)) {
|
||||
getSslBundles().addBundleUpdateHandler(bundleName,
|
||||
(sslBundle) -> customizer.updateSslBundle(hostName, sslBundle));
|
||||
(sslBundle) -> customizer.updateSslBundle(serverName, sslBundle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,28 +76,28 @@ public class SslServerCustomizer implements NettyServerCustomizer {
|
||||
}
|
||||
|
||||
private void applySecurity(SslContextSpec spec) {
|
||||
spec.sslContext(this.sslProvider.getSslContext()).setSniAsyncMappings((domainName, promise) -> {
|
||||
SslProvider provider = (domainName != null) ? this.serverNameSslProviders.get(domainName)
|
||||
spec.sslContext(this.sslProvider.getSslContext()).setSniAsyncMappings((serverName, promise) -> {
|
||||
SslProvider provider = (serverName != null) ? this.serverNameSslProviders.get(serverName)
|
||||
: this.sslProvider;
|
||||
return promise.setSuccess(provider);
|
||||
});
|
||||
}
|
||||
|
||||
void updateSslBundle(String hostName, SslBundle sslBundle) {
|
||||
void updateSslBundle(String serverName, SslBundle sslBundle) {
|
||||
logger.debug("SSL Bundle has been updated, reloading SSL configuration");
|
||||
if (hostName == null) {
|
||||
if (serverName == null) {
|
||||
this.sslBundle = sslBundle;
|
||||
this.sslProvider = createSslProvider(sslBundle);
|
||||
}
|
||||
else {
|
||||
this.serverNameSslProviders.put(hostName, createSslProvider(sslBundle));
|
||||
this.serverNameSslProviders.put(serverName, createSslProvider(sslBundle));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, SslProvider> createServerNameSslProviders(Map<String, SslBundle> serverNameSslBundles) {
|
||||
Map<String, SslProvider> serverNameSslProviders = new HashMap<>();
|
||||
serverNameSslBundles
|
||||
.forEach((hostName, sslBundle) -> serverNameSslProviders.put(hostName, createSslProvider(sslBundle)));
|
||||
.forEach((serverName, sslBundle) -> serverNameSslProviders.put(serverName, createSslProvider(sslBundle)));
|
||||
return serverNameSslProviders;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,9 +58,9 @@ class SslConnectorCustomizer {
|
||||
this.connector = connector;
|
||||
}
|
||||
|
||||
void update(String hostName, SslBundle updatedSslBundle) {
|
||||
void update(String serverName, SslBundle updatedSslBundle) {
|
||||
AbstractHttp11JsseProtocol<?> protocol = (AbstractHttp11JsseProtocol<?>) this.connector.getProtocolHandler();
|
||||
String host = (hostName != null) ? hostName : protocol.getDefaultSSLHostConfigName();
|
||||
String host = (serverName != null) ? serverName : protocol.getDefaultSSLHostConfigName();
|
||||
this.logger.debug("SSL Bundle for host " + host + " has been updated, reloading SSL configuration");
|
||||
addSslHostConfig(protocol, host, updatedSslBundle);
|
||||
}
|
||||
@@ -86,12 +86,12 @@ class SslConnectorCustomizer {
|
||||
if (sslBundle != null) {
|
||||
addSslHostConfig(protocol, protocol.getDefaultSSLHostConfigName(), sslBundle);
|
||||
}
|
||||
serverNameSslBundles.forEach((hostName, bundle) -> addSslHostConfig(protocol, hostName, bundle));
|
||||
serverNameSslBundles.forEach((serverName, bundle) -> addSslHostConfig(protocol, serverName, bundle));
|
||||
}
|
||||
|
||||
private void addSslHostConfig(AbstractHttp11JsseProtocol<?> protocol, String hostName, SslBundle sslBundle) {
|
||||
private void addSslHostConfig(AbstractHttp11JsseProtocol<?> protocol, String serverName, SslBundle sslBundle) {
|
||||
SSLHostConfig sslHostConfig = new SSLHostConfig();
|
||||
sslHostConfig.setHostName(hostName);
|
||||
sslHostConfig.setHostName(serverName);
|
||||
configureSslClientAuth(sslHostConfig);
|
||||
applySslBundle(protocol, sslHostConfig, sslBundle);
|
||||
protocol.addSslHostConfig(sslHostConfig, true);
|
||||
|
||||
@@ -245,10 +245,10 @@ public class TomcatReactiveWebServerFactory extends AbstractReactiveWebServerFac
|
||||
serverNameSslBundle.bundle(), customizer));
|
||||
}
|
||||
|
||||
private void addBundleUpdateHandler(String hostName, String sslBundleName, SslConnectorCustomizer customizer) {
|
||||
private void addBundleUpdateHandler(String serverName, String sslBundleName, SslConnectorCustomizer customizer) {
|
||||
if (StringUtils.hasText(sslBundleName)) {
|
||||
getSslBundles().addBundleUpdateHandler(sslBundleName,
|
||||
(sslBundle) -> customizer.update(hostName, sslBundle));
|
||||
(sslBundle) -> customizer.update(serverName, sslBundle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -387,10 +387,10 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto
|
||||
serverNameSslBundle.bundle(), customizer));
|
||||
}
|
||||
|
||||
private void addBundleUpdateHandler(String hostName, String sslBundleName, SslConnectorCustomizer customizer) {
|
||||
private void addBundleUpdateHandler(String serverName, String sslBundleName, SslConnectorCustomizer customizer) {
|
||||
if (StringUtils.hasText(sslBundleName)) {
|
||||
getSslBundles().addBundleUpdateHandler(sslBundleName,
|
||||
(sslBundle) -> customizer.update(hostName, sslBundle));
|
||||
(sslBundle) -> customizer.update(serverName, sslBundle));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ class SslBuilderCustomizer implements UndertowBuilderCustomizer {
|
||||
SNIContextMatcher.Builder builder = new SNIContextMatcher.Builder();
|
||||
builder.setDefaultContext(this.sslBundle.createSslContext());
|
||||
this.serverNameSslBundles
|
||||
.forEach((server, sslBundle) -> builder.addMatch(server, sslBundle.createSslContext()));
|
||||
.forEach((serverName, sslBundle) -> builder.addMatch(serverName, sslBundle.createSslContext()));
|
||||
return new SNISSLContext(builder.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -338,8 +338,8 @@ public class Ssl {
|
||||
return this.serverNameBundles;
|
||||
}
|
||||
|
||||
public void setServerNameBundles(List<ServerNameSslBundle> serverNames) {
|
||||
this.serverNameBundles = serverNames;
|
||||
public void setServerNameBundles(List<ServerNameSslBundle> serverNameBundles) {
|
||||
this.serverNameBundles = serverNameBundles;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
@@ -295,7 +295,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
ssl.setServerNameBundles(bundles);
|
||||
JettyServletWebServerFactory factory = getFactory();
|
||||
factory.setSsl(ssl);
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.webServer = factory.getWebServer())
|
||||
assertThatIllegalStateException().isThrownBy(() -> this.webServer = factory.getWebServer())
|
||||
.withMessageContaining("Server name SSL bundles are not supported with Jetty");
|
||||
}
|
||||
|
||||
@@ -561,7 +561,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyMaxConnectionsToConnectors() throws Exception {
|
||||
void shouldApplyMaxConnectionsToConnectors() {
|
||||
JettyServletWebServerFactory factory = getFactory();
|
||||
factory.setMaxConnections(1);
|
||||
this.webServer = factory.getWebServer();
|
||||
|
||||
@@ -20,6 +20,6 @@ dependencies {
|
||||
testImplementation("org.testcontainers:junit-jupiter")
|
||||
testImplementation("org.testcontainers:postgresql")
|
||||
testImplementation("org.testcontainers:r2dbc")
|
||||
|
||||
|
||||
testRuntimeOnly("org.flywaydb:flyway-database-postgresql")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user