diff --git a/spring-web/src/main/java/org/springframework/web/accept/PathExtensionContentNegotiationStrategy.java b/spring-web/src/main/java/org/springframework/web/accept/PathExtensionContentNegotiationStrategy.java index 0a042f4384..000b637964 100644 --- a/spring-web/src/main/java/org/springframework/web/accept/PathExtensionContentNegotiationStrategy.java +++ b/spring-web/src/main/java/org/springframework/web/accept/PathExtensionContentNegotiationStrategy.java @@ -35,8 +35,8 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.util.UriUtils; import org.springframework.web.util.UrlPathHelper; -import org.springframework.web.util.WebUtils; /** * A {@code ContentNegotiationStrategy} that resolves the file extension in the @@ -118,9 +118,8 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont return null; } String path = this.urlPathHelper.getLookupPathForRequest(request); - String filename = WebUtils.extractFullFilenameFromUrlPath(path); - String extension = StringUtils.getFilenameExtension(filename); - return (StringUtils.hasText(extension)) ? extension.toLowerCase(Locale.ENGLISH) : null; + String extension = UriUtils.extractFileExtension(path); + return (StringUtils.hasText(extension) ? extension.toLowerCase(Locale.ENGLISH) : null); } @Override @@ -128,7 +127,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont throws HttpMediaTypeNotAcceptableException { if (this.useJaf && JAF_PRESENT) { - MediaType mediaType = JafMediaTypeFactory.getMediaType("file." + extension); + MediaType mediaType = ActivationMediaTypeFactory.getMediaType("file." + extension); if (mediaType != null && !MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) { return mediaType; } @@ -157,7 +156,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont mediaType = lookupMediaType(extension); } if (mediaType == null && JAF_PRESENT) { - mediaType = JafMediaTypeFactory.getMediaType(filename); + mediaType = ActivationMediaTypeFactory.getMediaType(filename); } if (MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) { mediaType = null; @@ -169,7 +168,7 @@ public class PathExtensionContentNegotiationStrategy extends AbstractMappingCont /** * Inner class to avoid hard-coded dependency on JAF. */ - private static class JafMediaTypeFactory { + private static class ActivationMediaTypeFactory { private static final FileTypeMap fileTypeMap; diff --git a/spring-web/src/main/java/org/springframework/web/util/UriUtils.java b/spring-web/src/main/java/org/springframework/web/util/UriUtils.java index c68092971f..6b2f3e5049 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriUtils.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -34,6 +34,7 @@ import org.springframework.util.Assert; * * * @author Arjen Poutsma + * @author Juergen Hoeller * @since 3.0 * @see RFC 3986 */ @@ -213,4 +214,28 @@ public abstract class UriUtils { return (changed ? new String(bos.toByteArray(), encoding) : source); } + /** + * Extract the file extension from the given URI path. + * @param path the URI path (e.g. "/products/index.html") + * @return the extracted file extension (e.g. "html") + * @since 4.3.2 + */ + public static String extractFileExtension(String path) { + int end = path.indexOf('?'); + if (end == -1) { + end = path.indexOf('#'); + if (end == -1) { + end = path.length(); + } + } + int begin = path.lastIndexOf('/', end) + 1; + int paramIndex = path.indexOf(';', begin); + end = (paramIndex != -1 && paramIndex < end ? paramIndex : end); + int extIndex = path.lastIndexOf('.', end); + if (extIndex != -1 && extIndex > begin) { + return path.substring(extIndex + 1, end); + } + return null; + } + } diff --git a/spring-web/src/main/java/org/springframework/web/util/WebUtils.java b/spring-web/src/main/java/org/springframework/web/util/WebUtils.java index 6d8062fbdc..13195a76a7 100644 --- a/spring-web/src/main/java/org/springframework/web/util/WebUtils.java +++ b/spring-web/src/main/java/org/springframework/web/util/WebUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -278,7 +278,6 @@ public abstract class WebUtils { return realPath; } - /** * Determine the session id of the given request, if any. * @param request current HTTP request @@ -353,7 +352,9 @@ public abstract class WebUtils { * @param clazz the class to instantiate for a new attribute * @return the value of the session attribute, newly created if not found * @throws IllegalArgumentException if the session attribute could not be instantiated + * @deprecated as of Spring 4.3.2, in favor of custom code for such purposes */ + @Deprecated public static Object getOrCreateSessionAttribute(HttpSession session, String name, Class clazz) throws IllegalArgumentException { @@ -527,7 +528,9 @@ public abstract class WebUtils { * and the values as corresponding attribute values. Keys need to be Strings. * @param request current HTTP request * @param attributes the attributes Map + * @deprecated as of Spring 4.3.2, in favor of custom code for such purposes */ + @Deprecated public static void exposeRequestAttributes(ServletRequest request, Map attributes) { Assert.notNull(request, "Request must not be null"); Assert.notNull(attributes, "Attributes Map must not be null"); @@ -689,7 +692,9 @@ public abstract class WebUtils { * @param currentPage the current page, to be returned as fallback * if no target page specified * @return the page specified in the request, or current page if not found + * @deprecated as of Spring 4.3.2, in favor of custom code for such purposes */ + @Deprecated public static int getTargetPage(ServletRequest request, String paramPrefix, int currentPage) { Enumeration paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { @@ -713,7 +718,9 @@ public abstract class WebUtils { * Correctly resolves nested paths such as "/products/view.html" as well. * @param urlPath the request URL path (e.g. "/index.html") * @return the extracted URI filename (e.g. "index") + * @deprecated as of Spring 4.3.2, in favor of custom code for such purposes */ + @Deprecated public static String extractFilenameFromUrlPath(String urlPath) { String filename = extractFullFilenameFromUrlPath(urlPath); int dotIndex = filename.lastIndexOf('.'); @@ -729,7 +736,10 @@ public abstract class WebUtils { * "/products/view.html" and remove any path and or query parameters. * @param urlPath the request URL path (e.g. "/products/index.html") * @return the extracted URI filename (e.g. "index.html") + * @deprecated as of Spring 4.3.2, in favor of custom code for such purposes + * (or {@link UriUtils#extractFileExtension} for the file extension use case) */ + @Deprecated public static String extractFullFilenameFromUrlPath(String urlPath) { int end = urlPath.indexOf('?'); if (end == -1) { diff --git a/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java b/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java index 6480c5fa2e..2227674abc 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UriUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * 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. @@ -24,6 +24,7 @@ import static org.junit.Assert.*; /** * @author Arjen Poutsma + * @author Juergen Hoeller */ public class UriUtilsTests { @@ -104,4 +105,22 @@ public class UriUtilsTests { UriUtils.decode("foo%2", ENC); } + @Test + public void extractFileExtension() { + assertEquals("html", UriUtils.extractFileExtension("index.html")); + assertEquals("html", UriUtils.extractFileExtension("/index.html")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html#/a")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html#/path/a")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html#/path/a.do")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=a")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a.do")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a#/path/a")); + assertEquals("html", UriUtils.extractFileExtension("/products/view.html?param=/path/a.do#/path/a.do")); + assertEquals("html", UriUtils.extractFileExtension("/products;q=11/view.html?param=/path/a.do")); + assertEquals("html", UriUtils.extractFileExtension("/products;q=11/view.html;r=22?param=/path/a.do")); + assertEquals("html", UriUtils.extractFileExtension("/products;q=11/view.html;r=22;s=33?param=/path/a.do")); + } + } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java index 852f5cd2dc..367aed8503 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/support/ServletUriComponentsBuilder.java @@ -28,8 +28,8 @@ import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.web.util.UriUtils; import org.springframework.web.util.UrlPathHelper; -import org.springframework.web.util.WebUtils; /** * A UriComponentsBuilder that extracts information from the HttpServletRequest. @@ -44,7 +44,6 @@ public class ServletUriComponentsBuilder extends UriComponentsBuilder { /** * Default constructor. Protected to prevent direct instantiation. - * * @see #fromContextPath(HttpServletRequest) * @see #fromServletMapping(HttpServletRequest) * @see #fromRequest(HttpServletRequest) @@ -219,8 +218,7 @@ public class ServletUriComponentsBuilder extends UriComponentsBuilder { public String removePathExtension() { String extension = null; if (this.originalPath != null) { - String filename = WebUtils.extractFullFilenameFromUrlPath(this.originalPath); - extension = StringUtils.getFilenameExtension(filename); + extension = UriUtils.extractFileExtension(this.originalPath); if (!StringUtils.isEmpty(extension)) { int end = this.originalPath.length() - (extension.length() + 1); replacePath(this.originalPath.substring(0, end));