diff --git a/org.springframework.core/core.iml b/org.springframework.core/core.iml
index 552e3ec093..0fd49c0c31 100644
--- a/org.springframework.core/core.iml
+++ b/org.springframework.core/core.iml
@@ -1,202 +1,211 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.springframework.core/ivy.xml b/org.springframework.core/ivy.xml
index ebe3803be4..321a81b977 100644
--- a/org.springframework.core/ivy.xml
+++ b/org.springframework.core/ivy.xml
@@ -37,6 +37,7 @@
+
diff --git a/org.springframework.core/pom.xml b/org.springframework.core/pom.xml
index 776dbc1c29..836666ae9c 100644
--- a/org.springframework.core/pom.xml
+++ b/org.springframework.core/pom.xml
@@ -43,6 +43,12 @@
1.6.2
true
+
+ org.jboss.vfs
+ com.springsource.org.jboss.virtual
+ 2.1.0.GA
+ true
+
javax.servlet
servlet-api
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/ClassPathResource.java b/org.springframework.core/src/main/java/org/springframework/core/io/ClassPathResource.java
index c63afc0feb..9fffc28f58 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/io/ClassPathResource.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/ClassPathResource.java
@@ -27,6 +27,7 @@ import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
+import org.springframework.core.io.support.ResourceHandlingUtils;
/**
* {@link Resource} implementation for class path resources.
@@ -49,7 +50,6 @@ public class ClassPathResource extends AbstractResource {
private Class clazz;
-
/**
* Create a new ClassPathResource for ClassLoader usage.
* A leading slash will be removed, as the ClassLoader
@@ -174,7 +174,7 @@ public class ClassPathResource extends AbstractResource {
*/
@Override
public File getFile() throws IOException {
- return ResourceUtils.getFile(getURL(), getDescription());
+ return ResourceHandlingUtils.getFile(getURL(), getDescription());
}
/**
@@ -186,10 +186,10 @@ public class ClassPathResource extends AbstractResource {
URL url = getURL();
if (ResourceUtils.isJarURL(url)) {
URL actualUrl = ResourceUtils.extractJarFileURL(url);
- return ResourceUtils.getFile(actualUrl);
+ return ResourceHandlingUtils.getFile(actualUrl);
}
else {
- return ResourceUtils.getFile(url, getDescription());
+ return ResourceHandlingUtils.getFile(url, getDescription());
}
}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/UrlResource.java b/org.springframework.core/src/main/java/org/springframework/core/io/UrlResource.java
index 912b9091c3..2e02b20e59 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/io/UrlResource.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/UrlResource.java
@@ -28,6 +28,7 @@ import java.net.URLConnection;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;
+import org.springframework.core.io.support.ResourceHandlingUtils;
/**
* {@link Resource} implementation for java.net.URL
locators.
@@ -163,10 +164,10 @@ public class UrlResource extends AbstractResource {
@Override
public File getFile() throws IOException {
if (this.uri != null) {
- return ResourceUtils.getFile(this.uri, getDescription());
+ return ResourceHandlingUtils.getFile(this.uri, getDescription());
}
else {
- return ResourceUtils.getFile(this.url, getDescription());
+ return ResourceHandlingUtils.getFile(this.url, getDescription());
}
}
@@ -178,7 +179,7 @@ public class UrlResource extends AbstractResource {
protected File getFileForLastModifiedCheck() throws IOException {
if (ResourceUtils.isJarURL(this.url)) {
URL actualUrl = ResourceUtils.extractJarFileURL(this.url);
- return ResourceUtils.getFile(actualUrl);
+ return ResourceHandlingUtils.getFile(actualUrl);
}
else {
return getFile();
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
index 9c8b001e96..d53233a1e1 100644
--- a/org.springframework.core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java
@@ -154,6 +154,7 @@ import org.springframework.util.StringUtils;
*
* @author Juergen Hoeller
* @author Colin Sampaleanu
+ * @author Marius Bogoevici
* @since 1.0.2
* @see #CLASSPATH_ALL_URL_PREFIX
* @see org.springframework.util.AntPathMatcher
@@ -334,8 +335,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
Resource[] rootDirResources = getResources(rootDirPath);
Set result = new LinkedHashSet(16);
for (Resource rootDirResource : rootDirResources) {
- rootDirResource = resolveRootDirResource(rootDirResource);
- if (isJarResource(rootDirResource)) {
+ if (ResourceHandlingUtils.useResourceHandlingDelegate(rootDirResource.getURL())) {
+ result.addAll(ResourceHandlingUtils.findMatchingResourcesByDelegate(rootDirResource, subPattern, getPathMatcher()));
+ } else if (isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern));
}
else {
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceHandlingDelegate.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceHandlingDelegate.java
new file mode 100644
index 0000000000..2599c6989c
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceHandlingDelegate.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002-2009 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URI;
+import java.util.Set;
+
+import org.springframework.core.io.Resource;
+import org.springframework.util.PathMatcher;
+
+/**
+ * Abstraction for a path matching strategy, for customizing the way in which a resource can be
+ * scanned for finding underlying resources that match a given pattern.
+ * Used for implementing application-server specific resource scanning strategies (e.g. for JBoss AS)
+ *
+ * @author Marius Bogoevici
+ *
+ */
+public interface ResourceHandlingDelegate {
+
+ boolean canHandleResource(URL url);
+
+ boolean canHandleResource(URI uri);
+
+ Set findMatchingResources(Resource rootResource, String subPattern, PathMatcher pathMatcher) throws
+ IOException;
+
+ Resource loadResource(URL url) throws IOException;
+
+ Resource loadResource(URI uri) throws IOException;
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceHandlingUtils.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceHandlingUtils.java
new file mode 100644
index 0000000000..a6a615d1d4
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/ResourceHandlingUtils.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2002-2007 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support;
+
+import java.net.URL;
+import java.net.URI;
+import java.util.Set;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.File;
+
+import org.springframework.util.ReflectionUtils;
+import org.springframework.util.PathMatcher;
+import org.springframework.util.ResourceUtils;
+import org.springframework.util.Assert;
+import org.springframework.core.io.support.jboss.VfsResourceHandlingDelegate;
+import org.springframework.core.io.Resource;
+
+/**
+ * Utility class for determining whether a given URL is a resource
+ * location that should receive special treatmen, such as looking up a
+ * resource in JBoss VFS.
+ *
+ * @author Thomas Risberg
+ * @author Marius Bogoevici
+ * @since 3.0
+ */
+public abstract class ResourceHandlingUtils {
+
+ private static ResourceHandlingDelegate resourceHandlingDelegate;
+
+ static {
+ try {
+ Class jBossVersionClass = PathMatchingResourcePatternResolver.class.getClassLoader().loadClass("org.jboss.Version");
+ Object versionObject = ReflectionUtils.invokeMethod(ReflectionUtils.findMethod(jBossVersionClass, "getInstance"), null);
+ Integer majorVersion = (Integer) ReflectionUtils.invokeMethod(ReflectionUtils.findMethod(jBossVersionClass, "getMajor"), versionObject);
+ // For JBoss AS versions 5 and higher
+ if (majorVersion >= 5) {
+ resourceHandlingDelegate = new VfsResourceHandlingDelegate();
+ }
+ }
+ catch (Throwable ex) {
+ // do nothing
+ }
+ }
+
+ public static File getFile(URL resourceUrl) throws FileNotFoundException {
+ return getFile(resourceUrl, "URL");
+ }
+
+ public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
+ Assert.notNull(resourceUrl, "Resource URL must not be null");
+ if (useResourceHandlingDelegate(resourceUrl)) {
+ try {
+ return resourceHandlingDelegate.loadResource(resourceUrl).getFile();
+ }
+ catch (IOException e) {
+ throw new FileNotFoundException(description + " cannot be resolved as a file resource");
+ }
+ }
+ return ResourceUtils.getFile(resourceUrl, description);
+ }
+
+ public static File getFile(URI resourceUri) throws FileNotFoundException {
+ return getFile(resourceUri, "URI");
+ }
+
+ public static File getFile(URI resourceUri, String description) throws FileNotFoundException {
+ Assert.notNull(resourceUri, "Resource URI must not be null");
+ if (useResourceHandlingDelegate(resourceUri)) {
+ try {
+ return resourceHandlingDelegate.loadResource(resourceUri).getFile();
+ }
+ catch (IOException e) {
+ throw new FileNotFoundException(description + " cannot be resolved as a file resource");
+ }
+ }
+ return ResourceUtils.getFile(resourceUri, description);
+ }
+
+ public static boolean useResourceHandlingDelegate(URL url) {
+ return resourceHandlingDelegate != null && resourceHandlingDelegate.canHandleResource(url);
+ }
+
+ public static boolean useResourceHandlingDelegate(URI uri) {
+ return resourceHandlingDelegate != null && resourceHandlingDelegate.canHandleResource(uri);
+ }
+
+ public static Set findMatchingResourcesByDelegate(Resource resource, String pattern, PathMatcher matcher) throws
+ IOException {
+ return resourceHandlingDelegate.findMatchingResources(resource, pattern, matcher);
+ }
+}
\ No newline at end of file
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/jboss/VfsResource.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/jboss/VfsResource.java
new file mode 100644
index 0000000000..2aef4f4e10
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/jboss/VfsResource.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2002-2009 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support.jboss;
+
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URISyntaxException;
+import java.net.URI;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.VFSUtils;
+
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.AbstractResource;
+import org.springframework.util.Assert;
+
+/**
+ * VFS based Resource.
+ *
+ * @author Ales Justin
+ */
+class VfsResource extends AbstractResource {
+
+ private VirtualFile file;
+
+ public VfsResource(VirtualFile file) {
+ Assert.notNull(file, "The file cannot be null.");
+ this.file = file;
+ }
+
+ public boolean exists() {
+ try {
+ return file.exists();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean isOpen() {
+ return false;
+ }
+
+ public boolean isReadable() {
+ try {
+ return file.getSize() > 0;
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public long lastModified() {
+ try {
+ return file.getLastModified();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public URL getURL() throws IOException {
+ try {
+ return file.toURL();
+ }
+ catch (URISyntaxException e) {
+ IOException ioe = new IOException(e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ public URI getURI() throws IOException {
+ try {
+ return file.toURI();
+ }
+ catch (URISyntaxException e) {
+ IOException ioe = new IOException(e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ public File getFile() throws IOException {
+ if (VFSUtils.isNestedFile(file)) {
+ throw new IOException("This resource is a nested resource: " + file);
+ }
+
+ try {
+ return new File(VFSUtils.getCompatibleURI(file));
+ }
+ catch (IOException e) {
+ throw e;
+ }
+ catch (Exception e) {
+ IOException ioe = new IOException(e.getMessage());
+ ioe.initCause(e);
+ throw ioe;
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public Resource createRelative(String relativePath) throws IOException {
+ return new VfsResource(file.findChild(relativePath));
+ }
+
+ public String getFilename() {
+ return file.getName();
+ }
+
+ public String getDescription() {
+ return file.toString();
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return file.openStream();
+ }
+
+ public String toString() {
+ return getDescription();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof VfsResource) {
+ return file.equals(((VfsResource)obj).file);
+ }
+ else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return this.file.hashCode();
+ }
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/core/io/support/jboss/VfsResourceHandlingDelegate.java b/org.springframework.core/src/main/java/org/springframework/core/io/support/jboss/VfsResourceHandlingDelegate.java
new file mode 100644
index 0000000000..8b04c73fd6
--- /dev/null
+++ b/org.springframework.core/src/main/java/org/springframework/core/io/support/jboss/VfsResourceHandlingDelegate.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2002-2009 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.core.io.support.jboss;
+
+import java.io.IOException;
+import java.io.File;
+import java.util.Set;
+import java.util.LinkedHashSet;
+import java.net.URL;
+import java.net.URI;
+
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.VirtualFileVisitor;
+import org.jboss.virtual.VisitorAttributes;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.ResourceHandlingDelegate;
+import org.springframework.util.PathMatcher;
+
+/**
+ * {@link org.springframework.core.io.support.ResourceHandlingDelegate} implementation
+ * for JBoss' Virtual File System.
+ *
+ * @author Marius Bogoevici
+ * @author Ales Justin
+ *
+ * Note: Thanks to David Ward from Alfresco for indicating a fix for path matching.
+ */
+public class VfsResourceHandlingDelegate implements ResourceHandlingDelegate {
+
+ public boolean canHandleResource(URL url) {
+ return url.getProtocol().startsWith("vfs");
+ }
+
+ public boolean canHandleResource(URI uri) {
+ return uri.getScheme().startsWith("vfs");
+ }
+
+
+ public Set findMatchingResources(Resource rootResource, String locationPattern, PathMatcher pathMatcher) throws IOException {
+ VirtualFile root = VFS.getRoot(rootResource.getURL());
+ PatternVirtualFileVisitor visitor = new PatternVirtualFileVisitor(root.getPathName(), locationPattern, pathMatcher);
+ root.visit(visitor);
+ return visitor.getResources();
+ }
+
+ public Resource loadResource(URL url) throws IOException{
+ return new VfsResource(VFS.getRoot(url));
+ }
+
+ public Resource loadResource(URI uri) throws IOException {
+ return new VfsResource(VFS.getRoot(uri));
+ }
+
+
+ protected static class PatternVirtualFileVisitor implements VirtualFileVisitor
+ {
+ private final String subPattern;
+ private final Set resources = new LinkedHashSet();
+ private final PathMatcher pathMatcher;
+ private final String rootPath;
+
+ private PatternVirtualFileVisitor(String rootPath, String subPattern, PathMatcher pathMatcher)
+ {
+ this.subPattern = subPattern;
+ this.pathMatcher = pathMatcher;
+ this.rootPath = rootPath.length() == 0 || rootPath.endsWith("/") ? rootPath : rootPath + "/";
+ }
+
+ public VisitorAttributes getAttributes()
+ {
+ return VisitorAttributes.RECURSE;
+ }
+
+ public void visit(VirtualFile vf)
+ {
+ if (pathMatcher.match(subPattern, vf.getPathName().substring(rootPath.length())))
+ resources.add(new VfsResource(vf));
+ }
+
+ public Set getResources()
+ {
+ return resources;
+ }
+
+ public int size()
+ {
+ return resources.size();
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("sub-pattern: ").append(subPattern);
+ buffer.append(", resources: ").append(resources);
+ return buffer.toString();
+ }
+ }
+
+}
diff --git a/org.springframework.core/src/main/java/org/springframework/util/ResourceUtils.java b/org.springframework.core/src/main/java/org/springframework/util/ResourceUtils.java
index bf52694bb7..5d71d08c38 100644
--- a/org.springframework.core/src/main/java/org/springframework/util/ResourceUtils.java
+++ b/org.springframework.core/src/main/java/org/springframework/util/ResourceUtils.java
@@ -256,7 +256,6 @@ public abstract class ResourceUtils {
String protocol = url.getProtocol();
return (URL_PROTOCOL_JAR.equals(protocol) ||
URL_PROTOCOL_ZIP.equals(protocol) ||
- URL_PROTOCOL_VFSZIP.equals(protocol) ||
URL_PROTOCOL_WSJAR.equals(protocol) ||
(URL_PROTOCOL_CODE_SOURCE.equals(protocol) && url.getPath().indexOf(JAR_URL_SEPARATOR) != -1));
}
diff --git a/org.springframework.core/template.mf b/org.springframework.core/template.mf
index d426e0c5a7..f1a5d532f4 100644
--- a/org.springframework.core/template.mf
+++ b/org.springframework.core/template.mf
@@ -10,6 +10,7 @@ Import-Template:
org.springframework.asm.*;version="[3.0.0, 3.0.1)";resolution:=optional,
org.apache.log4j.*;version="[1.2.15, 2.0.0)";resolution:=optional,
org.aspectj.*;version="[1.5.4, 2.0.0)";resolution:=optional,
+ org.jboss.virtual.*;version="[2.1.0.GA,2.1.0.GA]";resolution:=optional,
org.xml.sax.*;version="0";resolution:=optional,
org.w3c.dom.*;version="0";resolution:=optional
Ignored-Existing-Headers: