Use consistent class design

Update all classes so that inner classes are always last. Also
ensure that utility classes are always final and have a private
constructor and make exceptions final whenever possible.

Issue: SPR-16968
This commit is contained in:
Phillip Webb
2018-06-20 19:44:39 -07:00
committed by Juergen Hoeller
parent 0ad0f341bd
commit eeebd51f57
128 changed files with 656 additions and 455 deletions

View File

@@ -39,7 +39,7 @@ import static java.time.format.DateTimeFormatter.*;
* @since 5.0
* @see <a href="https://tools.ietf.org/html/rfc2183">RFC 2183</a>
*/
public class ContentDisposition {
public final class ContentDisposition {
@Nullable
private final String type;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-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.
@@ -28,7 +28,7 @@ import org.springframework.util.InvalidMimeTypeException;
@SuppressWarnings("serial")
public class InvalidMediaTypeException extends IllegalArgumentException {
private String mediaType;
private final String mediaType;
/**

View File

@@ -40,13 +40,17 @@ import org.springframework.util.StringUtils;
* @author Arjen Poutsma
* @since 5.0
*/
public class MediaTypeFactory {
public final class MediaTypeFactory {
private static final String MIME_TYPES_FILE_NAME = "/org/springframework/http/mime.types";
private static final MultiValueMap<String, MediaType> fileExtensionToMediaTypes = parseMimeTypes();
private MediaTypeFactory() {
}
/**
* Parse the {@code mime.types} file found in the resources. Format is:
* <code>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-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.
@@ -36,7 +36,7 @@ import org.springframework.util.ClassUtils;
* @see ClientCodecConfigurer#create()
* @see ServerCodecConfigurer#create()
*/
class CodecConfigurerFactory {
final class CodecConfigurerFactory {
private static final String DEFAULT_CONFIGURERS_PATH = "CodecConfigurer.properties";
@@ -59,6 +59,10 @@ class CodecConfigurerFactory {
}
private CodecConfigurerFactory() {
}
@SuppressWarnings("unchecked")
public static <T extends CodecConfigurer> T create(Class<T> ifc) {
Class<?> impl = defaultCodecConfigurers.get(ifc);

View File

@@ -32,7 +32,7 @@ import org.springframework.lang.Nullable;
* @see ServerSentEventHttpMessageWriter
* @see <a href="https://www.w3.org/TR/eventsource/">Server-Sent Events W3C recommendation</a>
*/
public class ServerSentEvent<T> {
public final class ServerSentEvent<T> {
@Nullable
private final String id;

View File

@@ -42,7 +42,7 @@ import org.springframework.util.Assert;
* @author Arjen Poutsma
* @since 5.0
*/
class Jackson2Tokenizer {
final class Jackson2Tokenizer {
private final JsonParser parser;

View File

@@ -36,7 +36,7 @@ import org.springframework.util.StringUtils;
* @author Rossen Stoyanchev
* @since 5.0
*/
class DefaultPathContainer implements PathContainer {
final class DefaultPathContainer implements PathContainer {
private static final MultiValueMap<String, String> EMPTY_MAP = new LinkedMultiValueMap<>(0);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-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.
@@ -37,10 +37,10 @@ import org.springframework.util.StringUtils;
@SuppressWarnings("serial")
public class HttpRequestMethodNotSupportedException extends ServletException {
private String method;
private final String method;
@Nullable
private String[] supportedMethods;
private final String[] supportedMethods;
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-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.
@@ -30,7 +30,7 @@ import org.springframework.lang.Nullable;
public class HttpSessionRequiredException extends ServletException {
@Nullable
private String expectedAttribute;
private final String expectedAttribute;
/**
@@ -39,6 +39,7 @@ public class HttpSessionRequiredException extends ServletException {
*/
public HttpSessionRequiredException(String msg) {
super(msg);
this.expectedAttribute = null;
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-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.
@@ -30,7 +30,7 @@ import org.springframework.web.util.WebUtils;
* @author Rossen Stoyanchev
* @since 4.3.10
*/
class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper {
final class RelativeRedirectResponseWrapper extends HttpServletResponseWrapper {
private final HttpStatus redirectStatus;

View File

@@ -46,7 +46,7 @@ import org.springframework.util.StringUtils;
* @author Rossen Stoyanchev
* @since 5.1
*/
public class HandlerTypePredicate implements Predicate<Class<?>> {
public final class HandlerTypePredicate implements Predicate<Class<?>> {
private final Set<String> basePackages;

View File

@@ -71,7 +71,7 @@ public abstract class AbstractCookieValueMethodArgumentResolver extends Abstract
}
private static class CookieValueNamedValueInfo extends NamedValueInfo {
private static final class CookieValueNamedValueInfo extends NamedValueInfo {
private CookieValueNamedValueInfo(CookieValue annotation) {
super(annotation.name(), annotation.required(), annotation.defaultValue());

View File

@@ -77,7 +77,7 @@ public class ExpressionValueMethodArgumentResolver extends AbstractNamedValueMet
}
private static class ExpressionValueNamedValueInfo extends NamedValueInfo {
private static final class ExpressionValueNamedValueInfo extends NamedValueInfo {
private ExpressionValueNamedValueInfo(Value annotation) {
super("@Value", false, annotation.value());

View File

@@ -88,7 +88,7 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
}
private static class RequestHeaderNamedValueInfo extends NamedValueInfo {
private static final class RequestHeaderNamedValueInfo extends NamedValueInfo {
private RequestHeaderNamedValueInfo(RequestHeader annotation) {
super(annotation.name(), annotation.required(), annotation.defaultValue());

View File

@@ -62,7 +62,7 @@ import org.springframework.web.server.session.WebSessionManager;
* @since 5.0
* @see HttpWebHandlerAdapter
*/
public class WebHttpHandlerBuilder {
public final class WebHttpHandlerBuilder {
/** Well-known name for the target WebHandler in the bean factory. */
public static final String WEB_HANDLER_BEAN_NAME = "webHandler";

View File

@@ -53,6 +53,50 @@ final class HierarchicalUriComponents extends UriComponents {
private static final String PATH_DELIMITER_STRING = "/";
/**
* Represents an empty path.
*/
static final PathComponent NULL_PATH_COMPONENT = new PathComponent() {
@Override
public String getPath() {
return "";
}
@Override
public List<String> getPathSegments() {
return Collections.emptyList();
}
@Override
public PathComponent encode(Charset charset) {
return this;
}
@Override
public void verify() {
}
@Override
public PathComponent expand(UriTemplateVariables uriVariables) {
return this;
}
@Override
public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
}
@Override
public boolean equals(Object obj) {
return (this == obj);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
};
@Nullable
private final String userInfo;
@@ -862,43 +906,6 @@ final class HierarchicalUriComponents extends UriComponents {
}
/**
* Represents an empty path.
*/
static final PathComponent NULL_PATH_COMPONENT = new PathComponent() {
@Override
public String getPath() {
return "";
}
@Override
public List<String> getPathSegments() {
return Collections.emptyList();
}
@Override
public PathComponent encode(Charset charset) {
return this;
}
@Override
public void verify() {
}
@Override
public PathComponent expand(UriTemplateVariables uriVariables) {
return this;
}
@Override
public void copyToUriComponentsBuilder(UriComponentsBuilder builder) {
}
@Override
public boolean equals(Object obj) {
return (this == obj);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
};
private static class QueryUriTemplateVariables implements UriTemplateVariables {
private final UriTemplateVariables delegate;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-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.
@@ -29,7 +29,12 @@ package org.springframework.web.util;
* @author Rossen Stoyanchev
* @since 1.1.1
*/
public class JavaScriptUtils {
public final class JavaScriptUtils {
private JavaScriptUtils() {
}
/**
* Turn JavaScript special characters into escaped characters.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-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.
@@ -170,7 +170,7 @@ public class UriTemplate implements Serializable {
/**
* Helper to extract variable names and regex for matching to actual URLs.
*/
private static class TemplateInfo {
private static final class TemplateInfo {
private final List<String> variableNames;

View File

@@ -73,6 +73,25 @@ public class PathPattern implements Comparable<PathPattern> {
private static final PathContainer EMPTY_PATH = PathContainer.parsePath("");
/**
* Comparator that sorts patterns by specificity as follows:
* <ol>
* <li>Null instances are last.
* <li>Catch-all patterns are last.
* <li>If both patterns are catch-all, consider the length (longer wins).
* <li>Compare wildcard and captured variable count (lower wins).
* <li>Consider length (longer wins)
* </ol>
*/
public static final Comparator<PathPattern> SPECIFICITY_COMPARATOR =
Comparator.nullsLast(
Comparator.<PathPattern>
comparingInt(p -> p.isCatchAll() ? 1 : 0)
.thenComparingInt(p -> p.isCatchAll() ? scoreByNormalizedLength(p) : 0)
.thenComparingInt(PathPattern::getScore)
.thenComparingInt(PathPattern::scoreByNormalizedLength)
);
/** The text of the parsed pattern. */
private final String patternString;
@@ -408,97 +427,6 @@ public class PathPattern implements Comparable<PathPattern> {
return this.patternString;
}
/**
* Holder for URI variables and path parameters (matrix variables) extracted
* based on the pattern for a given matched path.
*/
public static class PathMatchInfo {
private static final PathMatchInfo EMPTY =
new PathMatchInfo(Collections.emptyMap(), Collections.emptyMap());
private final Map<String, String> uriVariables;
private final Map<String, MultiValueMap<String, String>> matrixVariables;
PathMatchInfo(Map<String, String> uriVars,
@Nullable Map<String, MultiValueMap<String, String>> matrixVars) {
this.uriVariables = Collections.unmodifiableMap(uriVars);
this.matrixVariables = matrixVars != null ?
Collections.unmodifiableMap(matrixVars) : Collections.emptyMap();
}
/**
* Return the extracted URI variables.
*/
public Map<String, String> getUriVariables() {
return this.uriVariables;
}
/**
* Return maps of matrix variables per path segment, keyed off by URI
* variable name.
*/
public Map<String, MultiValueMap<String, String>> getMatrixVariables() {
return this.matrixVariables;
}
@Override
public String toString() {
return "PathMatchInfo[uriVariables=" + this.uriVariables + ", " +
"matrixVariables=" + this.matrixVariables + "]";
}
}
/**
* Holder for the result of a match on the start of a pattern.
* Provides access to the remaining path not matched to the pattern as well
* as any variables bound in that first part that was matched.
*/
public static class PathRemainingMatchInfo {
private final PathContainer pathRemaining;
private final PathMatchInfo pathMatchInfo;
PathRemainingMatchInfo(PathContainer pathRemaining) {
this(pathRemaining, PathMatchInfo.EMPTY);
}
PathRemainingMatchInfo(PathContainer pathRemaining, PathMatchInfo pathMatchInfo) {
this.pathRemaining = pathRemaining;
this.pathMatchInfo = pathMatchInfo;
}
/**
* Return the part of a path that was not matched by a pattern.
*/
public PathContainer getPathRemaining() {
return this.pathRemaining;
}
/**
* Return variables that were bound in the part of the path that was
* successfully matched or an empty map.
*/
public Map<String, String> getUriVariables() {
return this.pathMatchInfo.getUriVariables();
}
/**
* Return the path parameters for each bound variable.
*/
public Map<String, MultiValueMap<String, String>> getMatrixVariables() {
return this.pathMatchInfo.getMatrixVariables();
}
}
int getScore() {
return this.score;
}
@@ -554,6 +482,138 @@ public class PathPattern implements Comparable<PathPattern> {
return this.head;
}
/**
* Join two paths together including a separator if necessary.
* Extraneous separators are removed (if the first path
* ends with one and the second path starts with one).
* @param path1 first path
* @param path2 second path
* @return joined path that may include separator if necessary
*/
private String concat(String path1, String path2) {
boolean path1EndsWithSeparator = (path1.charAt(path1.length() - 1) == this.separator);
boolean path2StartsWithSeparator = (path2.charAt(0) == this.separator);
if (path1EndsWithSeparator && path2StartsWithSeparator) {
return path1 + path2.substring(1);
}
else if (path1EndsWithSeparator || path2StartsWithSeparator) {
return path1 + path2;
}
else {
return path1 + this.separator + path2;
}
}
/**
* Return if the container is not null and has more than zero elements.
* @param container a path container
* @return {@code true} has more than zero elements
*/
private boolean hasLength(@Nullable PathContainer container) {
return container != null && container.elements().size() > 0;
}
private static int scoreByNormalizedLength(PathPattern pattern) {
return -pattern.getNormalizedLength();
}
private boolean pathContainerIsJustSeparator(PathContainer pathContainer) {
return pathContainer.value().length() == 1 &&
pathContainer.value().charAt(0) == separator;
}
/**
* Holder for URI variables and path parameters (matrix variables) extracted
* based on the pattern for a given matched path.
*/
public static class PathMatchInfo {
private static final PathMatchInfo EMPTY =
new PathMatchInfo(Collections.emptyMap(), Collections.emptyMap());
private final Map<String, String> uriVariables;
private final Map<String, MultiValueMap<String, String>> matrixVariables;
PathMatchInfo(Map<String, String> uriVars,
@Nullable Map<String, MultiValueMap<String, String>> matrixVars) {
this.uriVariables = Collections.unmodifiableMap(uriVars);
this.matrixVariables = matrixVars != null ?
Collections.unmodifiableMap(matrixVars) : Collections.emptyMap();
}
/**
* Return the extracted URI variables.
*/
public Map<String, String> getUriVariables() {
return this.uriVariables;
}
/**
* Return maps of matrix variables per path segment, keyed off by URI
* variable name.
*/
public Map<String, MultiValueMap<String, String>> getMatrixVariables() {
return this.matrixVariables;
}
@Override
public String toString() {
return "PathMatchInfo[uriVariables=" + this.uriVariables + ", " +
"matrixVariables=" + this.matrixVariables + "]";
}
}
/**
* Holder for the result of a match on the start of a pattern.
* Provides access to the remaining path not matched to the pattern as well
* as any variables bound in that first part that was matched.
*/
public static class PathRemainingMatchInfo {
private final PathContainer pathRemaining;
private final PathMatchInfo pathMatchInfo;
PathRemainingMatchInfo(PathContainer pathRemaining) {
this(pathRemaining, PathMatchInfo.EMPTY);
}
PathRemainingMatchInfo(PathContainer pathRemaining, PathMatchInfo pathMatchInfo) {
this.pathRemaining = pathRemaining;
this.pathMatchInfo = pathMatchInfo;
}
/**
* Return the part of a path that was not matched by a pattern.
*/
public PathContainer getPathRemaining() {
return this.pathRemaining;
}
/**
* Return variables that were bound in the part of the path that was
* successfully matched or an empty map.
*/
public Map<String, String> getUriVariables() {
return this.pathMatchInfo.getUriVariables();
}
/**
* Return the path parameters for each bound variable.
*/
public Map<String, MultiValueMap<String, String>> getMatrixVariables() {
return this.pathMatchInfo.getMatrixVariables();
}
}
/**
* Encapsulates context when attempting a match. Includes some fixed state like the
* candidate currently being considered for a match but also some accumulators for
@@ -642,65 +702,4 @@ public class PathPattern implements Comparable<PathPattern> {
return "";
}
}
/**
* Join two paths together including a separator if necessary.
* Extraneous separators are removed (if the first path
* ends with one and the second path starts with one).
* @param path1 first path
* @param path2 second path
* @return joined path that may include separator if necessary
*/
private String concat(String path1, String path2) {
boolean path1EndsWithSeparator = (path1.charAt(path1.length() - 1) == this.separator);
boolean path2StartsWithSeparator = (path2.charAt(0) == this.separator);
if (path1EndsWithSeparator && path2StartsWithSeparator) {
return path1 + path2.substring(1);
}
else if (path1EndsWithSeparator || path2StartsWithSeparator) {
return path1 + path2;
}
else {
return path1 + this.separator + path2;
}
}
/**
* Return if the container is not null and has more than zero elements.
* @param container a path container
* @return {@code true} has more than zero elements
*/
private boolean hasLength(@Nullable PathContainer container) {
return container != null && container.elements().size() > 0;
}
/**
* Comparator that sorts patterns by specificity as follows:
* <ol>
* <li>Null instances are last.
* <li>Catch-all patterns are last.
* <li>If both patterns are catch-all, consider the length (longer wins).
* <li>Compare wildcard and captured variable count (lower wins).
* <li>Consider length (longer wins)
* </ol>
*/
public static final Comparator<PathPattern> SPECIFICITY_COMPARATOR =
Comparator.nullsLast(
Comparator.<PathPattern>
comparingInt(p -> p.isCatchAll() ? 1 : 0)
.thenComparingInt(p -> p.isCatchAll() ? scoreByNormalizedLength(p) : 0)
.thenComparingInt(PathPattern::getScore)
.thenComparingInt(PathPattern::scoreByNormalizedLength)
);
private static int scoreByNormalizedLength(PathPattern pattern) {
return -pattern.getNormalizedLength();
}
private boolean pathContainerIsJustSeparator(PathContainer pathContainer) {
return pathContainer.value().length() == 1 &&
pathContainer.value().charAt(0) == separator;
}
}