Browse Source

ServletContextResourcePatternResolver handles "/WEB-INF/lib/*.jar!/**/context.xml" style patterns (SPR-7198)

pull/1234/head
Juergen Hoeller 15 years ago
parent
commit
a8ed98255f
  1. 69
      org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java

69
org.springframework.web/src/main/java/org/springframework/web/context/support/ServletContextResourcePatternResolver.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2010 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.
@ -17,14 +17,21 @@ @@ -17,14 +17,21 @@
package org.springframework.web.context.support;
import java.io.IOException;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
/**
@ -38,6 +45,9 @@ import org.springframework.util.StringUtils; @@ -38,6 +45,9 @@ import org.springframework.util.StringUtils;
*/
public class ServletContextResourcePatternResolver extends PathMatchingResourcePatternResolver {
private static final Log logger = LogFactory.getLog(ServletContextResourcePatternResolver.class);
/**
* Create a new ServletContextResourcePatternResolver.
* @param servletContext the ServletContext to load resources with
@ -102,8 +112,15 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP @@ -102,8 +112,15 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP
Set candidates = servletContext.getResourcePaths(dir);
if (candidates != null) {
boolean dirDepthNotFixed = fullPattern.contains("**");
for (Iterator it = candidates.iterator(); it.hasNext();) {
String currPath = (String) it.next();
int jarFileSep = fullPattern.indexOf(ResourceUtils.JAR_URL_SEPARATOR);
String jarFilePath = null;
String pathInJarFile = null;
if (jarFileSep > 0 && jarFileSep + ResourceUtils.JAR_URL_SEPARATOR.length() < fullPattern.length()) {
jarFilePath = fullPattern.substring(0, jarFileSep);
pathInJarFile = fullPattern.substring(jarFileSep + ResourceUtils.JAR_URL_SEPARATOR.length());
}
for (Object candidate : candidates) {
String currPath = (String) candidate;
if (!currPath.startsWith(dir)) {
// Returned resource path does not start with relative directory:
// assuming absolute path returned -> strip absolute path.
@ -112,13 +129,19 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP @@ -112,13 +129,19 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP
currPath = currPath.substring(dirIndex);
}
}
if (currPath.endsWith("/") &&
(dirDepthNotFixed ||
StringUtils.countOccurrencesOf(currPath, "/") <= StringUtils.countOccurrencesOf(fullPattern, "/"))) {
if (currPath.endsWith("/") && (dirDepthNotFixed || StringUtils.countOccurrencesOf(currPath, "/") <=
StringUtils.countOccurrencesOf(fullPattern, "/"))) {
// Search subdirectories recursively: ServletContext.getResourcePaths
// only returns entries for one directory level.
doRetrieveMatchingServletContextResources(servletContext, fullPattern, currPath, result);
}
if (jarFilePath != null && getPathMatcher().match(jarFilePath, currPath)) {
// Base pattern matches a jar file - search for matching entries within.
String absoluteJarPath = servletContext.getRealPath(currPath);
if (absoluteJarPath != null) {
doRetrieveMatchingJarEntries(absoluteJarPath, pathInJarFile, result);
}
}
if (getPathMatcher().match(fullPattern, currPath)) {
result.add(new ServletContextResource(servletContext, currPath));
}
@ -126,4 +149,36 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP @@ -126,4 +149,36 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP
}
}
/**
* Method extracts entries from the given jar by pattern.
* @param jarFilePath the path to the jar file
* @param entryPattern the pattern for jar entries to match
* @param result the Set of matching Resources to add to
* @throws IOException if jar contents could not be retrieved
*/
@SuppressWarnings("unchecked")
private void doRetrieveMatchingJarEntries(String jarFilePath, String entryPattern, Set<Resource> result) {
if (logger.isDebugEnabled()) {
logger.debug("Searching jar file [" + jarFilePath + "] for entries matching [" + entryPattern + "]");
}
try {
JarFile jarFile = new JarFile(jarFilePath);
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
JarEntry entry = entries.nextElement();
String entryPath = entry.getName();
if (getPathMatcher().match(entryPattern, entryPath)) {
result.add(new UrlResource(ResourceUtils.URL_PROTOCOL_JAR + ":" +
ResourceUtils.URL_PROTOCOL_FILE + ":" + jarFilePath +
ResourceUtils.JAR_URL_SEPARATOR + entryPath));
}
}
}
catch (IOException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Cannot search for matching resources in jar file [" + jarFilePath +
"] because the jar cannot be opened through the file system", ex);
}
}
}
}

Loading…
Cancel
Save