diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowDefinitionResourceFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowDefinitionResourceFactory.java index d1f0cf94..aef65c82 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowDefinitionResourceFactory.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowDefinitionResourceFactory.java @@ -24,6 +24,7 @@ import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.UrlResource; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -39,8 +40,6 @@ public class FlowDefinitionResourceFactory { private static final String CLASSPATH_SCHEME = "classpath:"; - private static final String CLASSPATH_STAR_SCHEME = "classpath*:"; - private static final String SLASH = "/"; private ResourceLoader resourceLoader; @@ -108,9 +107,9 @@ public class FlowDefinitionResourceFactory { } else { try { String basePath = this.basePath; - if (!basePath.endsWith("/")) { + if (!basePath.endsWith(SLASH)) { // the basePath must end with a slash to create a relative resource - basePath = basePath + "/"; + basePath = basePath + SLASH; } resource = resourceLoader.getResource(basePath).createRelative(path); } catch (IOException e) { @@ -194,34 +193,35 @@ public class FlowDefinitionResourceFactory { } String basePath = this.basePath; String filePath; - if (flowResource instanceof ClassPathResource) { - filePath = ((ClassPathResource) flowResource).getPath(); - // remove classpath scheme - if (basePath.startsWith(CLASSPATH_SCHEME)) { - basePath = basePath.substring(CLASSPATH_SCHEME.length()); - } else if (basePath.startsWith(CLASSPATH_STAR_SCHEME)) { - basePath = basePath.substring(CLASSPATH_STAR_SCHEME.length()); - } - } else if (flowResource instanceof ContextResource) { + if (flowResource instanceof ContextResource) { filePath = ((ContextResource) flowResource).getPathWithinContext(); + } else if (flowResource instanceof ClassPathResource) { + basePath = removeClasspathScheme(basePath); + filePath = ((ClassPathResource) flowResource).getPath(); + } else if (flowResource instanceof FileSystemResource) { + basePath = removeClasspathScheme(basePath); + filePath = truncateFilePath(((FileSystemResource) flowResource).getPath(), basePath); + } else if (flowResource instanceof UrlResource) { + basePath = removeClasspathScheme(basePath); + try { + filePath = truncateFilePath(((UrlResource) flowResource).getURL().getPath(), basePath); + } catch (IOException e) { + throw new IllegalArgumentException("Unable to obtain path: " + e.getMessage()); + } } else { // default to the filename return getFlowIdFromFileName(flowResource); } - // TODO can this logic be simplified? + int beginIndex = 0; int endIndex = filePath.length(); - if (filePath.startsWith(SLASH) || !basePath.startsWith(SLASH)) { - if (filePath.startsWith(basePath)) { - beginIndex = basePath.length(); - } - } else { - if (filePath.startsWith(SLASH + basePath)) { - beginIndex = basePath.length() + 1; - } + if (filePath.startsWith(basePath)) { + beginIndex = basePath.length(); + } else if (filePath.startsWith(SLASH + basePath)) { + beginIndex = basePath.length() + 1; } - // ignore a leading slash if (filePath.startsWith(SLASH, beginIndex)) { + // ignore a leading slash beginIndex++; } if (filePath.lastIndexOf(SLASH) >= beginIndex) { @@ -238,4 +238,21 @@ public class FlowDefinitionResourceFactory { return StringUtils.stripFilenameExtension(flowResource.getFilename()); } + private String truncateFilePath(String filePath, String basePath) { + int basePathIndex = filePath.lastIndexOf(basePath); + if (basePathIndex != -1) { + return filePath.substring(basePathIndex); + } else { + return filePath; + } + } + + private String removeClasspathScheme(String basePath) { + if (basePath.startsWith(CLASSPATH_SCHEME)) { + return basePath.substring(CLASSPATH_SCHEME.length()); + } else { + return basePath; + } + } + } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowDefinitionResourceFactoryTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowDefinitionResourceFactoryTests.java index 9572d5bf..2274f7c9 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowDefinitionResourceFactoryTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowDefinitionResourceFactoryTests.java @@ -15,11 +15,15 @@ */ package org.springframework.webflow.config; +import java.net.MalformedURLException; + import junit.framework.TestCase; import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.UrlResource; import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.support.ServletContextResourceLoader; @@ -37,18 +41,30 @@ public class FlowDefinitionResourceFactoryTests extends TestCase { factory = new FlowDefinitionResourceFactory(); } - public void testGetFlowId() { + public void testGetFlowIdNoBasePath() { Resource resource = resourceLoader.getResource("/WEB-INF/hotels/booking/booking-flow.xml"); assertEquals("booking-flow", factory.getFlowId(resource)); } public void testGetFlowIdCustomBasePath() { + Resource resource = resourceLoader.getResource("/WEB-INF/hotels/booking/booking-flow.xml"); + factory.setBasePath("WEB-INF"); + assertEquals("hotels/booking", factory.getFlowId(resource)); + } + + public void testGetFlowCustomBasePathTrailingSlash() { + Resource resource = resourceLoader.getResource("/WEB-INF/hotels/booking/booking-flow.xml"); + factory.setBasePath("WEB-INF/"); + assertEquals("hotels/booking", factory.getFlowId(resource)); + } + + public void testGetFlowIdCustomBasePathLeadingSlash() { Resource resource = resourceLoader.getResource("/WEB-INF/hotels/booking/booking-flow.xml"); factory.setBasePath("/WEB-INF"); assertEquals("hotels/booking", factory.getFlowId(resource)); } - public void testGetFlowIdCustomBasePathTrailingSlash() { + public void testGetFlowIdCustomBasePathLeadingAndTrailingSlash() { Resource resource = resourceLoader.getResource("/WEB-INF/hotels/booking/booking-flow.xml"); factory.setBasePath("/WEB-INF/"); assertEquals("hotels/booking", factory.getFlowId(resource)); @@ -60,10 +76,42 @@ public class FlowDefinitionResourceFactoryTests extends TestCase { assertEquals("booking-flow", factory.getFlowId(resource)); } + public void testGetFlowIdBasePathMismatch() { + Resource resource = resourceLoader.getResource("/WEB-INF/hotels/booking/booking-flow.xml"); + factory.setBasePath("/foo/bar"); + assertEquals("WEB-INF/hotels/booking", factory.getFlowId(resource)); + } + public void testGetFlowIdClassPathResource() { Resource resource = new ClassPathResource("org/springframework/webflow/sample/sample-flow.xml"); - factory.setBasePath("classpath:org/springframework/webflow"); + factory.setBasePath("classpath:org/springframework/webflow/"); assertEquals("sample", factory.getFlowId(resource)); } + public void testGetFlowIdFileSystemResource() { + Resource resource = new FileSystemResource( + "/the/path/on/the/file/system/org/springframework/webflow/sample/sample-flow.xml"); + factory.setBasePath("classpath:org/springframework/webflow/"); + assertEquals("sample", factory.getFlowId(resource)); + } + + public void testGetFlowIdFileSystemResourceNoBasePathMatch() { + Resource resource = new FileSystemResource("/the/path/on/the/file/system/sample-flow.xml"); + factory.setBasePath("classpath:org/springframework/webflow/"); + assertEquals("the/path/on/the/file/system", factory.getFlowId(resource)); + } + + public void testGetFlowIdUrlResource() throws MalformedURLException { + Resource resource = new UrlResource( + "file:/the/path/on/the/file/system/org/springframework/webflow/sample/sample-flow.xml"); + factory.setBasePath("classpath:org/springframework/webflow/"); + assertEquals("sample", factory.getFlowId(resource)); + } + + public void testGetFlowIdUrlResourceNoBasePathMatch() throws MalformedURLException { + Resource resource = new UrlResource("file:/the/path/on/the/file/system/sample-flow.xml"); + factory.setBasePath("classpath:org/springframework/webflow/"); + assertEquals("the/path/on/the/file/system", factory.getFlowId(resource)); + } + }