Skip to content

Commit 09c0714

Browse files
Register ProtocolResolvers with the application context by default
Any ProtocolResolvers that are registered in a spring.factories file will be added to the application context using an ApplicationContextInitializer. Closes gh-41433
1 parent a349170 commit 09c0714

File tree

5 files changed

+172
-3
lines changed

5 files changed

+172
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.io;
18+
19+
import java.util.List;
20+
21+
import org.springframework.context.ApplicationContextInitializer;
22+
import org.springframework.context.ConfigurableApplicationContext;
23+
import org.springframework.core.io.ProtocolResolver;
24+
import org.springframework.core.io.support.SpringFactoriesLoader;
25+
26+
/**
27+
* {@link ApplicationContextInitializer} that adds all {@link ProtocolResolver}s
28+
* registered in a {@code spring.factories} file.
29+
*
30+
* @author Scott Frederick
31+
*/
32+
class ProtocolResolverApplicationContextInitializer
33+
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
34+
35+
@Override
36+
public void initialize(ConfigurableApplicationContext applicationContext) {
37+
SpringFactoriesLoader loader = SpringFactoriesLoader
38+
.forDefaultResourceLocation(applicationContext.getClassLoader());
39+
List<ProtocolResolver> protocolResolvers = loader.load(ProtocolResolver.class);
40+
protocolResolvers.forEach(applicationContext::addProtocolResolver);
41+
}
42+
43+
}

spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ org.springframework.boot.diagnostics.FailureAnalyzers
3636
org.springframework.context.ApplicationContextInitializer=\
3737
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
3838
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
39+
org.springframework.boot.io.ProtocolResolverApplicationContextInitializer,\
3940
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\
4041
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
4142

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/builder/SpringApplicationBuilderTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ void initializersCreatedOnce() {
265265
SpringApplicationBuilder application = new SpringApplicationBuilder(ExampleConfig.class)
266266
.web(WebApplicationType.NONE);
267267
this.context = application.run();
268-
assertThat(application.application().getInitializers()).hasSize(4);
268+
assertThat(application.application().getInitializers()).hasSize(5);
269269
}
270270

271271
@Test
@@ -274,7 +274,7 @@ void initializersCreatedOnceForChild() {
274274
.child(ChildConfig.class)
275275
.web(WebApplicationType.NONE);
276276
this.context = application.run();
277-
assertThat(application.application().getInitializers()).hasSize(5);
277+
assertThat(application.application().getInitializers()).hasSize(6);
278278
}
279279

280280
@Test
@@ -284,7 +284,7 @@ void initializersIncludeDefaults() {
284284
.initializers((ConfigurableApplicationContext applicationContext) -> {
285285
});
286286
this.context = application.run();
287-
assertThat(application.application().getInitializers()).hasSize(5);
287+
assertThat(application.application().getInitializers()).hasSize(6);
288288
}
289289

290290
@Test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.io;
18+
19+
import java.io.IOException;
20+
import java.nio.charset.Charset;
21+
import java.util.Map;
22+
23+
import org.junit.jupiter.api.Test;
24+
25+
import org.springframework.boot.SpringApplication;
26+
import org.springframework.boot.WebApplicationType;
27+
import org.springframework.boot.context.properties.ConfigurationProperties;
28+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
29+
import org.springframework.context.ConfigurableApplicationContext;
30+
import org.springframework.context.annotation.Configuration;
31+
import org.springframework.core.io.Resource;
32+
33+
import static org.assertj.core.api.Assertions.assertThat;
34+
35+
/**
36+
* Integration tests for resolving configuration properties using
37+
* {@code ProtocolResolver}s.
38+
*
39+
* @author Scott Frederick
40+
*/
41+
class ProtocolResolverApplicationContextInitializerIntegrationTests {
42+
43+
@Test
44+
void base64ResourceResolves() throws IOException {
45+
SpringApplication application = new SpringApplication(TestConfiguration.class);
46+
application.setDefaultProperties(Map.of("test.resource", "base64:dGVzdC12YWx1ZQ=="));
47+
application.setWebApplicationType(WebApplicationType.NONE);
48+
ConfigurableApplicationContext context = application.run();
49+
TestProperties propertiesBean = context.getBean(TestProperties.class);
50+
Resource resource = propertiesBean.getResource();
51+
assertThat(resource).isNotNull();
52+
assertThat(resource.exists()).isTrue();
53+
assertThat(resource.getContentAsString(Charset.defaultCharset())).isEqualTo("test-value");
54+
}
55+
56+
@Configuration(proxyBeanMethods = false)
57+
@EnableConfigurationProperties(TestProperties.class)
58+
static class TestConfiguration {
59+
60+
}
61+
62+
@ConfigurationProperties(prefix = "test")
63+
static class TestProperties {
64+
65+
Resource resource;
66+
67+
Resource getResource() {
68+
return this.resource;
69+
}
70+
71+
void setResource(Resource resource) {
72+
this.resource = resource;
73+
}
74+
75+
}
76+
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.io;
18+
19+
import java.util.Collection;
20+
21+
import org.junit.jupiter.api.Test;
22+
23+
import org.springframework.context.ConfigurableApplicationContext;
24+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
25+
import org.springframework.core.io.DefaultResourceLoader;
26+
import org.springframework.core.io.ProtocolResolver;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
30+
/**
31+
* Tests for {@link ProtocolResolverApplicationContextInitializer}.
32+
*
33+
* @author Scott Frederick
34+
*/
35+
class ProtocolResolverApplicationContextInitializerTests {
36+
37+
@Test
38+
void initializeAddsProtocolResolversToApplicationContext() {
39+
try (ConfigurableApplicationContext context = new AnnotationConfigApplicationContext()) {
40+
ProtocolResolverApplicationContextInitializer initializer = new ProtocolResolverApplicationContextInitializer();
41+
initializer.initialize(context);
42+
assertThat(context).isInstanceOf(DefaultResourceLoader.class);
43+
Collection<ProtocolResolver> protocolResolvers = ((DefaultResourceLoader) context).getProtocolResolvers();
44+
assertThat(protocolResolvers).hasExactlyElementsOfTypes(Base64ProtocolResolver.class);
45+
}
46+
}
47+
48+
}

0 commit comments

Comments
 (0)