Add OriginCapablePropertySource interfaces
Add `OriginCapablePropertySource` interface and supporting classes so that `PropertySource` implementations can reveal the source of any given property. The `TextResourcePropertyOrigin` can be used for sources that load values from a text `Resource` and can track line/column numbers. See gh-8517 See gh-8142pull/8526/head
parent
2136a39004
commit
43a54c8db1
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.env;
|
||||||
|
|
||||||
|
import org.springframework.core.env.PropertySource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An additional interface that may be implemented by a {@link PropertySource} that can
|
||||||
|
* return origin information. For example a property source that's backed by a file may
|
||||||
|
* return origin information for line and column numbers.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public interface OriginCapablePropertySource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the origin of the given property name or {@code null} if the origin cannot
|
||||||
|
* be determined.
|
||||||
|
* @param name the property name
|
||||||
|
* @return the origin of the property or {@code null}
|
||||||
|
*/
|
||||||
|
PropertyOrigin getPropertyOrigin(String name);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.env;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface that uniquely represents the origin of a property. For example, a property
|
||||||
|
* loaded from a {@link File} may have an origin made up of the file name along with
|
||||||
|
* line/column numbers.
|
||||||
|
* <p>
|
||||||
|
* Implementations must provide sensible {@link #hashCode()}, {@link #equals(Object)} and
|
||||||
|
* {@link #toString()} implementations.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public interface PropertyOrigin {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.env;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link PropertyOrigin} for an item loaded from a text resource. Provides access to the
|
||||||
|
* origina {@link Resource} that loaded the text and a {@link Location} within it.
|
||||||
|
*
|
||||||
|
* @author Madhura Bhave
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public class TextResourcePropertyOrigin implements PropertyOrigin {
|
||||||
|
|
||||||
|
private final Resource resource;
|
||||||
|
|
||||||
|
private final Location location;
|
||||||
|
|
||||||
|
public TextResourcePropertyOrigin(Resource resource, Location location) {
|
||||||
|
this.resource = resource;
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the resource where the property originated.
|
||||||
|
* @return the resource the text resource or {@code null}
|
||||||
|
*/
|
||||||
|
public Resource getResource() {
|
||||||
|
return this.resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the location of the property within the source (if known).
|
||||||
|
* @return the location or {@code null}
|
||||||
|
*/
|
||||||
|
public Location getLocation() {
|
||||||
|
return this.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = 1;
|
||||||
|
result = 31 * result + ObjectUtils.nullSafeHashCode(this.resource);
|
||||||
|
result = 31 * result + ObjectUtils.nullSafeHashCode(this.location);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (obj instanceof TextResourcePropertyOrigin) {
|
||||||
|
TextResourcePropertyOrigin other = (TextResourcePropertyOrigin) obj;
|
||||||
|
boolean result = true;
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.resource, other.resource);
|
||||||
|
result = result && ObjectUtils.nullSafeEquals(this.location, other.location);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return super.equals(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
result.append(this.resource == null ? "unknown resource [?]"
|
||||||
|
: this.resource.getDescription());
|
||||||
|
if (this.location != null) {
|
||||||
|
result.append(":" + this.location);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A location (line and column number) within the resource.
|
||||||
|
*/
|
||||||
|
public final static class Location {
|
||||||
|
|
||||||
|
private final int line;
|
||||||
|
|
||||||
|
private final int column;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link Location} instance.
|
||||||
|
* @param line the line number (zero indexed)
|
||||||
|
* @param column the column number (zero indexed)
|
||||||
|
*/
|
||||||
|
public Location(int line, int column) {
|
||||||
|
this.line = line;
|
||||||
|
this.column = column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the line of the text resource where the property originated.
|
||||||
|
* @return the line number (zero indexed)
|
||||||
|
*/
|
||||||
|
public int getLine() {
|
||||||
|
return this.line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the column of the text resource where the property originated.
|
||||||
|
* @return the column number (zero indexed)
|
||||||
|
*/
|
||||||
|
public int getColumn() {
|
||||||
|
return this.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (31 * this.line) + this.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Location other = (Location) obj;
|
||||||
|
boolean result = true;
|
||||||
|
result = result && this.line == other.line;
|
||||||
|
result = result && this.column == other.column;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (this.line + 1) + ":" + (this.column + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2017 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
|
||||||
|
*
|
||||||
|
* http://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.env;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.env.TextResourcePropertyOrigin.Location;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link TextResourcePropertyOrigin}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class TextResourcePropertyOriginTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createWithNullResourceShouldSetNullResource() throws Exception {
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(null, null);
|
||||||
|
assertThat(origin.getResource()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createWithNullLocationShouldSetNullLocation() throws Exception {
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(null, null);
|
||||||
|
assertThat(origin.getLocation()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getResourceShouldReturnResource() throws Exception {
|
||||||
|
ClassPathResource resource = new ClassPathResource("foo.txt");
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(resource,
|
||||||
|
null);
|
||||||
|
assertThat(origin.getResource()).isEqualTo(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getLocationShouldReturnLocation() throws Exception {
|
||||||
|
Location location = new Location(1, 2);
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(null,
|
||||||
|
location);
|
||||||
|
assertThat(origin.getLocation()).isEqualTo(location);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getLocationLineShouldReturnLine() throws Exception {
|
||||||
|
Location location = new Location(1, 2);
|
||||||
|
assertThat(location.getLine()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getLocationColumnShouldReturnColumn() throws Exception {
|
||||||
|
Location location = new Location(1, 2);
|
||||||
|
assertThat(location.getColumn()).isEqualTo(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void locationToStringShouldReturnNiceString() throws Exception {
|
||||||
|
Location location = new Location(1, 2);
|
||||||
|
assertThat(location.toString()).isEqualTo("2:3");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toStringShouldReturnNiceString() throws Exception {
|
||||||
|
ClassPathResource resource = new ClassPathResource("foo.txt");
|
||||||
|
Location location = new Location(1, 2);
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(resource,
|
||||||
|
location);
|
||||||
|
assertThat(origin.toString()).isEqualTo("class path resource [foo.txt]:2:3");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toStringWhenResourceIsNullShouldReturnNiceString() throws Exception {
|
||||||
|
Location location = new Location(1, 2);
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(null,
|
||||||
|
location);
|
||||||
|
assertThat(origin.toString()).isEqualTo("unknown resource [?]:2:3");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toStringWhenLocationIsNullShouldReturnNiceString() throws Exception {
|
||||||
|
ClassPathResource resource = new ClassPathResource("foo.txt");
|
||||||
|
TextResourcePropertyOrigin origin = new TextResourcePropertyOrigin(resource,
|
||||||
|
null);
|
||||||
|
assertThat(origin.toString()).isEqualTo("class path resource [foo.txt]");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void locationEqualsAndHashcodeShouldUseLineAndColumn() throws Exception {
|
||||||
|
Location location1 = new Location(1, 2);
|
||||||
|
Location location2 = new Location(1, 2);
|
||||||
|
Location location3 = new Location(2, 2);
|
||||||
|
assertThat(location1.hashCode()).isEqualTo(location1.hashCode());
|
||||||
|
assertThat(location1.hashCode()).isEqualTo(location2.hashCode());
|
||||||
|
assertThat(location1).isEqualTo(location1);
|
||||||
|
assertThat(location1).isEqualTo(location2);
|
||||||
|
assertThat(location1).isNotEqualTo(location3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void equalsAndHashCodeShouldResourceAndLocation() throws Exception {
|
||||||
|
TextResourcePropertyOrigin origin1 = new TextResourcePropertyOrigin(
|
||||||
|
new ClassPathResource("foo.txt"), new Location(1, 2));
|
||||||
|
TextResourcePropertyOrigin origin2 = new TextResourcePropertyOrigin(
|
||||||
|
new ClassPathResource("foo.txt"), new Location(1, 2));
|
||||||
|
TextResourcePropertyOrigin origin3 = new TextResourcePropertyOrigin(
|
||||||
|
new ClassPathResource("foo.txt"), new Location(2, 2));
|
||||||
|
TextResourcePropertyOrigin origin4 = new TextResourcePropertyOrigin(
|
||||||
|
new ClassPathResource("foo2.txt"), new Location(1, 2));
|
||||||
|
assertThat(origin1.hashCode()).isEqualTo(origin1.hashCode());
|
||||||
|
assertThat(origin1.hashCode()).isEqualTo(origin2.hashCode());
|
||||||
|
assertThat(origin1).isEqualTo(origin1);
|
||||||
|
assertThat(origin1).isEqualTo(origin2);
|
||||||
|
assertThat(origin1).isNotEqualTo(origin3);
|
||||||
|
assertThat(origin1).isNotEqualTo(origin4);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue