001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.context.support;
018:
019: import java.io.IOException;
020: import java.util.Iterator;
021: import java.util.LinkedHashSet;
022: import java.util.Set;
023:
024: import javax.servlet.ServletContext;
025:
026: import org.springframework.core.io.Resource;
027: import org.springframework.core.io.ResourceLoader;
028: import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
029: import org.springframework.util.StringUtils;
030:
031: /**
032: * ServletContext-aware subclass of {@link PathMatchingResourcePatternResolver},
033: * able to find matching resources below the web application root directory
034: * via Servlet 2.3's <code>ServletContext.getResourcePaths</code>.
035: * Falls back to the superclass' file system checking for other resources.
036: *
037: * @author Juergen Hoeller
038: * @since 1.1.2
039: */
040: public class ServletContextResourcePatternResolver extends
041: PathMatchingResourcePatternResolver {
042:
043: /**
044: * Create a new ServletContextResourcePatternResolver.
045: * @param servletContext the ServletContext to load resources with
046: * @see ServletContextResourceLoader#ServletContextResourceLoader(javax.servlet.ServletContext)
047: */
048: public ServletContextResourcePatternResolver(
049: ServletContext servletContext) {
050: super (new ServletContextResourceLoader(servletContext));
051: }
052:
053: /**
054: * Create a new ServletContextResourcePatternResolver.
055: * @param resourceLoader the ResourceLoader to load root directories and
056: * actual resources with
057: */
058: public ServletContextResourcePatternResolver(
059: ResourceLoader resourceLoader) {
060: super (resourceLoader);
061: }
062:
063: /**
064: * Overridden version which checks for ServletContextResource
065: * and uses <code>ServletContext.getResourcePaths</code> to find
066: * matching resources below the web application root directory.
067: * In case of other resources, delegates to the superclass version.
068: * @see #doRetrieveMatchingServletContextResources
069: * @see ServletContextResource
070: * @see javax.servlet.ServletContext#getResourcePaths
071: */
072: protected Set doFindPathMatchingFileResources(
073: Resource rootDirResource, String subPattern)
074: throws IOException {
075: if (rootDirResource instanceof ServletContextResource) {
076: ServletContextResource scResource = (ServletContextResource) rootDirResource;
077: ServletContext sc = scResource.getServletContext();
078: String fullPattern = scResource.getPath() + subPattern;
079: Set result = new LinkedHashSet(8);
080: doRetrieveMatchingServletContextResources(sc, fullPattern,
081: scResource.getPath(), result);
082: return result;
083: } else {
084: return super .doFindPathMatchingFileResources(
085: rootDirResource, subPattern);
086: }
087: }
088:
089: /**
090: * Recursively retrieve ServletContextResources that match the given pattern,
091: * adding them to the given result set.
092: * @param servletContext the ServletContext to work on
093: * @param fullPattern the pattern to match against,
094: * with preprended root directory path
095: * @param dir the current directory
096: * @param result the Set of matching Resources to add to
097: * @throws IOException if directory contents could not be retrieved
098: * @see ServletContextResource
099: * @see javax.servlet.ServletContext#getResourcePaths
100: */
101: protected void doRetrieveMatchingServletContextResources(
102: ServletContext servletContext, String fullPattern,
103: String dir, Set result) throws IOException {
104:
105: Set candidates = servletContext.getResourcePaths(dir);
106: if (candidates != null) {
107: boolean dirDepthNotFixed = (fullPattern.indexOf("**") != -1);
108: for (Iterator it = candidates.iterator(); it.hasNext();) {
109: String currPath = (String) it.next();
110: if (!currPath.startsWith(dir)) {
111: // Returned resource path does not start with relative directory:
112: // assuming absolute path returned -> strip absolute path.
113: int dirIndex = currPath.indexOf(dir);
114: if (dirIndex != -1) {
115: currPath = currPath.substring(dirIndex);
116: }
117: }
118: if (currPath.endsWith("/")
119: && (dirDepthNotFixed || StringUtils
120: .countOccurrencesOf(currPath, "/") <= StringUtils
121: .countOccurrencesOf(fullPattern, "/"))) {
122: // Search subdirectories recursively: ServletContext.getResourcePaths
123: // only returns entries for one directory level.
124: doRetrieveMatchingServletContextResources(
125: servletContext, fullPattern, currPath,
126: result);
127: }
128: if (getPathMatcher().match(fullPattern, currPath)) {
129: result.add(new ServletContextResource(
130: servletContext, currPath));
131: }
132: }
133: }
134: }
135:
136: }
|