Skip to content

Commit 504e1b3

Browse files
committed
Hacking
1 parent 9b8ead8 commit 504e1b3

File tree

8 files changed

+188
-12
lines changed

8 files changed

+188
-12
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.apache.commons.logging.Log;
2626
import org.apache.commons.logging.LogFactory;
2727

28-
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
2928
import org.springframework.boot.jdbc.DataSourceBuilder;
3029
import org.springframework.boot.jdbc.DataSourceInitializationMode;
3130
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
@@ -148,27 +147,22 @@ private boolean isEmbedded() {
148147
private List<Resource> getScripts(String propertyName, List<String> resources,
149148
String fallback) {
150149
if (resources != null) {
151-
return getResources(propertyName, resources, true);
150+
return getResources(resources);
152151
}
153152
String platform = this.properties.getPlatform();
154153
List<String> fallbackResources = new ArrayList<>();
155154
fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
156155
fallbackResources.add("classpath*:" + fallback + ".sql");
157-
return getResources(propertyName, fallbackResources, false);
156+
return getResources(fallbackResources);
158157
}
159158

160-
private List<Resource> getResources(String propertyName, List<String> locations,
161-
boolean validate) {
159+
private List<Resource> getResources(List<String> locations) {
162160
List<Resource> resources = new ArrayList<>();
163161
for (String location : locations) {
164162
for (Resource resource : doGetResources(location)) {
165163
if (resource.exists()) {
166164
resources.add(resource);
167165
}
168-
else if (validate) {
169-
throw new InvalidConfigurationPropertyValueException(propertyName,
170-
resource, "The specified resource does not exist.");
171-
}
172166
}
173167
}
174168
return resources;

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import javax.sql.DataSource;
2626

27+
import org.springframework.beans.BeansException;
2728
import org.springframework.beans.factory.BeanClassLoaderAware;
2829
import org.springframework.beans.factory.BeanCreationException;
2930
import org.springframework.beans.factory.InitializingBean;
@@ -32,6 +33,9 @@
3233
import org.springframework.boot.jdbc.DataSourceInitializationMode;
3334
import org.springframework.boot.jdbc.DatabaseDriver;
3435
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
36+
import org.springframework.context.ApplicationContext;
37+
import org.springframework.context.ApplicationContextAware;
38+
import org.springframework.core.io.Resource;
3539
import org.springframework.util.Assert;
3640
import org.springframework.util.ClassUtils;
3741
import org.springframework.util.StringUtils;
@@ -47,7 +51,8 @@
4751
* @since 1.1.0
4852
*/
4953
@ConfigurationProperties(prefix = "spring.datasource")
50-
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
54+
public class DataSourceProperties
55+
implements BeanClassLoaderAware, InitializingBean, ApplicationContextAware {
5156

5257
private ClassLoader classLoader;
5358

@@ -155,6 +160,8 @@ public class DataSourceProperties implements BeanClassLoaderAware, InitializingB
155160

156161
private String uniqueName;
157162

163+
private ApplicationContext context;
164+
158165
@Override
159166
public void setBeanClassLoader(ClassLoader classLoader) {
160167
this.classLoader = classLoader;
@@ -399,6 +406,15 @@ public List<String> getSchema() {
399406
}
400407

401408
public void setSchema(List<String> schema) {
409+
if (schema != null) {
410+
for (String location : schema) {
411+
Resource resource = this.context.getResource(location);
412+
if (!resource.exists()) {
413+
throw new InvalidDataSourcePropertyValueException(
414+
resource, "The specified resource does not exist.");
415+
}
416+
}
417+
}
402418
this.schema = schema;
403419
}
404420

@@ -478,6 +494,12 @@ public void setXa(Xa xa) {
478494
this.xa = xa;
479495
}
480496

497+
@Override
498+
public void setApplicationContext(ApplicationContext applicationContext)
499+
throws BeansException {
500+
this.context = applicationContext;
501+
}
502+
481503
/**
482504
* XA Specific datasource settings.
483505
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2012-2018 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+
* http://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+
package org.springframework.boot.autoconfigure.jdbc;
17+
18+
import org.springframework.boot.context.properties.bind.PropertyValueValidationException;
19+
20+
/**
21+
* Error thrown when a datasource property value in invalid.
22+
*
23+
* @author Madhura Bhave
24+
*/
25+
class InvalidDataSourcePropertyValueException extends PropertyValueValidationException {
26+
27+
/**
28+
* Creates a new instance for the specified property {@code value}, including a
29+
* {@code reason} why the value is invalid.
30+
* @param value the value of the property, can be {@code null}
31+
* @param reason a human-readable text that describes why the reason is invalid.
32+
* Starts with an upper-case and ends with a dots. Several sentences and carriage
33+
*/
34+
public InvalidDataSourcePropertyValueException(Object value, String reason) {
35+
super(value, reason);
36+
}
37+
38+
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourcePropertiesTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616

1717
package org.springframework.boot.autoconfigure.jdbc;
1818

19+
import java.util.Collections;
20+
1921
import org.junit.Rule;
2022
import org.junit.Test;
2123
import org.junit.rules.ExpectedException;
2224

2325
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
2426
import org.springframework.boot.test.context.FilteredClassLoader;
27+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2528

2629
import static org.assertj.core.api.Assertions.assertThat;
30+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
2731

2832
/**
2933
* Tests for {@link DataSourceProperties}.
@@ -150,4 +154,13 @@ public void determineCredentialsForDataScripts() {
150154
assertThat(properties.getDataPassword()).isEqualTo("bar");
151155
}
152156

157+
@Test
158+
public void invalidSchemaLocationThrowsException() {
159+
DataSourceProperties properties = new DataSourceProperties();
160+
properties.setApplicationContext(new AnnotationConfigApplicationContext());
161+
assertThatExceptionOfType(InvalidDataSourcePropertyValueException.class)
162+
.isThrownBy(() -> properties
163+
.setSchema(Collections.singletonList("does-not-exist")));
164+
}
165+
153166
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver;
2828
import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler;
2929
import org.springframework.boot.context.properties.bind.handler.IgnoreTopLevelConverterNotFoundBindHandler;
30+
import org.springframework.boot.context.properties.bind.handler.InvalidConfigurationPropertyValueBindHandler;
3031
import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler;
3132
import org.springframework.boot.context.properties.bind.validation.ValidationBindHandler;
3233
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
@@ -114,7 +115,8 @@ private Validator getJsr303Validator() {
114115

115116
private BindHandler getBindHandler(ConfigurationProperties annotation,
116117
List<Validator> validators) {
117-
BindHandler handler = new IgnoreTopLevelConverterNotFoundBindHandler();
118+
BindHandler parent = new IgnoreTopLevelConverterNotFoundBindHandler();
119+
BindHandler handler = new InvalidConfigurationPropertyValueBindHandler(parent);
118120
if (annotation.ignoreInvalidFields()) {
119121
handler = new IgnoreErrorsBindHandler(handler);
120122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2012-2018 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+
* http://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+
package org.springframework.boot.context.properties.bind;
17+
18+
/**
19+
* Error thrown when a configuration property value fails validation.
20+
*
21+
* @author Madhura Bhave
22+
* @since 2.0.0
23+
*/
24+
public class PropertyValueValidationException extends RuntimeException {
25+
26+
private final Object value;
27+
28+
private final String reason;
29+
30+
public PropertyValueValidationException(Object value, String reason) {
31+
this.value = value;
32+
this.reason = reason;
33+
}
34+
35+
public Object getValue() {
36+
return this.value;
37+
}
38+
39+
public String getReason() {
40+
return this.reason;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2012-2018 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+
* http://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+
package org.springframework.boot.context.properties.bind.handler;
17+
18+
import org.springframework.boot.context.properties.bind.AbstractBindHandler;
19+
import org.springframework.boot.context.properties.bind.BindContext;
20+
import org.springframework.boot.context.properties.bind.BindHandler;
21+
import org.springframework.boot.context.properties.bind.Bindable;
22+
import org.springframework.boot.context.properties.bind.PropertyValueValidationException;
23+
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
24+
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
25+
26+
/**
27+
* {@link BindHandler} that can be used to convert
28+
* {@link PropertyValueValidationException} to
29+
* {@link InvalidConfigurationPropertyValueException}.
30+
*
31+
* @author Madhura Bhave
32+
*/
33+
public class InvalidConfigurationPropertyValueBindHandler extends AbstractBindHandler {
34+
35+
/**
36+
* Create a new {@link InvalidConfigurationPropertyValueBindHandler} instance with a
37+
* specific parent.
38+
* @param parent the parent handler
39+
*/
40+
public InvalidConfigurationPropertyValueBindHandler(BindHandler parent) {
41+
super(parent);
42+
}
43+
44+
@Override
45+
public Object onFailure(ConfigurationPropertyName name, Bindable<?> target,
46+
BindContext context, Exception error) throws Exception {
47+
PropertyValueValidationException ex = hasCause(error);
48+
if (ex != null) {
49+
throw new InvalidConfigurationPropertyValueException(name.toString(),
50+
ex.getValue(), ex.getReason());
51+
}
52+
throw error;
53+
}
54+
55+
private PropertyValueValidationException hasCause(Throwable failure) {
56+
while (failure != null) {
57+
if (PropertyValueValidationException.class.isInstance(failure)) {
58+
return (PropertyValueValidationException) failure;
59+
}
60+
failure = failure.getCause();
61+
}
62+
return null;
63+
}
64+
65+
}

spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/SampleJpaApplication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
public class SampleJpaApplication {
2424

2525
public static void main(String[] args) {
26-
SpringApplication.run(SampleJpaApplication.class, args);
26+
SpringApplication.run(SampleJpaApplication.class, "--app.datasource.schema=classpath:does-not-exist.sql");
2727
}
2828

2929
}

0 commit comments

Comments
 (0)