From efb5ba5a95043ebe0b3b254233909a409f0d3212 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 18 Jul 2017 04:35:56 +0200 Subject: [PATCH] Refactor VersionStrategy in WebFlux Collapse the base interface VersionPathStrategy into its extension VersionStrategy and then turn the prefix nad fliename based implementations into abstract base classes (vs delegate strategies). It is simpler to have one VersionStrategy hierarchy vs that plus a separate VersionPathStrategy as a delegate. In practice each VersionStrategy is suited to be prefix or filename based. Also none of our code cares about the distinction between those two interfaces. --- .../AbstractFileNameVersionStrategy.java | 66 ++++++++ .../AbstractPrefixVersionStrategy.java | 74 +++++++++ .../resource/AbstractVersionStrategy.java | 147 ------------------ .../resource/ContentVersionStrategy.java | 7 +- .../resource/FixedVersionStrategy.java | 9 +- .../resource/VersionPathStrategy.java | 55 ------- .../reactive/resource/VersionStrategy.java | 32 +++- 7 files changed, 173 insertions(+), 217 deletions(-) create mode 100644 spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractFileNameVersionStrategy.java create mode 100644 spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractPrefixVersionStrategy.java delete mode 100644 spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractVersionStrategy.java delete mode 100644 spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionPathStrategy.java diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractFileNameVersionStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractFileNameVersionStrategy.java new file mode 100644 index 0000000000..d4dd5d770b --- /dev/null +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractFileNameVersionStrategy.java @@ -0,0 +1,66 @@ +/* + * Copyright 2002-2016 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.web.reactive.resource; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.util.StringUtils; + +/** + * Abstract base class for filename suffix based {@link VersionStrategy} + * implementations, e.g. "static/myresource-version.js" + * + * @author Rossen Stoyanchev + * @author Brian Clozel + * @since 5.0 + */ +public abstract class AbstractFileNameVersionStrategy implements VersionStrategy { + + protected final Log logger = LogFactory.getLog(getClass()); + + private static final Pattern pattern = Pattern.compile("-(\\S*)\\."); + + + @Override + public String extractVersion(String requestPath) { + Matcher matcher = pattern.matcher(requestPath); + if (matcher.find()) { + String match = matcher.group(1); + return (match.contains("-") ? match.substring(match.lastIndexOf('-') + 1) : match); + } + else { + return null; + } + } + + @Override + public String removeVersion(String requestPath, String version) { + return StringUtils.delete(requestPath, "-" + version); + } + + @Override + public String addVersion(String requestPath, String version) { + String baseFilename = StringUtils.stripFilenameExtension(requestPath); + String extension = StringUtils.getFilenameExtension(requestPath); + return (baseFilename + '-' + version + '.' + extension); + } + +} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractPrefixVersionStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractPrefixVersionStrategy.java new file mode 100644 index 0000000000..906b7be249 --- /dev/null +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractPrefixVersionStrategy.java @@ -0,0 +1,74 @@ +/* + * Copyright 2002-2016 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.web.reactive.resource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.util.Assert; + +/** + * Abstract base class for {@link VersionStrategy} implementations that insert + * a prefix into the URL path, e.g. "version/static/myresource.js". + * + * @author Rossen Stoyanchev + * @author Brian Clozel + * @since 5.0 + */ +public abstract class AbstractPrefixVersionStrategy implements VersionStrategy { + + protected final Log logger = LogFactory.getLog(getClass()); + + + private final String prefix; + + + protected AbstractPrefixVersionStrategy(String version) { + Assert.hasText(version, "'version' must not be empty"); + this.prefix = version; + } + + + public String getPrefix() { + return this.prefix; + } + + + @Override + public String extractVersion(String requestPath) { + return requestPath.startsWith(this.prefix) ? this.prefix : null; + } + + @Override + public String removeVersion(String requestPath, String version) { + return requestPath.substring(this.prefix.length()); + } + + @Override + public String addVersion(String path, String version) { + if (path.startsWith(".")) { + return path; + } + else if (this.prefix.endsWith("/") || path.startsWith("/")) { + return this.prefix + path; + } + else { + return this.prefix + '/' + path; + } + } + +} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractVersionStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractVersionStrategy.java deleted file mode 100644 index 92287556af..0000000000 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/AbstractVersionStrategy.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2002-2016 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.web.reactive.resource; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -/** - * Abstract base class for {@link VersionStrategy} implementations. - * - *

Supports versions as: - *

- * - *

Note: This base class does not provide support for generating the - * version string. - * - * @author Rossen Stoyanchev - * @author Brian Clozel - * @since 5.0 - */ -public abstract class AbstractVersionStrategy implements VersionStrategy { - - protected final Log logger = LogFactory.getLog(getClass()); - - private final VersionPathStrategy pathStrategy; - - - protected AbstractVersionStrategy(VersionPathStrategy pathStrategy) { - Assert.notNull(pathStrategy, "VersionPathStrategy is required"); - this.pathStrategy = pathStrategy; - } - - - public VersionPathStrategy getVersionPathStrategy() { - return this.pathStrategy; - } - - - @Override - public String extractVersion(String requestPath) { - return this.pathStrategy.extractVersion(requestPath); - } - - @Override - public String removeVersion(String requestPath, String version) { - return this.pathStrategy.removeVersion(requestPath, version); - } - - @Override - public String addVersion(String requestPath, String version) { - return this.pathStrategy.addVersion(requestPath, version); - } - - - /** - * A prefix-based {@code VersionPathStrategy}, - * e.g. {@code "{version}/path/foo.js"}. - */ - protected static class PrefixVersionPathStrategy implements VersionPathStrategy { - - private final String prefix; - - public PrefixVersionPathStrategy(String version) { - Assert.hasText(version, "'version' must not be empty"); - this.prefix = version; - } - - @Override - public String extractVersion(String requestPath) { - return (requestPath.startsWith(this.prefix) ? this.prefix : null); - } - - @Override - public String removeVersion(String requestPath, String version) { - return requestPath.substring(this.prefix.length()); - } - - @Override - public String addVersion(String path, String version) { - if (path.startsWith(".")) { - return path; - } - else { - return (this.prefix.endsWith("/") || path.startsWith("/") ? - this.prefix + path : this.prefix + '/' + path); - } - } - } - - - /** - * File name-based {@code VersionPathStrategy}, - * e.g. {@code "path/foo-{version}.css"}. - */ - protected static class FileNameVersionPathStrategy implements VersionPathStrategy { - - private static final Pattern pattern = Pattern.compile("-(\\S*)\\."); - - @Override - public String extractVersion(String requestPath) { - Matcher matcher = pattern.matcher(requestPath); - if (matcher.find()) { - String match = matcher.group(1); - return (match.contains("-") ? match.substring(match.lastIndexOf('-') + 1) : match); - } - else { - return null; - } - } - - @Override - public String removeVersion(String requestPath, String version) { - return StringUtils.delete(requestPath, "-" + version); - } - - @Override - public String addVersion(String requestPath, String version) { - String baseFilename = StringUtils.stripFilenameExtension(requestPath); - String extension = StringUtils.getFilenameExtension(requestPath); - return (baseFilename + '-' + version + '.' + extension); - } - } - -} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ContentVersionStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ContentVersionStrategy.java index 341fc67334..9213209273 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ContentVersionStrategy.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/ContentVersionStrategy.java @@ -31,12 +31,7 @@ import org.springframework.util.DigestUtils; * @since 5.0 * @see VersionResourceResolver */ -public class ContentVersionStrategy extends AbstractVersionStrategy { - - - public ContentVersionStrategy() { - super(new FileNameVersionPathStrategy()); - } +public class ContentVersionStrategy extends AbstractFileNameVersionStrategy { @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/FixedVersionStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/FixedVersionStrategy.java index 9a8aea12fa..f16deda667 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/FixedVersionStrategy.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/FixedVersionStrategy.java @@ -31,9 +31,7 @@ import org.springframework.core.io.Resource; * @since 5.0 * @see VersionResourceResolver */ -public class FixedVersionStrategy extends AbstractVersionStrategy { - - private final String version; +public class FixedVersionStrategy extends AbstractPrefixVersionStrategy { /** @@ -41,14 +39,13 @@ public class FixedVersionStrategy extends AbstractVersionStrategy { * @param version the fixed version string to use */ public FixedVersionStrategy(String version) { - super(new PrefixVersionPathStrategy(version)); - this.version = version; + super(version); } @Override public String getResourceVersion(Resource resource) { - return this.version; + return getPrefix(); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionPathStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionPathStrategy.java deleted file mode 100644 index 28d245b45c..0000000000 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionPathStrategy.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2016 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.web.reactive.resource; - -import org.springframework.lang.Nullable; - -/** - * A strategy for extracting and embedding a resource version in its URL path. - * - * @author Rossen Stoyanchev - * @author Brian Clozel - * @since 5.0 -*/ -public interface VersionPathStrategy { - - /** - * Extract the resource version from the request path. - * @param requestPath the request path to check - * @return the version string or {@code null} if none was found - */ - @Nullable - String extractVersion(String requestPath); - - /** - * Remove the version from the request path. It is assumed that the given - * version was extracted via {@link #extractVersion(String)}. - * @param requestPath the request path of the resource being resolved - * @param version the version obtained from {@link #extractVersion(String)} - * @return the request path with the version removed - */ - String removeVersion(String requestPath, String version); - - /** - * Add a version to the given request path. - * @param requestPath the requestPath - * @param version the version - * @return the requestPath updated with a version string - */ - String addVersion(String requestPath, String version); - -} diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionStrategy.java b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionStrategy.java index 79a4ee9517..bc8ed43556 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionStrategy.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/resource/VersionStrategy.java @@ -17,17 +17,43 @@ package org.springframework.web.reactive.resource; import org.springframework.core.io.Resource; +import org.springframework.lang.Nullable; /** - * An extension of {@link VersionPathStrategy} that adds a method - * to determine the actual version of a {@link Resource}. + * A strategy to determine the version of a static resource and to apply and/or + * extract it from the URL path. * * @author Rossen Stoyanchev * @author Brian Clozel * @since 5.0 * @see VersionResourceResolver */ -public interface VersionStrategy extends VersionPathStrategy { +public interface VersionStrategy { + + /** + * Extract the resource version from the request path. + * @param requestPath the request path to check + * @return the version string or {@code null} if none was found + */ + @Nullable + String extractVersion(String requestPath); + + /** + * Remove the version from the request path. It is assumed that the given + * version was extracted via {@link #extractVersion(String)}. + * @param requestPath the request path of the resource being resolved + * @param version the version obtained from {@link #extractVersion(String)} + * @return the request path with the version removed + */ + String removeVersion(String requestPath, String version); + + /** + * Add a version to the given request path. + * @param requestPath the requestPath + * @param version the version + * @return the requestPath updated with a version string + */ + String addVersion(String requestPath, String version); /** * Determine the version for the given resource.