parent
							
								
									c5d6cc4134
								
							
						
					
					
						commit
						57e0c789a8
					
				| 
						 | 
				
			
			@ -29,15 +29,19 @@ import org.springframework.core.io.Resource;
 | 
			
		|||
 * A {@code ResourceResolver} that delegates to the chain to locate a resource
 | 
			
		||||
 * and then attempts to find a matching versioned resource contained in a WebJar JAR file.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>This allows WabJar users to use version-less paths in their templates, like {@code "/jquery/jquery.min.js"}
 | 
			
		||||
 * while this path is resolved to the unique version {@code "/jquery/1.2.0/jquery.min.js"}, which is a better fit
 | 
			
		||||
 * for HTTP caching and version management in applications.
 | 
			
		||||
 * <p>This allows WebJars.org users to write version agnostic paths in their templates,
 | 
			
		||||
 * like {@code <script src="/jquery/jquery.min.js"/>}.
 | 
			
		||||
 * This path will be resolved to the unique version {@code <script src="/jquery/1.2.0/jquery.min.js"/>},
 | 
			
		||||
 * which is a better fit for HTTP caching and version management in applications.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>This also resolves Resources for version agnostic HTTP requests {@code "GET /jquery/jquery.min.js"}.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>This resolver requires the "org.webjars:webjars-locator" library on classpath, and is automatically
 | 
			
		||||
 * registered if that library is present.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Brian Clozel
 | 
			
		||||
 * @since 4.2
 | 
			
		||||
 * @see org.springframework.web.servlet.config.annotation.ResourceChainRegistration
 | 
			
		||||
 * @see <a href="http://www.webjars.org">webjars.org</a>
 | 
			
		||||
 */
 | 
			
		||||
public class WebJarsResourceResolver extends AbstractResourceResolver {
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +60,12 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
 | 
			
