|
|
|
@ -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"); |
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -17,14 +17,21 @@ |
|
|
|
package org.springframework.web.context.support; |
|
|
|
package org.springframework.web.context.support; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.util.Iterator; |
|
|
|
import java.util.Enumeration; |
|
|
|
import java.util.LinkedHashSet; |
|
|
|
import java.util.LinkedHashSet; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
import java.util.jar.JarEntry; |
|
|
|
|
|
|
|
import java.util.jar.JarFile; |
|
|
|
import javax.servlet.ServletContext; |
|
|
|
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.Resource; |
|
|
|
import org.springframework.core.io.ResourceLoader; |
|
|
|
import org.springframework.core.io.ResourceLoader; |
|
|
|
|
|
|
|
import org.springframework.core.io.UrlResource; |
|
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
|
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
|
|
|
|
|
|
|
import org.springframework.util.ResourceUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -38,6 +45,9 @@ import org.springframework.util.StringUtils; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class ServletContextResourcePatternResolver extends PathMatchingResourcePatternResolver { |
|
|
|
public class ServletContextResourcePatternResolver extends PathMatchingResourcePatternResolver { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final Log logger = LogFactory.getLog(ServletContextResourcePatternResolver.class); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create a new ServletContextResourcePatternResolver. |
|
|
|
* Create a new ServletContextResourcePatternResolver. |
|
|
|
* @param servletContext the ServletContext to load resources with |
|
|
|
* @param servletContext the ServletContext to load resources with |
|
|
|
@ -102,8 +112,15 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP |
|
|
|
Set candidates = servletContext.getResourcePaths(dir); |
|
|
|
Set candidates = servletContext.getResourcePaths(dir); |
|
|
|
if (candidates != null) { |
|
|
|
if (candidates != null) { |
|
|
|
boolean dirDepthNotFixed = fullPattern.contains("**"); |
|
|
|
boolean dirDepthNotFixed = fullPattern.contains("**"); |
|
|
|
for (Iterator it = candidates.iterator(); it.hasNext();) { |
|
|
|
int jarFileSep = fullPattern.indexOf(ResourceUtils.JAR_URL_SEPARATOR); |
|
|
|
String currPath = (String) it.next(); |
|
|
|
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)) { |
|
|
|
if (!currPath.startsWith(dir)) { |
|
|
|
// Returned resource path does not start with relative directory:
|
|
|
|
// Returned resource path does not start with relative directory:
|
|
|
|
// assuming absolute path returned -> strip absolute path.
|
|
|
|
// assuming absolute path returned -> strip absolute path.
|
|
|
|
@ -112,13 +129,19 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP |
|
|
|
currPath = currPath.substring(dirIndex); |
|
|
|
currPath = currPath.substring(dirIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (currPath.endsWith("/") && |
|
|
|
if (currPath.endsWith("/") && (dirDepthNotFixed || StringUtils.countOccurrencesOf(currPath, "/") <= |
|
|
|
(dirDepthNotFixed || |
|
|
|
StringUtils.countOccurrencesOf(fullPattern, "/"))) { |
|
|
|
StringUtils.countOccurrencesOf(currPath, "/") <= StringUtils.countOccurrencesOf(fullPattern, "/"))) { |
|
|
|
|
|
|
|
// Search subdirectories recursively: ServletContext.getResourcePaths
|
|
|
|
// Search subdirectories recursively: ServletContext.getResourcePaths
|
|
|
|
// only returns entries for one directory level.
|
|
|
|
// only returns entries for one directory level.
|
|
|
|
doRetrieveMatchingServletContextResources(servletContext, fullPattern, currPath, result); |
|
|
|
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)) { |
|
|
|
if (getPathMatcher().match(fullPattern, currPath)) { |
|
|
|
result.add(new ServletContextResource(servletContext, currPath)); |
|
|
|
result.add(new ServletContextResource(servletContext, currPath)); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|