tamaya-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anat...@apache.org
Subject [16/27] incubator-tamaya git commit: TAMAYA-19: Reorganized dormant part for better focus of future discussions.
Date Sat, 03 Jan 2015 11:59:25 GMT
http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/resource/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resource/ReflectionUtils.java b/core/src/main/java/org/apache/tamaya/core/internal/resource/ReflectionUtils.java
new file mode 100644
index 0000000..391f7e8
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resource/ReflectionUtils.java
@@ -0,0 +1,192 @@
+/*
+* Copyright 2002-2014 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.apache.tamaya.core.internal.resource;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+* Simple utility class for working with the reflection API and handling
+* reflection exceptions.
+*
+* <p>Only intended for internal use.
+*
+* @author Juergen Hoeller
+* @author Rob Harrop
+* @author Rod Johnson
+* @author Costin Leau
+* @author Sam Brannen
+* @author Chris Beams
+* @since 1.2.2
+*/
+public abstract class ReflectionUtils {
+	/**
+	 * Cache for {@link Class#getDeclaredMethods()}, allowing for fast resolution.
+	 */
+	private static final Map<Class<?>, Method[]> declaredMethodsCache =
+			new ConcurrentHashMap<>(256);
+
+
+	/**
+	 * Attempt to find a {@link Field field} on the supplied {@link Class} with the
+	 * supplied {@code name}. Searches all superclasses up to {@link Object}.
+	 * @param clazz the class to introspect
+	 * @param name the name current the field
+	 * @return the corresponding Field object, or {@code null} if not found
+	 */
+	public static Field findField(Class<?> clazz, String name) {
+		return findField(clazz, name, null);
+	}
+
+	/**
+	 * Attempt to find a {@link Field field} on the supplied {@link Class} with the
+	 * supplied {@code name} and/or {@link Class type}. Searches all superclasses
+	 * up to {@link Object}.
+	 * @param clazz the class to introspect
+	 * @param name the name current the field (may be {@code null} if type is specified)
+	 * @param type the type current the field (may be {@code null} if name is specified)
+	 * @return the corresponding Field object, or {@code null} if not found
+	 */
+	public static Field findField(Class<?> clazz, String name, Class<?> type) {
+		Objects.requireNonNull(clazz, "Class must not be null");
+		if(name == null && type == null) throw new IllegalArgumentException("Either name or type current the field must be specified");
+		Class<?> searchType = clazz;
+		while (!Object.class.equals(searchType) && searchType != null) {
+			Field[] fields = searchType.getDeclaredFields();
+			for (Field field : fields) {
+				if ((name == null || name.equals(field.getName())) && (type == null || type.equals(field.getType()))) {
+					return field;
+				}
+			}
+			searchType = searchType.getSuperclass();
+		}
+		return null;
+	}
+
+	/**
+	 * Attempt to find a {@link Method} on the supplied class with the supplied name
+	 * and no parameters. Searches all superclasses up to {@code Object}.
+	 * <p>Returns {@code null} if no {@link Method} can be found.
+	 * @param clazz the class to introspect
+	 * @param name the name current the method
+	 * @return the Method object, or {@code null} if none found
+	 */
+	public static Method findMethod(Class<?> clazz, String name) {
+		return findMethod(clazz, name, new Class<?>[0]);
+	}
+
+	/**
+	 * Attempt to find a {@link Method} on the supplied class with the supplied name
+	 * and parameter types. Searches all superclasses up to {@code Object}.
+	 * <p>Returns {@code null} if no {@link Method} can be found.
+	 * @param clazz the class to introspect
+	 * @param name the name current the method
+	 * @param paramTypes the parameter types current the method
+	 * (may be {@code null} to indicate any signature)
+	 * @return the Method object, or {@code null} if none found
+	 */
+	public static Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
+		Objects.requireNonNull(clazz, "Class must not be null");
+		Objects.requireNonNull(name, "Method name must not be null");
+		Class<?> searchType = clazz;
+		while (searchType != null) {
+			Method[] methods = (searchType.isInterface() ? searchType.getMethods() : getDeclaredMethods(searchType));
+			for (Method method : methods) {
+				if (name.equals(method.getName()) &&
+						(paramTypes == null || Arrays.equals(paramTypes, method.getParameterTypes()))) {
+					return method;
+				}
+			}
+			searchType = searchType.getSuperclass();
+		}
+		return null;
+	}
+
+	/**
+	 * Handle the given reflection exception. Should only be called if no
+	 * checked exception is expected to be thrown by the target method.
+	 * <p>Throws the underlying RuntimeException or Error in case current an
+	 * InvocationTargetException with such a root cause. Throws an
+	 * IllegalStateException with an appropriate message else.
+	 * @param ex the reflection exception to handle
+	 */
+	public static void handleReflectionException(Exception ex) {
+		if (ex instanceof NoSuchMethodException) {
+			throw new IllegalStateException("Method not found: " + ex.getMessage());
+		}
+		if (ex instanceof IllegalAccessException) {
+			throw new IllegalStateException("Could not access method: " + ex.getMessage());
+		}
+		if (ex instanceof InvocationTargetException) {
+			handleInvocationTargetException((InvocationTargetException) ex);
+		}
+		if (ex instanceof RuntimeException) {
+			throw (RuntimeException) ex;
+		}
+		throw new UndeclaredThrowableException(ex);
+	}
+
+	/**
+	 * Handle the given invocation target exception. Should only be called if no
+	 * checked exception is expected to be thrown by the target method.
+	 * <p>Throws the underlying RuntimeException or Error in case current such a root
+	 * cause. Throws an IllegalStateException else.
+	 * @param ex the invocation target exception to handle
+	 */
+	public static void handleInvocationTargetException(InvocationTargetException ex) {
+		rethrowRuntimeException(ex.getTargetException());
+	}
+
+	/**
+	 * Rethrow the given {@link Throwable exception}, which is presumably the
+	 * <em>target exception</em> current an {@link InvocationTargetException}. Should
+	 * only be called if no checked exception is expected to be thrown by the
+	 * target method.
+	 * <p>Rethrows the underlying exception cast to an {@link RuntimeException} or
+	 * {@link Error} if appropriate; otherwise, throws an
+	 * {@link IllegalStateException}.
+	 * @param ex the exception to rethrow
+	 * @throws RuntimeException the rethrown exception
+	 */
+	public static void rethrowRuntimeException(Throwable ex) {
+		if (ex instanceof RuntimeException) {
+			throw (RuntimeException) ex;
+		}
+		if (ex instanceof Error) {
+			throw (Error) ex;
+		}
+		throw new UndeclaredThrowableException(ex);
+	}
+
+	/**
+	 * This method retrieves {@link Class#getDeclaredMethods()} from a local cache
+	 * in order to avoid the JVM's SecurityManager check and defensive array copying.
+	 */
+	private static Method[] getDeclaredMethods(Class<?> clazz) {
+		Method[] result = declaredMethodsCache.get(clazz);
+		if (result == null) {
+			result = clazz.getDeclaredMethods();
+			declaredMethodsCache.put(clazz, result);
+		}
+		return result;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/resource/ResourceUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resource/ResourceUtils.java b/core/src/main/java/org/apache/tamaya/core/internal/resource/ResourceUtils.java
new file mode 100644
index 0000000..a9979f1
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resource/ResourceUtils.java
@@ -0,0 +1,257 @@
+/*
+* Copyright 2002-2014 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.apache.tamaya.core.internal.resource;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Objects;
+
+/**
+* Utility methods for resolving resource locations to files in the
+* file system. Mainly for internal use within the framework.
+*
+* <p>Consider using Spring's Resource abstraction in the core package
+* for handling all kinds current file resources in a uniform manner.
+* {@code org.springframework.core.io.ResourceLoader}'s {@code getResource()}
+* method can resolve any location to a {@code org.springframework.core.io.Resource}
+* object, which in turn allows one to obtain a {@code java.io.File} in the
+* file system through its {@code getFile()} method.
+*
+* <p>The main reason for these utility methods for resource location handling
+* is to support {@code Log4jConfigurer}, which must be able to resolve
+* resource locations <i>before the logging system has been initialized</i>.
+* Spring's {@code Resource} abstraction in the core package, on the other hand,
+* already expects the logging system to be available.
+*
+* @author Juergen Hoeller
+* @since 1.1.5
+*/
+final class ResourceUtils {
+
+	/** URL prefix for loading from the file system: "file:" */
+	public static final String FILE_URL_PREFIX = "file:";
+
+	/** URL prefix for loading from the file system: "jar:" */
+	public static final String JAR_URL_PREFIX = "jar:";
+
+	/** URL protocol for a file in the file system: "file" */
+	public static final String URL_PROTOCOL_FILE = "file";
+
+	/** URL protocol for an entry from a jar file: "jar" */
+	public static final String URL_PROTOCOL_JAR = "jar";
+
+	/** URL protocol for an entry from a zip file: "zip" */
+	public static final String URL_PROTOCOL_ZIP = "zip";
+
+	/** URL protocol for an entry from a WebSphere jar file: "wsjar" */
+	public static final String URL_PROTOCOL_WSJAR = "wsjar";
+
+	/** URL protocol for an entry from a JBoss jar file: "vfszip" */
+	public static final String URL_PROTOCOL_VFSZIP = "vfszip";
+
+	/** URL protocol for a JBoss file system resource: "vfsfile" */
+	public static final String URL_PROTOCOL_VFSFILE = "vfsfile";
+
+	/** URL protocol for a general JBoss VFS resource: "vfs" */
+	public static final String URL_PROTOCOL_VFS = "vfs";
+
+	/** File extension for a regular jar file: ".jar" */
+	public static final String JAR_FILE_EXTENSION = ".jar";
+
+	/** Separator between JAR URL and file path within the JAR: "!/" */
+	public static final String JAR_URL_SEPARATOR = "!/";
+
+    /**
+     * Singleton constructor.
+     */
+    private ResourceUtils(){}
+
+	/**
+	 * Resolve the given resource URL to a {@code java.io.File},
+	 * i.e. to a file in the file system.
+	 * @param resourceUrl the resource URL to resolve
+	 * @return a corresponding File object
+	 * @throws FileNotFoundException if the URL cannot be resolved to
+	 * a file in the file system
+	 */
+	public static File getFile(URL resourceUrl) throws FileNotFoundException {
+		return getFile(resourceUrl, "URL");
+	}
+
+	/**
+	 * Resolve the given resource URL to a {@code java.io.File},
+	 * i.e. to a file in the file system.
+	 * @param resourceUrl the resource URL to resolve
+	 * @param description a description current the original resource that
+	 * the URL was created for (for example, a class path location)
+	 * @return a corresponding File object
+	 * @throws FileNotFoundException if the URL cannot be resolved to
+	 * a file in the file system
+	 */
+	public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
+		Objects.requireNonNull(resourceUrl, "Resource URL must not be null");
+		if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) {
+			throw new FileNotFoundException(
+					description + " cannot be resolved to absolute file path " +
+					"because it does not reside in the file system: " + resourceUrl);
+		}
+		try {
+			return new File(toURI(resourceUrl).getSchemeSpecificPart());
+		}
+		catch (URISyntaxException ex) {
+			// Fallback for URLs that are not valid URIs (should hardly ever happen).
+			return new File(resourceUrl.getFile());
+		}
+	}
+
+	/**
+	 * Resolve the given resource URI to a {@code java.io.File},
+	 * i.e. to a file in the file system.
+	 * @param resourceUri the resource URI to resolve
+	 * @return a corresponding File object
+	 * @throws FileNotFoundException if the URL cannot be resolved to
+	 * a file in the file system
+	 */
+	public static File getFile(URI resourceUri) throws FileNotFoundException {
+		return getFile(resourceUri, "URI");
+	}
+
+	/**
+	 * Resolve the given resource URI to a {@code java.io.File},
+	 * i.e. to a file in the file system.
+	 * @param resourceUri the resource URI to resolve
+	 * @param description a description current the original resource that
+	 * the URI was created for (for example, a class path location)
+	 * @return a corresponding File object
+	 * @throws FileNotFoundException if the URL cannot be resolved to
+	 * a file in the file system
+	 */
+	public static File getFile(URI resourceUri, String description) throws FileNotFoundException {
+		Objects.requireNonNull(resourceUri, "Resource URI must not be null");
+		if (!URL_PROTOCOL_FILE.equals(resourceUri.getScheme())) {
+			throw new FileNotFoundException(
+					description + " cannot be resolved to absolute file path " +
+					"because it does not reside in the file system: " + resourceUri);
+		}
+		return new File(resourceUri.getSchemeSpecificPart());
+	}
+
+	/**
+	 * Determine whether the given URL points to a resource in the file system,
+	 * that is, has protocol "file", "vfsfile" or "vfs".
+	 * @param url the URL to check
+	 * @return whether the URL has been identified as a file system URL
+	 */
+	public static boolean isFileURL(URL url) {
+		String protocol = url.getProtocol();
+		return (URL_PROTOCOL_FILE.equals(protocol) || URL_PROTOCOL_VFSFILE.equals(protocol) ||
+				URL_PROTOCOL_VFS.equals(protocol));
+	}
+
+	/**
+	 * Determine whether the given URL points to a resource in a jar file,
+	 * that is, has protocol "jar", "zip", "vfszip" or "wsjar".
+	 * @param url the URL to check
+	 * @return whether the URL has been identified as a JAR URL
+	 */
+	public static boolean isJarURL(URL url) {
+		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));
+	}
+
+	/**
+	 * Determine whether the given URL points to a jar file itself,
+	 * that is, has protocol "file" and ends with the ".jar" extension.
+	 * @param url the URL to check
+	 * @return whether the URL has been identified as a JAR file URL
+	 * @since 4.1
+	 */
+	public static boolean isJarFileURL(URL url) {
+		return (URL_PROTOCOL_FILE.equals(url.getProtocol()) &&
+				url.getPath().toLowerCase().endsWith(JAR_FILE_EXTENSION));
+	}
+
+	/**
+	 * Extract the URL for the actual jar file from the given URL
+	 * (which may point to a resource in a jar file or to a jar file itself).
+	 * @param jarUrl the original URL
+	 * @return the URL for the actual jar file
+	 * @throws MalformedURLException if no valid jar file URL could be extracted
+	 */
+	public static URL extractJarFileURL(URL jarUrl) throws MalformedURLException {
+		String urlFile = jarUrl.getFile();
+		int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
+		if (separatorIndex != -1) {
+			String jarFile = urlFile.substring(0, separatorIndex);
+			try {
+				return new URL(jarFile);
+			}
+			catch (MalformedURLException ex) {
+				// Probably no protocol in original jar URL, like "jar:C:/mypath/myjar.jar".
+				// This usually indicates that the jar file resides in the file system.
+				if (!jarFile.startsWith("/")) {
+					jarFile = "/" + jarFile;
+				}
+				return new URL(FILE_URL_PREFIX + jarFile);
+			}
+		}
+		else {
+			return jarUrl;
+		}
+	}
+
+	/**
+	 * Create a URI instance for the given URL,
+	 * replacing spaces with "%20" URI encoding first.
+	 * <p>Furthermore, this method works on JDK 1.4 as well,
+	 * in contrast to the {@code URL.toURI()} method.
+	 * @param url the URL to convert into a URI instance
+	 * @return the URI instance
+	 * @throws URISyntaxException if the URL wasn't a valid URI
+	 * @see java.net.URL#toURI()
+	 */
+	public static URI toURI(URL url) throws URISyntaxException {
+		return toURI(url.toString());
+	}
+
+	/**
+	 * Create a URI instance for the given location String,
+	 * replacing spaces with "%20" URI encoding first.
+	 * @param location the location String to convert into a URI instance
+	 * @return the URI instance
+	 * @throws URISyntaxException if the location wasn't a valid URI
+	 */
+	public static URI toURI(String location) throws URISyntaxException {
+		return new URI(location.replaceAll(" ", "%20"));
+	}
+
+	/**
+	 * Set the {@link URLConnection#setUseCaches "useCaches"} flag on the
+	 * given connection, preferring {@code false} but leaving the
+	 * flag at {@code true} for JNLP based resources.
+	 * @param con the URLConnection to set the flag on
+	 */
+	public static void useCachesIfNecessary(URLConnection con) {
+		con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/resource/UrlResource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resource/UrlResource.java b/core/src/main/java/org/apache/tamaya/core/internal/resource/UrlResource.java
new file mode 100644
index 0000000..6011109
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resource/UrlResource.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2002-2013 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.apache.tamaya.core.internal.resource;
+
+import org.apache.tamaya.core.util.StringUtils;
+import org.apache.tamaya.core.resources.Resource;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Objects;
+
+/**
+ * {@link Resource} implementation for {@code java.net.URL} locators.
+ * Obviously supports resolution as URL, and also as File in case current
+ * the "file:" protocol.
+ *
+ * @author Juergen Hoeller
+ * @since 28.12.2003
+ * @see java.net.URL
+ */
+public class UrlResource extends AbstractFileResolvingResource {
+
+    /**
+     * Original URI, if available; used for URI and File access.
+     */
+    private final URI uri;
+
+    /**
+     * Original URL, used for actual access.
+     */
+    private final URL url;
+
+    /**
+     * Cleaned URL (with normalized path), used for comparisons.
+     */
+    private final URL cleanedUrl;
+
+
+    /**
+     * Create a new UrlResource based on the given URI object.
+     * @param uri a URI
+     * @throws MalformedURLException if the given URL path is not valid
+     */
+    public UrlResource(URI uri) throws MalformedURLException {
+        Objects.requireNonNull(uri, "URI must not be null");
+        this.uri = uri;
+        this.url = uri.toURL();
+        this.cleanedUrl = getCleanedUrl(this.url, uri.toString());
+    }
+
+    /**
+     * Create a new UrlResource based on the given URL object.
+     * @param url a URL
+     */
+    public UrlResource(URL url) {
+        Objects.requireNonNull(url, "URL must not be null");
+        this.url = url;
+        this.cleanedUrl = getCleanedUrl(this.url, url.toString());
+        this.uri = null;
+    }
+
+    /**
+     * Create a new UrlResource based on a URL path.
+     * <p>Note: The given path needs to be pre-encoded if necessary.
+     * @param path a URL path
+     * @throws MalformedURLException if the given URL path is not valid
+     * @see java.net.URL#URL(String)
+     */
+    public UrlResource(String path) throws MalformedURLException {
+        Objects.requireNonNull(path, "Path must not be null");
+        this.uri = null;
+        this.url = new URL(path);
+        this.cleanedUrl = getCleanedUrl(this.url, path);
+    }
+
+    /**
+     * Create a new UrlResource based on a URI specification.
+     * <p>The given parts will automatically get encoded if necessary.
+     * @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);
+     * also known as "scheme"
+     * @param location the location (e.g. the file path within that protocol);
+     * also known as "scheme-specific part"
+     * @throws MalformedURLException if the given URL specification is not valid
+     * @see java.net.URI#URI(String, String, String)
+     */
+    public UrlResource(String protocol, String location) throws MalformedURLException  {
+        this(protocol, location, null);
+    }
+
+    /**
+     * Create a new UrlResource based on a URI specification.
+     * <p>The given parts will automatically get encoded if necessary.
+     * @param protocol the URL protocol to use (e.g. "jar" or "file" - without colon);
+     * also known as "scheme"
+     * @param location the location (e.g. the file path within that protocol);
+     * also known as "scheme-specific part"
+     * @param fragment the fragment within that location (e.g. anchor on an HTML page,
+     * as following after a "#" separator)
+     * @throws MalformedURLException if the given URL specification is not valid
+     * @see java.net.URI#URI(String, String, String)
+     */
+    public UrlResource(String protocol, String location, String fragment) throws MalformedURLException  {
+        try {
+            this.uri = new URI(protocol, location, fragment);
+            this.url = this.uri.toURL();
+            this.cleanedUrl = getCleanedUrl(this.url, this.uri.toString());
+        }
+        catch (URISyntaxException ex) {
+            MalformedURLException exToThrow = new MalformedURLException(ex.getMessage());
+            exToThrow.initCause(ex);
+            throw exToThrow;
+        }
+    }
+
+    /**
+     * Determine a cleaned URL for the given original URL.
+     * @param originalUrl the original URL
+     * @param originalPath the original URL path
+     * @return the cleaned URL
+     */
+    private URL getCleanedUrl(URL originalUrl, String originalPath) {
+        try {
+            return new URL(StringUtils.cleanPath(originalPath));
+        }
+        catch (MalformedURLException ex) {
+            // Cleaned URL path cannot be converted to URL
+            // -> take original URL.
+            return originalUrl;
+        }
+    }
+
+
+    /**
+     * This implementation opens an InputStream for the given URL.
+     * It sets the "UseCaches" flag to {@code false},
+     * mainly to avoid jar file locking on Windows.
+     * @see java.net.URL#openConnection()
+     * @see java.net.URLConnection#setUseCaches(boolean)
+     * @see java.net.URLConnection#getInputStream()
+     */
+    @Override
+    public InputStream getInputStream()throws IOException {
+        URLConnection con = null;
+        try {
+            con = this.url.openConnection();
+            useCachesIfNecessary(con);
+            return con.getInputStream();
+        }
+        catch (IOException ex) {
+            // Close the HTTP connection (if applicable).
+            if (con instanceof HttpURLConnection) {
+                ((HttpURLConnection) con).disconnect();
+            }
+            throw ex;
+        }
+    }
+
+    /**
+     * This implementation returns the underlying URL reference.
+     */
+    @Override
+    public URL toURL() throws IOException {
+        return this.url;
+    }
+
+    /**
+     * This implementation returns the underlying URI directly,
+     * if possible.
+     */
+    @Override
+    public URI getURI() throws IOException {
+        if (this.uri != null) {
+            return this.uri;
+        }
+        else {
+            return super.getURI();
+        }
+    }
+
+    /**
+     * This implementation returns a File reference for the underlying URL/URI,
+     * provided that it refers to a file in the file system.
+     */
+    @Override
+    public File toFile() throws IOException {
+        if (this.uri != null) {
+            return super.getFile(this.uri);
+        }
+        else {
+            return super.toFile();
+        }
+    }
+
+    /**
+     * This implementation creates a UrlResource, applying the given path
+     * relative to the path current the underlying URL current this resource descriptor.
+     * @see java.net.URL#URL(java.net.URL, String)
+     */
+    @Override
+    public Resource createRelative(String relativePath) throws MalformedURLException {
+        if (relativePath.startsWith("/")) {
+            relativePath = relativePath.substring(1);
+        }
+        return new UrlResource(new URL(this.url, relativePath));
+    }
+
+    /**
+     * This implementation returns the name current the file that this URL refers to.
+     * @see java.net.URL#getFile()
+     * @see java.io.File#getName()
+     */
+    @Override
+    public String getDisplayName() {
+        return new File(this.url.getFile()).getName();
+    }
+
+    /**
+     * This implementation returns a description that includes the URL.
+     */
+    @Override
+    public String toString() {
+        return "URL [" + this.url + "]";
+    }
+
+
+    /**
+     * This implementation compares the underlying URL references.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        return (obj == this ||
+                (obj instanceof UrlResource && this.cleanedUrl.equals(((UrlResource) obj).cleanedUrl)));
+    }
+
+    /**
+     * This implementation returns the hash code current the underlying URL reference.
+     */
+    @Override
+    public int hashCode() {
+        return this.cleanedUrl.hashCode();
+    }
+
+    	/**
+	 * Set the {@link URLConnection#setUseCaches "useCaches"} flag on the
+	 * given connection, preferring {@code false} but leaving the
+	 * flag at {@code true} for JNLP based resources.
+	 * @param con the URLConnection to set the flag on
+	 */
+	private void useCachesIfNecessary(URLConnection con) {
+		con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
+	}
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsResource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsResource.java b/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsResource.java
new file mode 100644
index 0000000..b39a907
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsResource.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2002-2014 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.apache.tamaya.core.internal.resource;
+
+import org.apache.tamaya.core.resources.Resource;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
+import java.util.Objects;
+
+/**
+ * JBoss VFS based {@link Resource} implementation.
+ *
+ * <p>As current Spring 4.0, this class supports VFS 3.x on JBoss AS 6+ (package
+ * {@code org.jboss.vfs}) and is in particular compatible with JBoss AS 7 and
+ * WildFly 8.
+ *
+ * @author Ales Justin
+ * @author Juergen Hoeller
+ * @author Costin Leau
+ * @since 3.0
+ */
+public class VfsResource implements Resource {
+
+	private final Object resource;
+
+
+	public VfsResource(Object resource) {
+		Objects.requireNonNull(resource, "VirtualFile must not be null");
+		this.resource = resource;
+	}
+
+
+	@Override
+	public InputStream getInputStream()throws IOException {
+        return VfsUtils.getInputStream(this.resource);
+    }
+
+	@Override
+	public boolean exists() {
+		return VfsUtils.exists(this.resource);
+	}
+
+	@Override
+	public boolean isReadable() {
+		return VfsUtils.isReadable(this.resource);
+	}
+
+	@Override
+	public URL toURL() throws IOException {
+		try {
+			return VfsUtils.getURL(this.resource);
+		}
+		catch (Exception ex) {
+			throw new IllegalStateException("Failed to obtain URL for file " + this.resource, ex);
+		}
+	}
+
+	@Override
+	public URI getURI() throws IOException {
+		try {
+			return VfsUtils.getURI(this.resource);
+		}
+		catch (Exception ex) {
+			throw new IllegalStateException("Failed to obtain URI for " + this.resource, ex);
+		}
+	}
+
+	@Override
+	public File toFile() throws IOException {
+		return VfsUtils.getFile(this.resource);
+	}
+
+	@Override
+	public long contentLength() throws IOException {
+		return VfsUtils.getSize(this.resource);
+	}
+
+	@Override
+	public long lastModified() throws IOException {
+		return VfsUtils.getLastModified(this.resource);
+	}
+
+	@Override
+	public Resource createRelative(String relativePath) throws IOException {
+		if (!relativePath.startsWith(".") && relativePath.contains("/")) {
+			try {
+				return new VfsResource(VfsUtils.getChild(this.resource, relativePath));
+			}
+			catch (IOException ex) {
+				// fall back to getRelative
+			}
+		}
+
+		return new VfsResource(VfsUtils.getRelative(new URL(toURL(), relativePath)));
+	}
+
+	@Override
+	public String getDisplayName() {
+		return VfsUtils.getName(this.resource);
+	}
+
+	@Override
+	public String toString() {
+		return this.resource.toString();
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		return (obj == this || (obj instanceof VfsResource && this.resource.equals(((VfsResource) obj).resource)));
+	}
+
+	@Override
+	public int hashCode() {
+		return this.resource.hashCode();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsUtils.java b/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsUtils.java
new file mode 100644
index 0000000..60fc452
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/resource/VfsUtils.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2002-2014 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.apache.tamaya.core.internal.resource;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.*;
+import java.net.URI;
+import java.net.URL;
+
+/**
+ * Utility for detecting and accessing JBoss VFS in the classpath.
+ *
+ * <p>As current Spring 4.0, this class supports VFS 3.x on JBoss AS 6+ (package
+ * {@code org.jboss.vfs}) and is in particular compatible with JBoss AS 7 and
+ * WildFly 8.
+ *
+ * <p>Thanks go to Marius Bogoevici for the initial patch.
+ * <b>Note:</b> This is an internal class and should not be used outside the framework.
+ *
+ * @author Costin Leau
+ * @author Juergen Hoeller
+ * @since 3.0.3
+ */
+class VfsUtils {
+
+	private static final String VFS3_PKG = "org.jboss.vfs.";
+	private static final String VFS_NAME = "VFS";
+
+	private static Method VFS_METHOD_GET_ROOT_URL = null;
+	private static Method VFS_METHOD_GET_ROOT_URI = null;
+
+	private static Method VIRTUAL_FILE_METHOD_EXISTS = null;
+	private static Method VIRTUAL_FILE_METHOD_GET_INPUT_STREAM;
+	private static Method VIRTUAL_FILE_METHOD_GET_SIZE;
+	private static Method VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED;
+	private static Method VIRTUAL_FILE_METHOD_TO_URL;
+	private static Method VIRTUAL_FILE_METHOD_TO_URI;
+	private static Method VIRTUAL_FILE_METHOD_GET_NAME;
+	private static Method VIRTUAL_FILE_METHOD_GET_PATH_NAME;
+	private static Method VIRTUAL_FILE_METHOD_GET_CHILD;
+
+	protected static Class<?> VIRTUAL_FILE_VISITOR_INTERFACE;
+	protected static Method VIRTUAL_FILE_METHOD_VISIT;
+
+	private static Field VISITOR_ATTRIBUTES_FIELD_RECURSE = null;
+	private static Method GET_PHYSICAL_FILE = null;
+
+	static {
+		ClassLoader loader = VfsUtils.class.getClassLoader();
+		try {
+			Class<?> vfsClass = loader.loadClass(VFS3_PKG + VFS_NAME);
+			VFS_METHOD_GET_ROOT_URL = ReflectionUtils.findMethod(vfsClass, "getChild", URL.class);
+			VFS_METHOD_GET_ROOT_URI = ReflectionUtils.findMethod(vfsClass, "getChild", URI.class);
+
+			Class<?> virtualFile = loader.loadClass(VFS3_PKG + "VirtualFile");
+			VIRTUAL_FILE_METHOD_EXISTS = ReflectionUtils.findMethod(virtualFile, "exists");
+			VIRTUAL_FILE_METHOD_GET_INPUT_STREAM = ReflectionUtils.findMethod(virtualFile, "openStream");
+			VIRTUAL_FILE_METHOD_GET_SIZE = ReflectionUtils.findMethod(virtualFile, "getSize");
+			VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED = ReflectionUtils.findMethod(virtualFile, "getLastModified");
+			VIRTUAL_FILE_METHOD_TO_URI = ReflectionUtils.findMethod(virtualFile, "toURI");
+			VIRTUAL_FILE_METHOD_TO_URL = ReflectionUtils.findMethod(virtualFile, "toURL");
+			VIRTUAL_FILE_METHOD_GET_NAME = ReflectionUtils.findMethod(virtualFile, "getName");
+			VIRTUAL_FILE_METHOD_GET_PATH_NAME = ReflectionUtils.findMethod(virtualFile, "getPathName");
+			GET_PHYSICAL_FILE = ReflectionUtils.findMethod(virtualFile, "getPhysicalFile");
+			VIRTUAL_FILE_METHOD_GET_CHILD = ReflectionUtils.findMethod(virtualFile, "getChild", String.class);
+
+			VIRTUAL_FILE_VISITOR_INTERFACE = loader.loadClass(VFS3_PKG + "VirtualFileVisitor");
+			VIRTUAL_FILE_METHOD_VISIT = ReflectionUtils.findMethod(virtualFile, "visit", VIRTUAL_FILE_VISITOR_INTERFACE);
+
+			Class<?> visitorAttributesClass = loader.loadClass(VFS3_PKG + "VisitorAttributes");
+			VISITOR_ATTRIBUTES_FIELD_RECURSE = ReflectionUtils.findField(visitorAttributesClass, "RECURSE");
+		}
+		catch (ClassNotFoundException ex) {
+			throw new IllegalStateException("Could not detect JBoss VFS infrastructure", ex);
+		}
+	}
+
+    private VfsUtils(){}
+
+    static void visit(Object resource, InvocationHandler visitor) throws IOException {
+        Object visitorProxy = Proxy.newProxyInstance(
+                VIRTUAL_FILE_VISITOR_INTERFACE.getClassLoader(),
+                new Class<?>[]{VIRTUAL_FILE_VISITOR_INTERFACE}, visitor);
+        invokeVfsMethod(VIRTUAL_FILE_METHOD_VISIT, resource, visitorProxy);
+    }
+
+	protected static Object invokeVfsMethod(Method method, Object target, Object... args) throws IOException {
+		try {
+			return method.invoke(target, args);
+		}
+		catch (InvocationTargetException ex) {
+			Throwable targetEx = ex.getTargetException();
+			if (targetEx instanceof IOException) {
+				throw (IOException) targetEx;
+			}
+			ReflectionUtils.handleInvocationTargetException(ex);
+		}
+		catch (Exception ex) {
+			ReflectionUtils.handleReflectionException(ex);
+		}
+
+		throw new IllegalStateException("Invalid code path reached");
+	}
+
+	static boolean exists(Object vfsResource) {
+		try {
+			return (Boolean) invokeVfsMethod(VIRTUAL_FILE_METHOD_EXISTS, vfsResource);
+		}
+		catch (IOException ex) {
+			return false;
+		}
+	}
+
+	static boolean isReadable(Object vfsResource) {
+		try {
+			return ((Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_SIZE, vfsResource) > 0);
+		}
+		catch (IOException ex) {
+			return false;
+		}
+	}
+
+	static long getSize(Object vfsResource) throws IOException {
+		return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_SIZE, vfsResource);
+	}
+
+	static long getLastModified(Object vfsResource) throws IOException {
+		return (Long) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_LAST_MODIFIED, vfsResource);
+	}
+
+	static InputStream getInputStream(Object vfsResource) throws IOException {
+		return (InputStream) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_INPUT_STREAM, vfsResource);
+	}
+
+	static URL getURL(Object vfsResource) throws IOException {
+		return (URL) invokeVfsMethod(VIRTUAL_FILE_METHOD_TO_URL, vfsResource);
+	}
+
+	static URI getURI(Object vfsResource) throws IOException {
+		return (URI) invokeVfsMethod(VIRTUAL_FILE_METHOD_TO_URI, vfsResource);
+	}
+
+	static String getName(Object vfsResource) {
+		try {
+			return (String) invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_NAME, vfsResource);
+		}
+		catch (IOException ex) {
+			throw new IllegalStateException("Cannot get resource name", ex);
+		}
+	}
+
+	static Object getRelative(URL url) throws IOException {
+		return invokeVfsMethod(VFS_METHOD_GET_ROOT_URL, null, url);
+	}
+
+	static Object getChild(Object vfsResource, String path) throws IOException {
+		return invokeVfsMethod(VIRTUAL_FILE_METHOD_GET_CHILD, vfsResource, path);
+	}
+
+	static File getFile(Object vfsResource) throws IOException {
+		return (File) invokeVfsMethod(GET_PHYSICAL_FILE, vfsResource);
+	}
+
+	static Object getRoot(URI url) throws IOException {
+		return invokeVfsMethod(VFS_METHOD_GET_ROOT_URI, null, url);
+	}
+
+	// protected methods used by the support sub-package
+
+	protected static Object getRoot(URL url) throws IOException {
+		return invokeVfsMethod(VFS_METHOD_GET_ROOT_URL, null, url);
+	}
+
+	protected static Object getVisitorAttribute() {
+		try{
+            return VISITOR_ATTRIBUTES_FIELD_RECURSE.get(null);
+        }
+        catch(Exception e){
+            ReflectionUtils.handleReflectionException(e);
+            return null; // never called
+        }
+	}
+
+	protected static String getPath(Object resource) {
+		try{
+            return (String) VIRTUAL_FILE_METHOD_GET_PATH_NAME.invoke(resource);
+        }
+        catch(Exception e){
+            ReflectionUtils.handleReflectionException(e);
+            return null; // never called
+        }
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/resources/InputStreamSource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/resources/InputStreamSource.java b/core/src/main/java/org/apache/tamaya/core/resources/InputStreamSource.java
new file mode 100644
index 0000000..dfe6cf7
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/resources/InputStreamSource.java
@@ -0,0 +1,46 @@
+/*
+* Copyright 2002-2012 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.apache.tamaya.core.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+* Simple interface for objects that are sources for an {@link InputStream}.
+*
+* <p>This is the base interface for the more extensive {@link Resource} interface.
+*
+* @author Juergen Hoeller
+* @since 20.01.2004
+* @see java.io.InputStream
+* @see Resource
+*/
+@FunctionalInterface
+public interface InputStreamSource {
+
+	/**
+	 * Return an {@link InputStream}.
+	 * <p>It is expected that each call creates a <i>fresh</i> stream.
+	 * <p>This requirement is particularly important when you consider an API such
+	 * as JavaMail, which needs to be able to read the stream multiple times when
+	 * creating mail attachments. For such a use case, it is <i>required</i>
+	 * that each {@code getInputStreamSupplier()} call returns a fresh stream.
+	 * @return the input stream for the underlying resource (must not be {@code null})
+	 * @throws IOException if the stream could not be opened
+	 */
+	InputStream getInputStream() throws IOException;
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/resources/Resource.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/resources/Resource.java b/core/src/main/java/org/apache/tamaya/core/resources/Resource.java
new file mode 100644
index 0000000..7ab27dc
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/resources/Resource.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2002-2012 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.apache.tamaya.core.resources;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Objects;
+
+/**
+ * Interface for a resource descriptor that abstracts from the actual
+ * type current underlying resource, such as a file or class path resource.
+ *
+ * <p>An InputStream can be opened for every resource if it exists in
+ * physical form, but a URL or File handle can just be returned for
+ * certain resources. The actual behavior is implementation-specific.
+ *
+ * @author Juergen Hoeller
+ * @since 28.12.2003
+ * @see #getInputStream()
+ * @see #toURL()
+ * @see #getURI()
+ * @see #toFile()
+ */
+public interface Resource extends InputStreamSource {
+
+	/**
+	 * Return whether this resource actually exists in physical form.
+	 * <p>This method performs a definitive existence check, whereas the
+	 * existence current a {@code Resource} handle only guarantees a
+	 * valid descriptor handle.
+	 */
+    default boolean exists() {
+        // Try file existence: can we find the file in the file system?
+        try {
+            return toFile().exists();
+        }
+        catch (IOException ex) {
+            // Fall back to stream existence: can we open the stream?
+            try {
+                InputStream is = getInputStream();
+                is.close();
+                return true;
+            }
+            catch (Throwable isEx) {
+                return false;
+            }
+        }
+    }
+
+	/**
+	 * Return whether the contents current this resource can be read,
+	 * e.g. via {@link #getInputStream()} or {@link #toFile()}.
+	 * <p>Will be {@code true} for typical resource descriptors;
+	 * note that actual content reading may still fail when attempted.
+	 * However, a keys current {@code false} is a definitive indication
+	 * that the resource content cannot be read.
+	 * @see #getInputStream()
+	 */
+	default boolean isReadable(){return true;}
+
+	/**
+	 * Return whether this resource represents a handle with an open
+	 * stream. If true, the InputStream cannot be read multiple times,
+	 * and must be read and closed to avoid resource leaks.
+	 * <p>Will be {@code false} for typical resource descriptors.
+	 */
+	default boolean isOpen(){return false;}
+
+	/**
+	 * Return a URL handle for this resource.
+	 * @throws IOException if the resource cannot be resolved as URL,
+	 * i.e. if the resource is not available as descriptor
+	 */
+	default URL toURL() throws IOException{
+        return getURI().toURL();
+    }
+
+	/**
+	 * Return a URI handle for this resource.
+	 * @throws IOException if the resource cannot be resolved as URI,
+	 * i.e. if the resource is not available as descriptor
+	 */
+	default URI getURI() throws IOException{
+        URL url = toURL();
+        try {
+            return new URI(url.toString().replaceAll(" ", "%20"));
+        }
+        catch (URISyntaxException ex) {
+            throw new IllegalStateException("Invalid URI [" + url + "]", ex);
+        }
+    }
+
+	/**
+	 * Return a File handle for this resource.
+	 * @throws IOException if the resource cannot be resolved as absolute
+	 * file path, i.e. if the resource is not available in a file system
+	 */
+	default File toFile() throws IOException{
+        return new File(getURI());
+    }
+
+	/**
+	 * Determine the content length for this resource.
+	 * @throws IOException if the resource cannot be resolved
+	 * (in the file system or as some other known physical resource type)
+	 */
+	default long contentLength() throws IOException{
+        InputStream is = this.getInputStream();
+        Objects.requireNonNull(is, "resource input stream must not be null");
+        try {
+            long size = 0;
+            byte[] buf = new byte[255];
+            int read;
+            while ((read = is.read(buf)) != -1) {
+                size += read;
+            }
+            return size;
+        }
+        finally {
+            try {
+                is.close();
+            }
+            catch (IOException ex) {
+            }
+        }
+    }
+
+	/**
+	 * Determine the last-modified timestamp for this resource.
+	 * @throws IOException if the resource cannot be resolved
+	 * (in the file system or as some other known physical resource type)
+	 */
+	default long lastModified() throws IOException {
+        long lastModified = toFile().lastModified();
+        if (lastModified == 0L) {
+            throw new FileNotFoundException(getDisplayName() +
+                    " cannot be resolved in the file system for resolving its last-modified timestamp");
+        }
+        return lastModified;
+    }
+
+	/**
+	 * Create a resource relative to this resource.
+	 * @param relativePath the relative path (relative to this resource)
+	 * @return the resource handle for the relative resource
+	 * @throws IOException if the relative resource cannot be determined
+	 */
+	default Resource createRelative(String relativePath) throws IOException{
+        throw new FileNotFoundException("Cannot of a relative resource for " + getDisplayName());
+    }
+
+	/**
+	 * Determine a filename for this resource, i.e. typically the last
+	 * part current the path: for example, "myfile.txt".
+	 * <p>Returns {@code null} if this type current resource does not
+	 * have a filename.
+	 */
+	default String getDisplayName(){
+        try{
+            return getURI().toString();
+        }
+        catch(Exception e){
+            return toString();
+        }
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/b56817f7/core/src/main/java/org/apache/tamaya/core/resources/ResourceLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/resources/ResourceLoader.java b/core/src/main/java/org/apache/tamaya/core/resources/ResourceLoader.java
new file mode 100644
index 0000000..ca071ca
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/resources/ResourceLoader.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.tamaya.core.resources;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Interface to be implemented by containers that decouples loading current resources from the effective
+ * classloader architecture. Implementations of this class encapsulate the mechanism of
+ * determining the concrete resources available base on an expression defining the configuration
+ * locations. A an example the expression {@code cfg/global/*.xml} defines a
+ * location for reading global configuration in the classpath. A resources
+ * interprets this expression and evaluates the concrete resources to be read,
+ * e.g. {@code cfg/global/default.xml, cfg/global/myApp.xml}.
+ */
+public interface ResourceLoader{
+
+    /**
+     * Called, when a given expression has to be resolved.
+     *
+     * @param expressions the expressions to be resolved, not empty.
+     * @return the corresponding collection current {@link java.net.URI}s defining the
+     * concrete resources to be read.
+     * .
+     */
+    default List<Resource> getResources(String... expressions) {
+        return getResources(Arrays.asList(expressions));
+    }
+
+
+    /**
+     * Called, when a given expression has to be resolved.
+     *
+     * @param expressions the expressions to be resolved, not empty.
+     * @return the corresponding collection current {@link java.net.URI}s defining the
+     * concrete resources to be read.
+     * .
+     */
+    default List<Resource> getResources(Collection<String> expressions) {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if(cl==null){
+            cl = getClass().getClassLoader();
+        }
+        return getResources(cl, expressions);
+    }
+
+    /**
+     * Called, when a given expression has to be resolved.
+     *
+     * @param expressions the expressions to be resolved, not empty.
+     * @return the corresponding collection current {@link java.net.URI}s defining the
+     * concrete resources to be read.
+     * .
+     */
+    default List<Resource> getResources(ClassLoader classLoader, String... expressions) {
+        return getResources(classLoader, Arrays.asList(expressions));
+    }
+
+    /**
+     * Called, when a given expression has to be resolved.
+     *
+     * @param expressions the expressions to be resolved, not empty.
+     * @return the corresponding collection current {@link org.apache.tamaya.core.resources.Resource}s defining the
+     * concrete resources to be read.
+     * .
+     */
+    List<Resource> getResources(ClassLoader classLoader, Collection<String> expressions);
+
+}


Mime
View raw message