		|||
	protected Resource resolveResourceInternal(HttpServletRequest request, String requestPath,
 | 
			
		||||
			List<? extends Resource> locations, ResourceResolverChain chain) {
 | 
			
		||||
 | 
			
		||||
		return chain.resolveResource(request, requestPath, locations);
 | 
			
		||||
		Resource resolved = chain.resolveResource(request, requestPath, locations);
 | 
			
		||||
		if (resolved == null) {
 | 
			
		||||
			String webJarResourcePath = findWebJarResourcePath(requestPath);
 | 
			
		||||
			return chain.resolveResource(request, webJarResourcePath, locations);
 | 
			
		||||
		}
 | 
			
		||||
		return resolved;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			@ -65,26 +74,31 @@ public class WebJarsResourceResolver extends AbstractResourceResolver {
 | 
			
		|||
 | 
			
		||||
		String path = chain.resolveUrlPath(resourceUrlPath, locations);
 | 
			
		||||
		if (path == null) {
 | 
			
		||||
			try {
 | 
			
		||||
				int startOffset = resourceUrlPath.startsWith("/") ? 1 : 0;
 | 
			
		||||
				int endOffset = resourceUrlPath.indexOf("/", 1);
 | 
			
		||||
				if (endOffset != -1) {
 | 
			
		||||
					String webjar = resourceUrlPath.substring(startOffset, endOffset);
 | 
			
		||||
					String partialPath = resourceUrlPath.substring(endOffset);
 | 
			
		||||
					String webJarPath = webJarAssetLocator.getFullPath(webjar, partialPath);
 | 
			
		||||
					return chain.resolveUrlPath(webJarPath.substring(WEBJARS_LOCATION_LENGTH), locations);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			catch (MultipleMatchesException ex) {
 | 
			
		||||
				logger.warn("WebJar version conflict for \"" + resourceUrlPath + "\"", ex);
 | 
			
		||||
			}
 | 
			
		||||
			catch (IllegalArgumentException ex) {
 | 
			
		||||
				if (logger.isTraceEnabled()) {
 | 
			
		||||
					logger.trace("No WebJar resource found for \"" + resourceUrlPath + "\"");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			String webJarResourcePath = findWebJarResourcePath(resourceUrlPath);
 | 
			
		||||
			return chain.resolveUrlPath(webJarResourcePath, locations);
 | 
			
		||||
		}
 | 
			
		||||
		return path;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected String findWebJarResourcePath(String path) {
 | 
			
		||||
		try {
 | 
			
		||||
			int startOffset = path.startsWith("/") ? 1 : 0;
 | 
			
		||||
			int endOffset = path.indexOf("/", 1);
 | 
			
		||||
			if (endOffset != -1) {
 | 
			
		||||
				String webjar = path.substring(startOffset, endOffset);
 | 
			
		||||
				String partialPath = path.substring(endOffset);
 | 
			
		||||
				String webJarPath = webJarAssetLocator.getFullPath(webjar, partialPath);
 | 
			
		||||
				return webJarPath.substring(WEBJARS_LOCATION_LENGTH);
 | 
			
		||||
			}
 | 
			
		||||
		} catch (MultipleMatchesException ex) {
 | 
			
		||||
			logger.warn("WebJar version conflict for \"" + path + "\"", ex);
 | 
			
		||||
		}
 | 
			
		||||
		catch (IllegalArgumentException ex) {
 | 
			
		||||
			if (logger.isTraceEnabled()) {
 | 
			
		||||
				logger.trace("No WebJar resource found for \"" + path + "\"");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,11 +26,14 @@ import static org.mockito.Mockito.verify;
 | 
			
		|||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import org.springframework.core.io.ClassPathResource;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.mock.web.test.MockHttpServletRequest;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Unit tests for
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +49,8 @@ public class WebJarsResourceResolverTests {
 | 
			
		|||
 | 
			
		||||
	private ResourceResolverChain chain;
 | 
			
		||||
 | 
			
		||||
	private HttpServletRequest request = new MockHttpServletRequest();
 | 
			
		||||
 | 
			
		||||
	@Before
 | 
			
		||||
	public void setup() {
 | 
			
		||||
		// for this to work, an actual WebJar must be on the test classpath
 | 
			
		||||
| 
						 | 
				
			
			@ -104,4 +109,31 @@ public class WebJarsResourceResolverTests {
 | 
			
		|||
		verify(this.chain, times(1)).resolveUrlPath(file, this.locations);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void resolveResourceExisting() {
 | 
			
		||||
		Resource expected = mock(Resource.class);
 | 
			
		||||
		this.locations = Collections.singletonList(new ClassPathResource("/META-INF/resources/webjars/", getClass()));
 | 
			
		||||
		String file = "/foo/2.3/foo.txt";
 | 
			
		||||
		given(this.chain.resolveResource(this.request, file, this.locations)).willReturn(expected);
 | 
			
		||||
 | 
			
		||||
		Resource actual = this.resolver.resolveResource(this.request, file, this.locations, this.chain);
 | 
			
		||||
 | 
			
		||||
		assertEquals(expected, actual);
 | 
			
		||||
		verify(this.chain, times(1)).resolveResource(this.request, file, this.locations);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void resolveResourceWebJar() {
 | 
			
		||||
		Resource expected = mock(Resource.class);
 | 
			
		||||
		String file = "/underscorejs/underscore.js";
 | 
			
		||||
		String expectedPath = "/underscorejs/1.8.2/underscore.js";
 | 
			
		||||
		this.locations = Collections.singletonList(new ClassPathResource("/META-INF/resources/webjars/", getClass()));
 | 
			
		||||
		given(this.chain.resolveResource(this.request, expectedPath, this.locations)).willReturn(expected);
 | 
			
		||||
 | 
			
		||||
		Resource actual = this.resolver.resolveResource(this.request, file, this.locations, this.chain);
 | 
			
		||||
 | 
			
		||||
		assertEquals(expected, actual);
 | 
			
		||||
		verify(this.chain, times(1)).resolveResource(this.request, file, this.locations);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue