Introduce EndpointID to enforce naming rules
Add an `EndpointID` class to enforce the naming rules that we support for actuator endpoints. We now ensure that all endpoint names contain only letters and numbers and must begin with a lower-case letter. Existing public classes and interfaces have been changes so that String based `endpointId` methods are deprecated and strongly typed versions are preferred instead. A few public classes that we're not expecting to be used directly have been changed without deprecated methods being introduced. See gh-14773pull/14914/head
parent
c5786c218d
commit
3105a38884
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2018 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.actuate.endpoint;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An identifier for an actuator endpoint. Endpoint IDs may contain only letters and
|
||||||
|
* numbers and must begin with a lower-case letter. Case is ignored when comparing
|
||||||
|
* endpoint IDs.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @since 2.0.6
|
||||||
|
*/
|
||||||
|
public final class EndpointId {
|
||||||
|
|
||||||
|
private static final Pattern ALPHA_NUMERIC = Pattern.compile("[a-zA-Z0-9]+");
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private final String lowerCaseValue;
|
||||||
|
|
||||||
|
private EndpointId(String value) {
|
||||||
|
Assert.hasText(value, "Value must not be empty");
|
||||||
|
Assert.isTrue(ALPHA_NUMERIC.matcher(value).matches(),
|
||||||
|
"Value must be alpha-numeric");
|
||||||
|
Assert.isTrue(!Character.isDigit(value.charAt(0)),
|
||||||
|
"Value must not start with a number");
|
||||||
|
Assert.isTrue(!Character.isUpperCase(value.charAt(0)),
|
||||||
|
"Value must not start with an uppercase letter");
|
||||||
|
this.value = value;
|
||||||
|
this.lowerCaseValue = value.toLowerCase(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null || getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return toLowerCaseString().equals(((EndpointId) obj).toLowerCaseString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return toLowerCaseString().hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a lower-case version of the endpoint ID.
|
||||||
|
* @return the lower-case endpoint ID
|
||||||
|
*/
|
||||||
|
public String toLowerCaseString() {
|
||||||
|
return this.lowerCaseValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method to create a new {@link EndpointId} of the specified value.
|
||||||
|
* @param value the endpoint ID value
|
||||||
|
* @return an {@link EndpointId} instance
|
||||||
|
*/
|
||||||
|
public static EndpointId of(String value) {
|
||||||
|
return new EndpointId(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2018 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.actuate.endpoint;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link EndpointId}.
|
||||||
|
*
|
||||||
|
* @author Phillip Webb
|
||||||
|
*/
|
||||||
|
public class EndpointIdTests {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ofWhenNullThorowsException() {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Value must not be empty");
|
||||||
|
EndpointId.of(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ofWhenEmptyThrowsException() {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Value must not be empty");
|
||||||
|
EndpointId.of("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ofWhenContainsDashThrowsException() {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Value must be alpha-numeric");
|
||||||
|
EndpointId.of("foo-bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ofWhenHasBadCharThrowsException() {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Value must be alpha-numeric");
|
||||||
|
EndpointId.of("foo!bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ofWhenStartsWithNumberThrowsException() {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Value must not start with a number");
|
||||||
|
EndpointId.of("1foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ofWhenStartsWithUppercaseLetterThrowsException() {
|
||||||
|
this.thrown.expect(IllegalArgumentException.class);
|
||||||
|
this.thrown.expectMessage("Value must not start with an uppercase letter");
|
||||||
|
EndpointId.of("Foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void equalsAndHashCode() {
|
||||||
|
EndpointId one = EndpointId.of("foobar");
|
||||||
|
EndpointId two = EndpointId.of("fooBar");
|
||||||
|
EndpointId three = EndpointId.of("barfoo");
|
||||||
|
assertThat(one.hashCode()).isEqualTo(two.hashCode());
|
||||||
|
assertThat(one).isEqualTo(one).isEqualTo(two).isNotEqualTo(three);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toLowerCaseStringReturnsLowercase() {
|
||||||
|
assertThat(EndpointId.of("fooBar").toLowerCaseString()).isEqualTo("foobar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void toStringReturnsString() {
|
||||||
|
assertThat(EndpointId.of("fooBar").toString()).isEqualTo("fooBar");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue