You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2015/01/11 01:43:48 UTC

[1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Repository: incubator-tamaya
Updated Branches:
  refs/heads/master 2dd0c13e5 -> c48c5794e


TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall.
TAMAYA-43: Removed Resource abstraction in favor of URL.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/ae66299e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/ae66299e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/ae66299e

Branch: refs/heads/master
Commit: ae66299e25b41167008021ffe95cad236f6e2bd3
Parents: 2dd0c13
Author: anatole <an...@apache.org>
Authored: Wed Jan 7 22:49:39 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Jan 11 01:40:57 2015 +0100

----------------------------------------------------------------------
 .../tamaya/format/ConfigurationFormat.java      |  10 +-
 .../apache/tamaya/format/PropertiesFormat.java  |  15 +-
 .../tamaya/format/PropertiesXmlFormat.java      |  15 +-
 ...AbstractPathBasedPropertySourceProvider.java |   7 +-
 .../AbstractResourcePropertySourceProvider.java |  17 +-
 .../org/apache/tamaya/resource/Resource.java    | 115 --------
 .../tamaya/resource/ResourceResolver.java       |  25 +-
 .../resource/internal/ClassPathResource.java    | 187 -------------
 .../resource/internal/ClasspathCollector.java   | 264 +++++++++++++++++++
 .../internal/DefaultResourceResolver.java       |  61 ++++-
 .../tamaya/resource/internal/FileCollector.java | 157 +++++++++++
 .../tamaya/resource/internal/FileResource.java  | 172 ------------
 .../resource/internal/InputStreamResource.java  | 117 --------
 .../tamaya/resource/internal/Locator.java       | 150 +++++++++++
 .../tamaya/resource/internal/UrlResource.java   | 140 ----------
 15 files changed, 671 insertions(+), 781 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
index 4a1e06f..924fa7c 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
@@ -21,9 +21,8 @@ package org.apache.tamaya.format;
 import org.apache.tamaya.spi.PropertySource;
 
 import java.io.IOException;
-import java.io.InputStream;
+import java.net.URL;
 import java.util.Collection;
-import java.util.function.Supplier;
 
 /**
  * Implementations current this class encapsulate the mechanism how to read a
@@ -44,12 +43,11 @@ public interface ConfigurationFormat {
      * ladder case multiple PropertySources can be returned, each one with its own ordinal and the corresponding
      * entries.
      *
-     * @param sourceName name to be used for constructing a useful name for the created
-     *                   {@link org.apache.tamaya.spi.PropertySource} instances.
-     * @param streamSupplier   the resource represented by a supplier of InputStream, not null
+     * @param url the url to read the configuration data from (could be a file, a remote location, a classpath
+     *            resource or something else.
      * @return the corresponding {@link org.apache.tamaya.spi.PropertySource} instances, never {@code null}.
      */
-    Collection<PropertySource> readConfiguration(String sourceName, Supplier<InputStream> streamSupplier)
+    Collection<PropertySource> readConfiguration(URL url)
             throws IOException;
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
index 34c9e21..a49e492 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
@@ -21,6 +21,7 @@ package org.apache.tamaya.format;
 import org.apache.tamaya.spi.PropertySource;
 
 import java.io.InputStream;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -28,7 +29,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
-import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -70,10 +70,15 @@ public class PropertiesFormat implements ConfigurationFormat {
 
     @SuppressWarnings("unchecked")
     @Override
-    public Collection<PropertySource> readConfiguration(String sourceName, Supplier<InputStream> streamSupplier) {
-        final String name = "Properties(" + Objects.requireNonNull(sourceName) + ')';
+    public Collection<PropertySource> readConfiguration(URL url) {
+        final String name;
+        if (Objects.requireNonNull(url).getQuery() == null) {
+            name = "Properties(" + Objects.requireNonNull(url).toString() + ')';
+        } else {
+            name = Objects.requireNonNull(url).getQuery();
+        }
         List<PropertySource> propertySources = new ArrayList<>();
-        try (InputStream is = streamSupplier.get()) {
+        try (InputStream is = url.openStream()) {
             if (is != null) {
                 final Properties p = new Properties();
                 p.load(is);
@@ -101,7 +106,7 @@ public class PropertiesFormat implements ConfigurationFormat {
                 return propertySources;
             }
         } catch (Exception e) {
-            LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + sourceName);
+            LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + url);
         }
         return Collections.emptyList();
     }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
index 8b3468b..ddfe723 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
@@ -21,6 +21,7 @@ package org.apache.tamaya.format;
 import org.apache.tamaya.spi.PropertySource;
 
 import java.io.InputStream;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -28,7 +29,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
-import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -71,10 +71,15 @@ public class PropertiesXmlFormat implements ConfigurationFormat {
 
     @SuppressWarnings("unchecked")
     @Override
-    public Collection<PropertySource> readConfiguration(String source, Supplier<InputStream> streamSupplier) {
-        final String name = "XML-Properties:" + Objects.requireNonNull(source) + ')';
+    public Collection<PropertySource> readConfiguration(URL url) {
+        final String name;
+        if (Objects.requireNonNull(url).getQuery() == null) {
+            name = "XML-Properties(" + Objects.requireNonNull(url).toString() + ')';
+        } else {
+            name = Objects.requireNonNull(url).getQuery();
+        }
         List<PropertySource> propertySources = new ArrayList<>();
-        try (InputStream is = streamSupplier.get()) {
+        try (InputStream is = url.openStream()) {
             if (is != null) {
                 final Properties p = new Properties();
                 p.loadFromXML(is);
@@ -102,7 +107,7 @@ public class PropertiesXmlFormat implements ConfigurationFormat {
                 return propertySources;
             }
         } catch (Exception e) {
-            LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + source);
+            LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + url);
         }
         return Collections.emptyList();
     }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
index c4c5651..58acba3 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
@@ -23,6 +23,7 @@ import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertySourceProvider;
 import org.apache.tamaya.spi.ServiceContext;
 
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -75,13 +76,13 @@ public abstract class AbstractPathBasedPropertySourceProvider implements Propert
     public Collection<PropertySource> getPropertySources() {
         List<PropertySource> propertySources = new ArrayList<>();
         paths.forEach((path) -> {
-            for (Resource res : ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path)) {
+            for (URL res : ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path)) {
                 try {
                     for (ConfigurationFormat format : configFormats) {
-                        propertySources.addAll(format.readConfiguration(sourceName, res));
+                        propertySources.addAll(format.readConfiguration(res));
                     }
                 } catch (Exception e) {
-                    LOG.log(Level.WARNING, "Failed to add resource based config: " + res.getName(), e);
+                    LOG.log(Level.WARNING, "Failed to add resource based config: " + res, e);
                 }
             }
         });

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
index 6edba5b..f1ec885 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
@@ -22,6 +22,7 @@ import org.apache.tamaya.format.ConfigurationFormat;
 import org.apache.tamaya.spi.PropertySource;
 import org.apache.tamaya.spi.PropertySourceProvider;
 
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -39,25 +40,25 @@ public abstract class AbstractResourcePropertySourceProvider implements Property
     /** The supported formats. */
     private List<ConfigurationFormat> formats = new ArrayList<>();
     /** The resource. */
-    private Resource resource;
+    private URL resource;
     /** The source name used for creating the PropertySource names. */
     private String sourceName;
 
     /**
      * Creates a new instance.
-     * @param resource the {@link Resource}, not null.
+     * @param resource the {@link URL}, not null.
      * @param formats the supported formats, not empty.
      */
-    public AbstractResourcePropertySourceProvider(String sourceName, Resource resource, ConfigurationFormat... formats) {
+    public AbstractResourcePropertySourceProvider(String sourceName, URL resource, ConfigurationFormat... formats) {
         this(sourceName, resource, Arrays.asList(formats));
     }
 
     /**
      * Creates a new instance.
-     * @param resource the {@link Resource}, not null.
+     * @param resource the {@link URL}, not null.
      * @param formats the supported formats, not empty.
      */
-    public AbstractResourcePropertySourceProvider(String sourceName, Resource resource, List<ConfigurationFormat> formats) {
+    public AbstractResourcePropertySourceProvider(String sourceName, URL resource, List<ConfigurationFormat> formats) {
         this.resource = Objects.requireNonNull(resource);
         this.sourceName = Objects.requireNonNull(sourceName);
         if(formats.size()==0){
@@ -72,7 +73,7 @@ public abstract class AbstractResourcePropertySourceProvider implements Property
      *
      * @return the underlying resource, never null.
      */
-    public Resource getResource() {
+    public URL getResource() {
         return this.resource;
     }
 
@@ -90,9 +91,9 @@ public abstract class AbstractResourcePropertySourceProvider implements Property
         List<PropertySource> propertySources = new ArrayList<>();
         for (ConfigurationFormat format : formats) {
             try {
-                propertySources.addAll(format.readConfiguration(sourceName, resource));
+                propertySources.addAll(format.readConfiguration(resource));
             } catch (Exception e) {
-                LOG.info(() -> "Format was not matching: " + format + " for resource: " + resource.getName());
+                LOG.info(() -> "Format was not matching: " + format + " for resource: " + resource);
             }
         }
         return propertySources;

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java b/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
deleted file mode 100644
index 39e34e9..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.resource;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Objects;
-import java.util.function.Supplier;
-
-/**
- * Interface for an abstract resource. The effective resource implementation can be completely arbitrary.
- * By default files, classpath format and URLs are supported, but alternate implementations are possible.
- *
- * @see #get()
- * @see #toURI()
- */
-public interface Resource extends Supplier<InputStream> {
-
-    /**
-     * Return whether this resource actually exists. Depending on the resource this can delegate to
-     * {@link java.io.File#exists()} or whatever may be appropriate to check accessibility of the resource.
-     */
-    default boolean exists() {
-        // Try to open a file first, if that fails try to open the stream...
-        try {
-            return new File(toURI()).exists();
-        } catch (IOException ex) {
-            // Fallback
-            try {
-                InputStream is = get();
-                is.close();
-                return true;
-            } catch (Exception e) {
-                // ignore, just return false for non existing
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Checks whether the resource is accessible, meaning {@link #get()} should return a InputStream for reading the
-     * resource's content.
-     *
-     * @see #get()
-     */
-    default boolean isAccessible() {
-        return true;
-    }
-
-    /**
-     * Returns the resource as an URI.
-     *
-     * @throws IOException if the resource cannot be resolved as URI.
-     */
-    URI toURI() throws IOException;
-
-    /**
-     * Determines the length for this resource.
-     *
-     * @throws IOException if the resource is not readable.
-     */
-    default long length() throws IOException {
-        try(InputStream is = this.get();) {
-            Objects.requireNonNull(is, "resource not available");
-            long length = 0;
-            byte[] buf = new byte[256];
-            int bytesRead;
-            while ((bytesRead = is.read(buf)) > 0) {
-                length += bytesRead;
-            }
-            return length;
-        }
-    }
-
-    /**
-     * Determine the last-modified timestamp for a resource, as UTC ms timestamp
-     *
-     * @throws IOException if the resource is not accessible.
-     */
-    default long lastModified() throws IOException{
-        return new File(toURI()).lastModified();
-    }
-
-    /**
-     * Get a name for the resource. The name should be identifying the resource and also
-     * never change, so it must be eligible for hashcode/equals implementations.
-     */
-    default String getName() {
-        try {
-            return toURI().toString();
-        } catch (Exception e) {
-            return toString();
-        }
-    }
-
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
index 7901ca6..31856cf 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tamaya.resource;
 
+import java.net.URL;
 import java.util.Arrays;
 import java.util.Collection;
 
@@ -28,16 +29,16 @@ import java.util.Collection;
 public interface ResourceResolver {
 
     /**
-     * Resolves resource expressions to a list of {@link Resource}s. Hereby
+     * Resolves resource expressions to a list of {@link URL}s. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
      * there is no determined ordering of format located within a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
-     * @return the corresponding collection of current {@link Resource}s found, never
+     * @return the corresponding collection of current {@link URL}s found, never
      * null.
      * .
      */
-    default Collection<Resource> getResources(Collection<String> expressions) {
+    default Collection<URL> getResources(Collection<String> expressions) {
         ClassLoader cl = Thread.currentThread().getContextClassLoader();
         if (cl == null) {
             cl = getClass().getClassLoader();
@@ -46,45 +47,45 @@ public interface ResourceResolver {
     }
 
     /**
-     * Resolves resource expressions to a list of {@link Resource}s. Hereby
+     * Resolves resource expressions to a list of {@link URL}s. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
      * there is no determined ordering of format located within a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
-     * @return the corresponding collection of current {@link Resource}s found, never
+     * @return the corresponding collection of current {@link URL}s found, never
      * null.
      * .
      */
-    default Collection<Resource> getResources(String... expressions) {
+    default Collection<URL> getResources(String... expressions) {
         return getResources(Arrays.asList(expressions));
     }
 
     /**
-     * Resolves resource expressions to a list of {@link Resource}s, considerubg
+     * Resolves resource expressions to a list of {@link URL}s, considerubg
      * the given classloader for classloader dependent format. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
      * there is no determined ordering of format located within a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
-     * @return the corresponding collection of current {@link Resource}s found, never
+     * @return the corresponding collection of current {@link URL}s found, never
      * null.
      * .
      */
-    default Collection<Resource> getResources(ClassLoader classLoader, String... expressions){
+    default Collection<URL> getResources(ClassLoader classLoader, String... expressions){
         return getResources(classLoader, Arrays.asList(expressions));
     }
 
     /**
-     * Resolves resource expressions to a list of {@link Resource}s, considerubg
+     * Resolves resource expressions to a list of {@link URL}s, considerubg
      * the given classloader for classloader dependent format. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
      * there is no determined ordering of format located within a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
-     * @return the corresponding collection of current {@link Resource}s found, never
+     * @return the corresponding collection of current {@link URL}s found, never
      * null.
      * .
      */
-    Collection<Resource> getResources(ClassLoader classLoader, Collection<String> expressions);
+    Collection<URL> getResources(ClassLoader classLoader, Collection<String> expressions);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
deleted file mode 100644
index b901164..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.resource.internal;
-
-import org.apache.tamaya.resource.Resource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Objects;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Implementation of {@link Resource} to be loaded from the classpath.
- */
-public class ClassPathResource implements Resource {
-
-    private static final Logger LOG = Logger.getLogger(ClassPathResource.class.getName());
-
-    private final String path;
-
-    private ClassLoader classLoader;
-
-
-    /**
-     * Create a new resource using the current context class loader.
-     *
-     * @param path the resource path, not null
-     * @see java.lang.ClassLoader#getResourceAsStream(String)
-     */
-    public ClassPathResource(String path) {
-        this(path, (ClassLoader) null);
-    }
-
-    /**
-     * Create a new resource using the given class loader.
-     *
-     * @param path        the resource path, not null
-     * @param classLoader the class loader to load the resource with,
-     *                    or {@code null} for the current context class loader
-     * @see ClassLoader#getResourceAsStream(String)
-     */
-    public ClassPathResource(String path, ClassLoader classLoader) {
-        Objects.requireNonNull(path, "Path null");
-        if (path.startsWith("/")) {
-            path = path.substring(1);
-        }
-        this.path = path.trim();
-        if (classLoader == null) {
-            classLoader = Thread.currentThread().getContextClassLoader();
-        }
-        if (classLoader == null) {
-            classLoader = getClass().getClassLoader();
-        }
-        this.classLoader = classLoader;
-    }
-
-    /**
-     * @return the path for this resource.
-     */
-    public final String getPath() {
-        return this.path;
-    }
-
-    /**
-     * @return the ClassLoader that this resource will be accessed from.
-     */
-    public final ClassLoader getClassLoader() {
-        return this.classLoader;
-    }
-
-
-    /**
-     * Checks if the given resource is resolvable from the configured classloader.
-     *
-     * @see java.lang.ClassLoader#getResource(String)
-     */
-    @Override
-    public boolean exists() {
-        return (resolveURL() != null);
-    }
-
-    /**
-     * Resolves a URL for the underlying class path resource.
-     *
-     * @return the resolved URL, or {@code null}
-     */
-    protected URL resolveURL() {
-        return this.classLoader.getResource(this.path);
-    }
-
-    /**
-     * This implementation opens an InputStream for the given class path resource.
-     *
-     * @see java.lang.ClassLoader#getResourceAsStream(String)
-     * @see java.lang.Class#getResourceAsStream(String)
-     */
-    @Override
-    public InputStream get() {
-        try {
-            InputStream is = this.classLoader.getResourceAsStream(this.path);
-            if (is == null) {
-                throw new IOException(getName() + " does not exist");
-            }
-            return is;
-        } catch (IOException e) {
-            LOG.log(Level.INFO, "Failed to open classpath resource: " + path, e);
-            return null;
-        }
-    }
-
-    @Override
-    public URI toURI() throws IOException {
-        try {
-            return resolveURL().toURI();
-        } catch (URISyntaxException e) {
-            throw new IOException(e);
-        }
-    }
-
-    @Override
-    public long lastModified() throws IOException {
-        return 0;
-    }
-
-    /**
-     * This implementation returns the name current the file that this class path
-     * resource refers to.
-     */
-    @Override
-    public String getName() {
-        return "classpath:" + path;
-    }
-
-    /**
-     * This implementation returns a description that includes the class path location.
-     */
-    @Override
-    public String toString() {
-        return "ClassPathResource[" + path + ']';
-    }
-
-    /**
-     * This implementation compares the underlying class path locations.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-        if (obj instanceof ClassPathResource) {
-            ClassPathResource otherRes = (ClassPathResource) obj;
-            return (this.path.equals(otherRes.path) &&
-                    Objects.equals(this.classLoader, otherRes.classLoader));
-        }
-        return false;
-    }
-
-    /**
-     * This implementation returns the hash code current the underlying
-     * class path location.
-     */
-    @Override
-    public int hashCode() {
-        return getName().hashCode();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
new file mode 100644
index 0000000..3f2093b
--- /dev/null
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
@@ -0,0 +1,264 @@
+/*
+ * 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.resource.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Objects;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Collector that searches files based on ant styled patterns. For example the following patterns would be matched:
+ * <pre>
+ *     classpath:javax/annotations/*
+ *     javax?/annotations&#47;**&#47;*.class
+ *     org/apache/tamaya&#47;**&#47;tamayaconfig.properties
+ * </pre>
+ */
+public class ClasspathCollector {
+
+    /**
+     * JAR protocol.
+     */
+    public static final String PROTOCOL_JAR = "jar";
+
+    /**
+     * Separator between JAR file URL and the internal jar file path.
+     */
+    public static final String JAR_URL_SEPARATOR = "!/";
+
+    /**
+     * ZIP protocol.
+     */
+    public static final String PROTOCOL_ZIP = "zip";
+
+    /**
+     * ZIP protocol for a JBoss jar file entry: "vfszip".
+     */
+    public static final String PROTOCOL_VFSZIP = "vfszip";
+
+    /**
+     * URL protocol for an WebSphere jar file: "wsjar".
+     */
+    public static final String PROTOCOL_WSJAR = "wsjar";
+
+    /**
+     * URL protocol for an entry from an OC4J jar.
+     */
+    public static final String PROTOCOL_CODE_SOURCE = "code-source";
+
+    /**
+     * The logger used.
+     */
+    private static final Logger LOG = Logger.getLogger(ClasspathCollector.class.getName());
+
+    /**
+     * The classloader used to load the resources.
+     */
+    private ClassLoader classLoader;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param classLoader the class loader to be used, not null.
+     */
+    public ClasspathCollector(ClassLoader classLoader) {
+        this.classLoader = Objects.requireNonNull(classLoader);
+    }
+
+    /**
+     * Collect all classpath resources given the expression.
+     *
+     * @param expression the expression, not null.
+     * @return the resources found.
+     */
+    public Collection<URL> collectFiles(String expression) {
+        if (expression.startsWith("classpath:")) {
+            expression = expression.substring("classpath:".length());
+        }
+        if (expression.startsWith("/")) {
+            expression = expression.substring(1);
+        }
+        Locator locator = Locator.of(expression);
+        List<URL> result = new ArrayList<>();
+        String rootPath = locator.getRootPath();
+        try {
+            Enumeration<URL> rootResources = this.classLoader.getResources(rootPath);
+            while (rootResources.hasMoreElements()) {
+                URL resource = rootResources.nextElement();
+                try {
+                    if (isJarFile(resource)) {
+                        result.addAll(doFindPathMatchingJarResources(resource, locator.getSubPath()));
+                    } else {
+                        File file = getFile(resource);
+                        result.addAll(FileCollector.traverseAndSelectFromChildren(file, locator.getSubPathTokens(), 0));
+                    }
+                } catch (Exception e) {
+                    LOG.log(Level.SEVERE, "Error locating resources for: " + expression, e);
+                }
+            }
+        } catch (IOException e) {
+            LOG.log(Level.SEVERE, "Error locating resources for: " + expression, e);
+        }
+        return result;
+    }
+
+
+    /**
+     * Find all resources in jar files that match the given location pattern
+     * via the Ant-style PathMatcher.
+     *
+     * @param rootDirResource the root directory as Resource
+     * @param subPattern      the sub pattern to match (below the root directory)
+     * @return the Set of matching Resource instances
+     * @throws java.io.IOException in case of I/O errors
+     * @see java.net.JarURLConnection
+     */
+    protected Collection<URL> doFindPathMatchingJarResources(URL rootDirResource, String subPattern)
+            throws IOException, URISyntaxException {
+        subPattern = subPattern.replace("*", ".*").replace("?", ".?").replace(".*.*", ".*");
+        URLConnection con = rootDirResource.toURI().toURL().openConnection();
+        JarFile jarFile;
+        boolean newJarFile = false;
+        String jarFileUrl;
+        String rootEntryPath;
+
+        if (con instanceof JarURLConnection) {
+            // Should usually be the case for traditional JAR files.
+            JarURLConnection jarCon = (JarURLConnection) con;
+            jarCon.setUseCaches(false);
+            jarFile = jarCon.getJarFile();
+            jarFileUrl = jarCon.getJarFileURL().toExternalForm();
+            JarEntry jarEntry = jarCon.getJarEntry();
+            rootEntryPath = (jarEntry != null ? jarEntry.getName() : "");
+        } else {
+            // No JarURLConnection -> need to resort to URL file parsing.
+            // We'll assume URLs of the format "jar:path!/entry", with the protocol
+            // being arbitrary as long as following the entry format.
+            // We'll also handle paths with and without leading "file:" prefix.
+            String urlFile = rootDirResource.toURI().toURL().getFile();
+            int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
+            jarFileUrl = urlFile.substring(0, separatorIndex);
+            if (jarFileUrl.startsWith("file:")) {
+                jarFileUrl = jarFileUrl.substring("file:".length());
+            }
+            jarFile = new JarFile(jarFileUrl);
+            newJarFile = true;
+            jarFileUrl = "file:" + jarFileUrl;
+            rootEntryPath = urlFile.substring(separatorIndex + JAR_URL_SEPARATOR.length());
+        }
+
+        try {
+            if (LOG.isLoggable(Level.FINEST)) {
+                LOG.finest("Looking for matching resources in jar file [" + jarFileUrl + "]");
+            }
+            if (!rootEntryPath.isEmpty() && !rootEntryPath.endsWith("/")) {
+                // Root entry path must end with slash for correct matching
+                rootEntryPath = rootEntryPath + '/';
+            }
+            Collection<URL> result = new ArrayList<>(10);
+            for (Enumeration entries = jarFile.entries(); entries.hasMoreElements(); ) {
+                JarEntry entry = (JarEntry) entries.nextElement();
+                String entryPath = entry.getName();
+                if (entryPath.startsWith(rootEntryPath)) {
+                    String relativePath = entryPath.substring(rootEntryPath.length());
+                    if (relativePath.matches(subPattern)) {
+                        result.add(createRelativeFrom(rootDirResource, relativePath));
+                    }
+                }
+            }
+            return result;
+        } finally {
+            // Close jar file, but only if freshly obtained -
+            // not from JarURLConnection, which might cache the file reference.
+            if (newJarFile) {
+                jarFile.close();
+            }
+        }
+    }
+
+    /**
+     * Creates a new URL based on the given root path and the relative path to be added.
+     *
+     * @param url          the root, not null
+     * @param relativePath the relative path to be added, not null
+     * @return the new URL instance
+     * @throws MalformedURLException
+     */
+    private URL createRelativeFrom(URL url, String relativePath)
+            throws MalformedURLException {
+        String rootDirResource = url.toExternalForm();
+        if (relativePath.startsWith("/")) {
+            relativePath = relativePath.substring(1);
+        }
+        if (!rootDirResource.endsWith("/")) {
+            rootDirResource = rootDirResource + '/';
+        }
+        return new URL(rootDirResource + relativePath);
+    }
+
+
+    /**
+     * Small check if a given URL is a jar file URL.
+     *
+     * @param url the URL to check, not null.
+     * @return true if the URL has one of the following protocols: jar, zip, vfszip, wsjar, code-source.
+     */
+    private boolean isJarFile(URL url) {
+        String protocol = Objects.requireNonNull(url).getProtocol();
+        return (PROTOCOL_JAR.equals(protocol) ||
+                PROTOCOL_ZIP.equals(protocol) ||
+                PROTOCOL_VFSZIP.equals(protocol) ||
+                PROTOCOL_WSJAR.equals(protocol) ||
+                (PROTOCOL_CODE_SOURCE.equals(protocol) && url.getPath().indexOf(JAR_URL_SEPARATOR) != -1));
+    }
+
+    /**
+     * Creates a file from an URL.
+     *
+     * @param resourceUrl the url, not null.
+     * @return a new file instance. The instance still may not exist. if the url's protocol is not 'file', {@code null}
+     * is returned.
+     */
+    private File getFile(URL resourceUrl) {
+        Objects.requireNonNull(resourceUrl, "Resource URL must not be null");
+        if (!"file".equals(resourceUrl.getProtocol())) {
+            return null;
+        }
+        try {
+            return new File(resourceUrl.toURI().getSchemeSpecificPart());
+        } catch (Exception ex) {
+            // Fallback for URLs that are not valid URIs (should hardly ever happen).
+            return new File(resourceUrl.getFile());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
index 9fd6fc4..c90e53a 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
@@ -18,7 +18,6 @@
  */
 package org.apache.tamaya.resource.internal;
 
-import org.apache.tamaya.resource.Resource;
 import org.apache.tamaya.resource.ResourceResolver;
 
 import javax.annotation.Priority;
@@ -39,10 +38,10 @@ public class DefaultResourceResolver implements ResourceResolver {
     private static final Logger LOG = Logger.getLogger(DefaultResourceResolver.class.getName());
 
     @Override
-    public List<Resource> getResources(ClassLoader classLoader, Collection<String> expressions) {
-        List<Resource> resources = new ArrayList<>();
+    public List<URL> getResources(ClassLoader classLoader, Collection<String> expressions) {
+        List<URL> resources = new ArrayList<>();
         for (String expression : expressions) {
-            if (tryClassPath(classLoader, expression, resources) || tryFile(expression, resources) ||
+            if (tryPath(classLoader, expression, resources) || tryClassPath(classLoader, expression, resources) || tryFile(expression, resources) ||
                     tryURL(expression, resources)) {
                 continue;
             }
@@ -51,12 +50,41 @@ public class DefaultResourceResolver implements ResourceResolver {
         return resources;
     }
 
-    private boolean tryClassPath(ClassLoader classLoader, String expression, List<Resource> resources) {
+    /**
+     * Tries to evaluate the location passed by Ant path matching.
+     * @param classLoader the class loader to use
+     * @param expression the path expression
+     * @param resources the resources for adding the results
+     * @return true, if the expression could be resolved.
+     */
+    private boolean tryPath(ClassLoader classLoader, String expression, List<URL> resources) {
+        try {
+            // 1: try file path
+            Collection<URL> found = FileCollector.collectFiles(expression);
+            if (found.isEmpty()) {
+                found = new ClasspathCollector(classLoader).collectFiles(expression);
+            }
+            resources.addAll(found);
+            return !found.isEmpty();
+        } catch (Exception e) {
+            LOG.finest(() -> "Failed to load resource from CP: " + expression);
+        }
+        return false;
+    }
+
+    /**
+     * Tries to evaluate the location passed by loading from the classloader.
+     * @param classLoader the class loader to use
+     * @param expression the path expression
+     * @param resources the resources for adding the results
+     * @return true, if the expression could be resolved.
+     */
+    private boolean tryClassPath(ClassLoader classLoader, String expression, List<URL> resources) {
         try {
             Enumeration<URL> urls = classLoader.getResources(expression);
             while (urls.hasMoreElements()) {
                 URL url = urls.nextElement();
-                resources.add(new UrlResource(url));
+                resources.add(url);
             }
             return !resources.isEmpty();
         } catch (Exception e) {
@@ -65,11 +93,17 @@ public class DefaultResourceResolver implements ResourceResolver {
         return false;
     }
 
-    private boolean tryFile(String expression, List<Resource> resources) {
+    /**
+     * Tries to evaluate the location passed by lokking up a file.
+     * @param expression the path expression
+     * @param resources the resources for adding the results
+     * @return true, if the expression could be resolved.
+     */
+    private boolean tryFile(String expression, List<URL> resources) {
         try {
             File file = new File(expression);
             if (file.exists()) {
-                resources.add(new FileResource(file));
+                resources.add(file.toURI().toURL());
                 return true;
             }
         } catch (Exception e) {
@@ -78,16 +112,21 @@ public class DefaultResourceResolver implements ResourceResolver {
         return false;
     }
 
-    private boolean tryURL(String expression, List<Resource> resources) {
+    /**
+     * Tries to interpret the expression as URL.
+     * @param expression the path expression
+     * @param resources the resources for adding the results
+     * @return true, if the expression could be resolved.
+     */
+    private boolean tryURL(String expression, List<URL> resources) {
         try {
             URL url = new URL(expression);
-            resources.add(new UrlResource(url));
+            resources.add(url);
             return true;
         } catch (Exception e) {
             LOG.finest(() -> "Failed to load resource from file: " + expression);
         }
         return false;
-
     }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
new file mode 100644
index 0000000..d506e11
--- /dev/null
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
@@ -0,0 +1,157 @@
+/*
+ * 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.resource.internal;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+/**
+ * Collector that searches files based on ant styled patterns. For example the following patterns would be matched:
+ * <pre>
+ *     file:C:/temp/*.txt
+ *     file:C:\**\*.ini
+ *     C:\Programs\**&#47;*.ini
+ *     /user/home/A*b101_?.pid
+ *     /var/logs&#47;**&#47;*.log
+ * </pre>
+ */
+public class FileCollector {
+
+    public static final String FILE_PREFIX = "file:";
+
+    private FileCollector() {
+    }
+
+    private static final Logger LOG = Logger.getLogger(FileCollector.class.getName());
+
+    public static Collection<URL> collectFiles(String expression) {
+        expression = expression.replace("\\", "/");
+        Locator locator = Locator.of(expression);
+        List<URL> result = new ArrayList<>();
+        String rootPath = locator.getRootPath();
+        if (rootPath.startsWith(FILE_PREFIX)) {
+            rootPath = rootPath.substring(FILE_PREFIX.length());
+        }
+        File file = new File(rootPath);
+        if (file.exists()) {
+            List<String> subTokens = locator.getSubPathTokens();
+            result.addAll(traverseAndSelectFromChildren(file, subTokens, 0));
+        }
+        return result;
+    }
+
+    static Collection<URL> traverseAndSelectFromChildren(File dir, List<String> subTokens, int tokenIndex) {
+        if (tokenIndex >= subTokens.size() || dir.isFile()) {
+            return Collections.emptyList();
+        }
+        List<URL> result = new ArrayList<>();
+        String token = subTokens.get(tokenIndex);
+        if (token.equals("**")) {
+            result.addAll(traverseAndSelectFromChildren(dir, getSubExpression(subTokens, tokenIndex + 1)));
+        } else {
+            token = token.replace("*", ".*");
+            File[] files = dir.listFiles();
+            if (tokenIndex == subTokens.size() - 1) {
+                // select files!
+                for (File f : files) {
+                    if (f.isFile() && f.getName().matches(token)) {
+                        result.add(getURL(f));
+                    }
+                }
+            } else {
+                // check directory pattern
+                for (File f : files) {
+                    if (f.isDirectory() && f.getName().matches(token)) {
+                        result.addAll(traverseAndSelectFromChildren(f, subTokens, tokenIndex + 1));
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    static Collection<URL> traverseAndSelectFromChildren(File file, String subExpression) {
+        List<URL> result = new ArrayList<>();
+        for (File childFile : file.listFiles()) {
+            if (childFile.isFile()) {
+                if (childFile.getName().matches(subExpression)) {
+                    try {
+                        result.add(getURL(childFile));
+                    } catch (Exception e) {
+                        LOG.warning(() -> "File not convertible to URL: " + childFile);
+                    }
+                }
+            } else if (childFile.isDirectory()) {
+                result.addAll(traverseAndSelectFromChildren(childFile, subExpression));
+            }
+        }
+        return result;
+    }
+
+    private static boolean matchesFile(File childFile, List<String> subTokens, int tokenIndex) {
+        if (tokenIndex < (subTokens.size() - 1)) {
+            // not all tokens consumed, so no match!
+            return false;
+        }
+        String tokenToMatch = subTokens.get(tokenIndex);
+        tokenToMatch = tokenToMatch.replace("*", ".*");
+        return childFile.getName().matches(tokenToMatch);
+    }
+
+    /**
+     * Get an URL from a file.
+     *
+     * @param file the file, not null.
+     * @return the URL, never null.
+     * @throws java.lang.IllegalStateException if it fails to create the URL
+     */
+    private static URL getURL(File file) {
+        Objects.requireNonNull(file);
+        try {
+            return file.toURI().toURL();
+        } catch (Exception e) {
+            throw new IllegalStateException("Failed to create URL from file: " + file);
+        }
+    }
+
+    /**
+     * Constructs a sub expression, using the tokens from {@code subTokens} starting at index {@code startIndex}.
+     *
+     * @param subTokens  the token list, not null
+     * @param startIndex the start index from where tokens should be taken to produce the path.
+     * @return the constructed path, never null.
+     */
+    private static String getSubExpression(List<String> subTokens, int startIndex) {
+        StringBuilder b = new StringBuilder();
+        for (int i = startIndex; i < subTokens.size(); i++) {
+            b.append(subTokens.get(i));
+            b.append('/');
+        }
+        if (b.length() > 0) {
+            b.setLength(b.length() - 1);
+        }
+        return b.toString().replaceAll("\\*", ".*").replaceAll("\\?", ".?");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
deleted file mode 100644
index c5f521a..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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.resource.internal;
-
-import org.apache.tamaya.resource.Resource;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Objects;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Implementation of {@link Resource} to be loaded from a file.
- *
- * @see java.io.File
- */
-public class FileResource implements Resource {
-
-    private static final Logger LOG = Logger.getLogger(FileResource.class.getName());
-
-    private final File file;
-
-    /**
-     * Creates a new instance.
-     *
-     * @param file a File, not null.
-     */
-    public FileResource(File file) {
-        this.file = Objects.requireNonNull(file, "File must not be null");
-    }
-
-    /**
-     * Crreates a new instance.
-     *
-     * @param filePath a file path
-     */
-    public FileResource(String filePath) {
-        Objects.requireNonNull(filePath, "Path must not be null");
-        this.file = new File(filePath);
-    }
-
-
-    /**
-     * Get the file path for this resource.
-     */
-    public final String getPath() {
-        return this.file.getPath();
-    }
-
-
-    /**
-     * This implementation returns whether the underlying file exists.
-     *
-     * @see java.io.File#exists()
-     */
-    @Override
-    public boolean exists() {
-        return this.file.exists();
-    }
-
-    /**
-     * This implementation checks whether the underlying file is marked as readable
-     * (and corresponds to an actual file with content, not to a directory).
-     *
-     * @see java.io.File#canRead()
-     * @see java.io.File#isDirectory()
-     */
-    @Override
-    public boolean isAccessible() {
-        return (this.file.canRead() && !this.file.isDirectory());
-    }
-
-    /**
-     * This implementation opens a FileInputStream for the underlying file.
-     *
-     * @see java.io.FileInputStream
-     */
-    @Override
-    public InputStream get() {
-        try {
-            return new FileInputStream(this.file);
-        } catch (Exception e) {
-            LOG.log(Level.INFO, "Failed to open file: " + file.getAbsolutePath(), e);
-            return null;
-        }
-    }
-
-    /**
-     * This implementation returns a URI for the underlying file.
-     *
-     * @see java.io.File#toURI()
-     */
-    @Override
-    public URI toURI() throws IOException {
-        return this.file.toURI();
-    }
-
-    /**
-     * Returns the underlying File's length.
-     */
-    @Override
-    public long length() throws IOException {
-        return this.file.length();
-    }
-
-    @Override
-    public long lastModified() throws IOException {
-        return file.lastModified();
-    }
-
-    /**
-     * Returns the name of the current file.
-     *
-     * @see java.io.File#getName()
-     */
-    @Override
-    public String getName() {
-        return this.file.getName();
-    }
-
-    /**
-     * Returns a description that includes the absolute
-     * path of the current file.
-     *
-     * @see java.io.File#getAbsolutePath()
-     */
-    @Override
-    public String toString() {
-        return "File [" + this.file.getAbsolutePath() + "]";
-    }
-
-
-    // implementation current WritableResource
-
-    /**
-     * Compares the underlying Files.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        return (obj == this ||
-                (obj instanceof FileResource && this.file.equals(((FileResource) obj).file)));
-    }
-
-    /**
-     * Returns hash code current the underlying File reference.
-     */
-    @Override
-    public int hashCode() {
-        return this.file.hashCode();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
deleted file mode 100644
index d4aa673..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.resource.internal;
-
-import org.apache.tamaya.resource.Resource;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.Objects;
-
-/**
- * Simple Resource encapsulating an InputStream.
- */
-public class InputStreamResource implements Resource {
-
-    /** The InputStream. */
-    private final InputStream inputStream;
-    /** The read flag. */
-    private boolean read = false;
-    /** The name of the resource. */
-    private String name;
-
-
-    /**
-     * Create a new InputStreamResource.
-     *
-     * @param inputStream the InputStream to use
-     */
-    public InputStreamResource(InputStream inputStream) {
-        this(inputStream, "InputStream:");
-    }
-
-    /**
-     * Create a new InputStreamResource.
-     *
-     * @param inputStream the InputStream to use
-     * @param name where the InputStream comes from
-     */
-    public InputStreamResource(InputStream inputStream, String name) {
-        this.inputStream = Objects.requireNonNull(inputStream);
-        this.name = (name != null ? name : "InputStream");
-    }
-
-
-    /**
-     * This implementation always returns {@code true}.
-     */
-    @Override
-    public boolean exists() {
-        return true;
-    }
-
-    @Override
-    public URI toURI() throws IOException {
-        throw new IOException("URI not available.");
-    }
-
-    @Override
-    public long lastModified() throws IOException {
-        throw new IOException("lastModified not available.");
-    }
-
-    /**
-     * Accesses the input stream. Hereby the input stream can only accessed once.
-     */
-    @Override
-    public InputStream get() {
-        if (this.read) {
-            throw new IllegalStateException("InputStream can only be read once!");
-        }
-        this.read = true;
-        return this.inputStream;
-    }
-
-    /**
-     * This implementation returns the passed-in description, if any.
-     */
-    public String toString() {
-        return this.name != null ? this.name : super.toString();
-    }
-
-
-    /**
-     * Compares the underlying InputStream.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        return (obj == this ||
-                (obj instanceof InputStreamResource && ((InputStreamResource) obj).inputStream.equals(this.inputStream)));
-    }
-
-    /**
-     * This implementation returns the hash code current the underlying InputStream.
-     */
-    @Override
-    public int hashCode() {
-        return this.inputStream.hashCode();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
new file mode 100644
index 0000000..8d9e08a
--- /dev/null
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
@@ -0,0 +1,150 @@
+/*
+ * 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.resource.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Small helper class that manages the path parts of a location expression.
+ */
+final class Locator {
+    /**
+     * The tokenized location expression.
+     */
+    private List<String> tokens;
+
+    /**
+     * Creates a new instances based on the tokenized expression.
+     *
+     * @param tokens the tokenized expression, not null.
+     */
+    Locator(List<String> tokens) {
+        this.tokens = tokens;
+    }
+
+    /**
+     * Creates a new instance of the corresponding expression.
+     *
+     * @param expression the location expression, not null.
+     * @return the tokenized instance.
+     */
+    public static Locator of(String expression) {
+        return new Locator(Arrays.asList(expression.split("/")).stream().filter((s) -> !s.isEmpty()).collect(Collectors.toList()));
+    }
+
+    /**
+     * Access the root path, which is the location expression, before any wildcards or placeholders are used.
+     * It is used as the entry point into the file system or for accessing base classpath resources, before
+     * further analysis on the file or jar filesystem can be performed.
+     *
+     * @return the root path, never null.
+     */
+    public String getRootPath() {
+        StringBuilder builder = new StringBuilder();
+        for (String token : tokens) {
+            if (containsPlaceholder(token)) {
+                break;
+            } else {
+                builder.append(token);
+                builder.append('/');
+            }
+        }
+        if (builder.length() > 0) {
+            builder.setLength(builder.length() - 1);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Return the sub expression path, which contains the second part of the expression, starting with a placeholder
+     * or wildcard token.
+     *
+     * @return the sub expression part, never null.
+     */
+    public String getSubPath() {
+        StringBuilder builder = new StringBuilder();
+        for (String token : getSubPathTokens()) {
+            builder.append(token);
+            builder.append('/');
+        }
+        if (builder.length() > 0) {
+            builder.setLength(builder.length() - 1);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * This method returns the single tokenized form of the sub expression.
+     *
+     * @return the tokenized version of the sub path.
+     * @see #getSubPath()
+     */
+    public List<String> getSubPathTokens() {
+        List<String> subTokens = new ArrayList<>();
+        for (String token : tokens) {
+            if (!containsPlaceholder(token)) {
+                continue;
+            } else {
+                subTokens.add(token);
+            }
+        }
+        return subTokens;
+    }
+
+    /**
+     * Access the full reconstructed path. In most cases this should match the original expression.
+     *
+     * @return the full expression path, never null.
+     */
+    public String getPath() {
+        StringBuilder builder = new StringBuilder();
+        for (String token : tokens) {
+            builder.append(token);
+            builder.append('/');
+        }
+        if (builder.length() > 0) {
+            builder.setLength(builder.length() - 1);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Short method that checks for '*' and '?' chars.
+     *
+     * @param token the token to check, not null
+     * @return true, if it contains wildcard characters.
+     */
+    private boolean containsPlaceholder(String token) {
+        return token.contains("*") || token.contains("?");
+    }
+
+    /**
+     * Return the expressions' path.
+     *
+     * @return the locator path.
+     */
+    @Override
+    public String toString() {
+        return "Locator: " + getPath();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
deleted file mode 100644
index 6522cf5..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.resource.internal;
-
-import org.apache.tamaya.resource.Resource;
-
-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;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Implementation of a resource based on a {@code java.net.URL}.
- */
-public class UrlResource implements Resource {
-
-    private static final Logger LOG = Logger.getLogger(UrlResource.class.getName());
-
-    /**
-     * Original URL, used for actual access.
-     */
-    private final URL url;
-
-    /**
-     * Create a new instance based on the given URL.
-     *
-     * @param url a URL
-     */
-    public UrlResource(URL url) {
-        this.url = Objects.requireNonNull(url, "URL null");
-    }
-
-    /**
-     * Create a new URLResource based on a URL path.
-     *
-     * @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.url = new URL(path);
-    }
-
-
-    /**
-     * This implementation opens an InputStream for the given URL.
-     *
-     * @see java.net.URL#openConnection()
-     * @see java.net.URLConnection#setUseCaches(boolean)
-     * @see java.net.URLConnection#getInputStream()
-     */
-    @Override
-    public InputStream get() {
-        URLConnection con = null;
-        try {
-            con = this.url.openConnection();
-            useCachesIfNecessary(con);
-            return con.getInputStream();
-        } catch (IOException e) {
-            if (con instanceof HttpURLConnection) {
-                ((HttpURLConnection) con).disconnect();
-            }
-            LOG.log(Level.INFO, "Failed to open URL: " + url, e);
-            return null;
-        }
-    }
-
-    @Override
-    public URI toURI() throws IOException {
-        try {
-            return this.url.toURI();
-        } catch (URISyntaxException e) {
-            throw new IOException("Failed to create URI from " + url);
-        }
-    }
-
-    @Override
-    public String getName() {
-        return this.url.toString();
-    }
-
-    @Override
-    public String toString() {
-        return "URL [" + this.url + "]";
-    }
-
-    /**
-     * Compares the underlying URL references.
-     */
-    @Override
-    public boolean equals(Object obj) {
-        return (obj == this ||
-                (obj instanceof UrlResource && this.url.equals(((UrlResource) obj).url)));
-    }
-
-    /**
-     * This implementation returns the hash code current the underlying URL reference.
-     */
-    @Override
-    public int hashCode() {
-        return this.url.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 format.
-     *
-     * @param con the URLConnection to set the flag on
-     */
-    private void useCachesIfNecessary(URLConnection con) {
-        con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
-    }
-
-}
-


Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Mark Struberg <st...@yahoo.de>.
probably have 2 ways as already explained:

1.) a single ConfigSource with an URL parameter
2.) a classpath resource name -> register multiple ConfigSources.

That will probably solve 98% of all cases. And this is really easy to do and perfectly portable as well.

LieGrue,
strub





> On Sunday, 11 January 2015, 18:07, Romain Manni-Bucau <rm...@gmail.com> wrote:
> > What's your base use case? why not classpath: ->
> loader.getResources(path)? Do you need something else than an
> inputstream?
> 
> Side note: we already said you the only way to solve it is to allow
> user to extend your code base which is surely overcomplicated but
> tamaya needs IMO.
> 
> 
> 2015-01-11 18:01 GMT+01:00 Anatole Tresch <an...@apache.org>:
>>  Basically I dont care. Instead of listing me how bloated things are, start
>>  discussing how it can be solved. I have a crucial use case here, that must
>>  be solved. I have a solution that many users are satisifed with and which
>>  works well in SE as well as in Weblogic (Credit Suisse). Either make a
>>  proposal how things can be improved or live with what we have IMO.
>> 
>>  2015-01-11 17:57 GMT+01:00 Anatole Tresch <at...@gmail.com>:
>> 
>>>  Basically I dont care. Instead of listing me how bloated things are, 
> start
>>>  discussing how it can be solved. I have a crucial use case here, that 
> must
>>>  be solved. I have a solution that many users are satisifed with and 
> which
>>>  works well in SE as well as in Weblogic (Credit Suisse). Either make a
>>>  proposal how things can be improved or live with what we have IMO.
>>> 
>>>  2015-01-11 16:40 GMT+01:00 Romain Manni-Bucau 
> <rm...@gmail.com>:
>>> 
>>>>  2015-01-11 14:52 GMT+01:00 Anatole Tresch 
> <at...@gmail.com>:
>>>>  > Hi Mark
>>>>  >
>>>>  > some more input:
>>>>  >
>>>>  > 2015-01-11 11:54 GMT+01:00 Mark Struberg 
> <st...@yahoo.de>:
>>>>  >
>>>>  >> Hi!
>>>>  >>
>>>>  >> > I do not agree. It works relatively well for
>>>>  >>
>>>>  >> > many cases. Nobody using
>>>>  >> > Spring did much have complains on it.
>>>>  >> a.) They did have huge problems. That was the reason why 
> they have
>>>>  special
>>>>  >> hacks for every JBoss container for example
>>>>  >>
>>>>  > For Credit Suisse and most of my colleagues it does what it 
> should. I
>>>>  > looked at the code of Spring as well, and so only very few 
> specifics,
>>>>  which
>>>>  > does not look to be very specialized for one JBoss version.
>>>>  >
>>>> 
>>>>  what about others? Spring works mainly cause it has other hacks for
>>>>  other environment in other modules as well.
>>>> 
>>>>  >
>>>>  >> b.) Springs solution now is pretty bloated because of 
> that. It's not
>>>>  just
>>>>  >> 20k it's rather 200k and bigger.
>>>>  >>
>>>>  >
>>>>  > That has various reasons, one of the are the abstractions 
> chosen. The
>>>>  > current solution in Tamaya is about 20k and does basically 
> exactly the
>>>>  same
>>>>  > as Spring - despite the special handling of Vfs. Perhaps we 
> should
>>>>  focus on
>>>>  > what was went wrong in the past and I will double check if 
> that would
>>>>  be an
>>>>  > issue with the current apporach.
>>>>  >
>>>> 
>>>>  Mark is really true saying there is *NO* way to do it right without 
> a
>>>>  SPI and letting the user change it for all not default environments
>>>>  (not openjdk based JVMs, custom handlers etc...). And there are 
> more
>>>>  numerous than JBoss.
>>>> 
>>>>  > CU
>>>>  > ANatole
>>>>  >
>>>>  >
>>>>  >
>>>>  >
>>>>  >
>>>>  >>
>>>>  >> > And on top: I do not need a "perfect" 
> solution
>>>>  >> Just like to make you aware of the issue we will face with 
> it.
>>>>  >>
>>>>  >>
>>>>  >>
>>>>  >> > Lets take it up later at the hangout.
>>>>  >> +1
>>>>  >>
>>>>  >> LieGrue,
>>>>  >> strub
>>>>  >>
>>>>  >>
>>>>  >>
>>>>  >>
>>>>  >> > On Sunday, 11 January 2015, 11:33, Anatole Tresch 
> <
>>>>  atsticks@gmail.com>
>>>>  >> wrote:
>>>>  >> > > Hi Mark
>>>>  >> >
>>>>  >> > I do not agree. It works relatively well for many 
> cases. Nobody using
>>>>  >> > Spring did much have complains on it. And on top: I 
> do not need a
>>>>  >> > "perfect"
>>>>  >> > solution, I need a feasible solution. Lets document 
> its limits and be
>>>>  >> with
>>>>  >> > it. And you example and proposal simply does not 
> cover my use case ;(
>>>>  >> >
>>>>  >> > Lets take it up later at the hangout.
>>>>  >> >
>>>>  >> > Cheers,
>>>>  >> > Anatole
>>>>  >> >
>>>>  >> >
>>>>  >> > 2015-01-11 11:16 GMT+01:00 Mark Struberg 
> <st...@yahoo.de>:
>>>>  >> >
>>>>  >> >>  Anatole, again:
>>>>  >> >>
>>>>  >> >>
>>>>  >> >>  > PROTOCOL_WSJAR
>>>>  >> >>
>>>>  >> >>
>>>>  >> >>  All this does NOT work portably!
>>>>  >> >>  Many people tried that many times and it simply 
> does NOT work that
>>>>  >> easily!
>>>>  >> >>  The solution I know to work (xban-finder) 
> explicitly has exit
>>>>  points to
>>>>  >> >>  extend archive handlers. And it is about 
> 200kByte of size
>>>>  alltogether.
>>>>  >> >>
>>>>  >> >>
>>>>  >> >>  The problem with such a solution is that we must 
> support it
>>>>  perfectly
>>>>  >> >>  well, or not at all...
>>>>  >> >>
>>>>  >> >>  What we *could* support is a _very_ easy 
> solution with a prefix
>>>>  >> >>
>>>>  >> >>  classpath-config:mydir/myconfig.properties
>>>>  >> >>  vs a real URL e.g. file://
>>>>  >> >>
>>>>  >> >>  In the first case we would simply use 
> ClassLoader.getResources and
>>>>  >> >>  register 0..n ConfigSources, in the second case 
> we register exactly
>>>>  >> the one
>>>>  >> >>  URL we got handed over as parameter.
>>>>  >> >>
>>>>  >> >>  Also note that any wildcard style in an URL or 
> classpath resource
>>>>  is
>>>>  >> NOT
>>>>  >> >>  widely supported. Some ClassLoaders can handle 
> it in SOME
>>>>  situations,
>>>>  >> but
>>>>  >> >>  most of them don't.
>>>>  >> >>
>>>>  >> >>  LieGrue,
>>>>  >> >>  strub
>>>>  >> >>
>>>>  >> >>
>>>>  >>
>>>>  >
>>>>  >
>>>>  >
>>>>  > --
>>>>  > *Anatole Tresch*
>>>>  > Java Engineer & Architect, JSR Spec Lead
>>>>  > Glärnischweg 10
>>>>  > CH - 8620 Wetzikon
>>>>  >
>>>>  > *Switzerland, Europe Zurich, GMT+1*
>>>>  > *Twitter:  @atsticks*
>>>>  > *Blogs: **http://javaremarkables.blogspot.ch/
>>>>  > <http://javaremarkables.blogspot.ch/>*
>>>>  >
>>>>  > *Google: atsticksMobile  +41-76 344 62 79*
>>>> 
>>> 
>>> 
>>> 
>>>  --
>>>  *Anatole Tresch*
>>>  Java Engineer & Architect, JSR Spec Lead
>>>  Glärnischweg 10
>>>  CH - 8620 Wetzikon
>>> 
>>>  *Switzerland, Europe Zurich, GMT+1*
>>>  *Twitter:  @atsticks*
>>>  *Blogs: **http://javaremarkables.blogspot.ch/
>>>  <http://javaremarkables.blogspot.ch/>*
>>> 
>>>  *Google: atsticksMobile  +41-76 344 62 79 
> <%2B41-76%20344%2062%2079>*
>>> 
>

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Romain Manni-Bucau <rm...@gmail.com>.
What's your base use case? why not classpath: ->
loader.getResources(path)? Do you need something else than an
inputstream?

Side note: we already said you the only way to solve it is to allow
user to extend your code base which is surely overcomplicated but
tamaya needs IMO.

2015-01-11 18:01 GMT+01:00 Anatole Tresch <an...@apache.org>:
> Basically I dont care. Instead of listing me how bloated things are, start
> discussing how it can be solved. I have a crucial use case here, that must
> be solved. I have a solution that many users are satisifed with and which
> works well in SE as well as in Weblogic (Credit Suisse). Either make a
> proposal how things can be improved or live with what we have IMO.
>
> 2015-01-11 17:57 GMT+01:00 Anatole Tresch <at...@gmail.com>:
>
>> Basically I dont care. Instead of listing me how bloated things are, start
>> discussing how it can be solved. I have a crucial use case here, that must
>> be solved. I have a solution that many users are satisifed with and which
>> works well in SE as well as in Weblogic (Credit Suisse). Either make a
>> proposal how things can be improved or live with what we have IMO.
>>
>> 2015-01-11 16:40 GMT+01:00 Romain Manni-Bucau <rm...@gmail.com>:
>>
>>> 2015-01-11 14:52 GMT+01:00 Anatole Tresch <at...@gmail.com>:
>>> > Hi Mark
>>> >
>>> > some more input:
>>> >
>>> > 2015-01-11 11:54 GMT+01:00 Mark Struberg <st...@yahoo.de>:
>>> >
>>> >> Hi!
>>> >>
>>> >> > I do not agree. It works relatively well for
>>> >>
>>> >> > many cases. Nobody using
>>> >> > Spring did much have complains on it.
>>> >> a.) They did have huge problems. That was the reason why they have
>>> special
>>> >> hacks for every JBoss container for example
>>> >>
>>> > For Credit Suisse and most of my colleagues it does what it should. I
>>> > looked at the code of Spring as well, and so only very few specifics,
>>> which
>>> > does not look to be very specialized for one JBoss version.
>>> >
>>>
>>> what about others? Spring works mainly cause it has other hacks for
>>> other environment in other modules as well.
>>>
>>> >
>>> >> b.) Springs solution now is pretty bloated because of that. It's not
>>> just
>>> >> 20k it's rather 200k and bigger.
>>> >>
>>> >
>>> > That has various reasons, one of the are the abstractions chosen. The
>>> > current solution in Tamaya is about 20k and does basically exactly the
>>> same
>>> > as Spring - despite the special handling of Vfs. Perhaps we should
>>> focus on
>>> > what was went wrong in the past and I will double check if that would
>>> be an
>>> > issue with the current apporach.
>>> >
>>>
>>> Mark is really true saying there is *NO* way to do it right without a
>>> SPI and letting the user change it for all not default environments
>>> (not openjdk based JVMs, custom handlers etc...). And there are more
>>> numerous than JBoss.
>>>
>>> > CU
>>> > ANatole
>>> >
>>> >
>>> >
>>> >
>>> >
>>> >>
>>> >> > And on top: I do not need a "perfect" solution
>>> >> Just like to make you aware of the issue we will face with it.
>>> >>
>>> >>
>>> >>
>>> >> > Lets take it up later at the hangout.
>>> >> +1
>>> >>
>>> >> LieGrue,
>>> >> strub
>>> >>
>>> >>
>>> >>
>>> >>
>>> >> > On Sunday, 11 January 2015, 11:33, Anatole Tresch <
>>> atsticks@gmail.com>
>>> >> wrote:
>>> >> > > Hi Mark
>>> >> >
>>> >> > I do not agree. It works relatively well for many cases. Nobody using
>>> >> > Spring did much have complains on it. And on top: I do not need a
>>> >> > "perfect"
>>> >> > solution, I need a feasible solution. Lets document its limits and be
>>> >> with
>>> >> > it. And you example and proposal simply does not cover my use case ;(
>>> >> >
>>> >> > Lets take it up later at the hangout.
>>> >> >
>>> >> > Cheers,
>>> >> > Anatole
>>> >> >
>>> >> >
>>> >> > 2015-01-11 11:16 GMT+01:00 Mark Struberg <st...@yahoo.de>:
>>> >> >
>>> >> >>  Anatole, again:
>>> >> >>
>>> >> >>
>>> >> >>  > PROTOCOL_WSJAR
>>> >> >>
>>> >> >>
>>> >> >>  All this does NOT work portably!
>>> >> >>  Many people tried that many times and it simply does NOT work that
>>> >> easily!
>>> >> >>  The solution I know to work (xban-finder) explicitly has exit
>>> points to
>>> >> >>  extend archive handlers. And it is about 200kByte of size
>>> alltogether.
>>> >> >>
>>> >> >>
>>> >> >>  The problem with such a solution is that we must support it
>>> perfectly
>>> >> >>  well, or not at all...
>>> >> >>
>>> >> >>  What we *could* support is a _very_ easy solution with a prefix
>>> >> >>
>>> >> >>  classpath-config:mydir/myconfig.properties
>>> >> >>  vs a real URL e.g. file://
>>> >> >>
>>> >> >>  In the first case we would simply use ClassLoader.getResources and
>>> >> >>  register 0..n ConfigSources, in the second case we register exactly
>>> >> the one
>>> >> >>  URL we got handed over as parameter.
>>> >> >>
>>> >> >>  Also note that any wildcard style in an URL or classpath resource
>>> is
>>> >> NOT
>>> >> >>  widely supported. Some ClassLoaders can handle it in SOME
>>> situations,
>>> >> but
>>> >> >>  most of them don't.
>>> >> >>
>>> >> >>  LieGrue,
>>> >> >>  strub
>>> >> >>
>>> >> >>
>>> >>
>>> >
>>> >
>>> >
>>> > --
>>> > *Anatole Tresch*
>>> > Java Engineer & Architect, JSR Spec Lead
>>> > Glärnischweg 10
>>> > CH - 8620 Wetzikon
>>> >
>>> > *Switzerland, Europe Zurich, GMT+1*
>>> > *Twitter:  @atsticks*
>>> > *Blogs: **http://javaremarkables.blogspot.ch/
>>> > <http://javaremarkables.blogspot.ch/>*
>>> >
>>> > *Google: atsticksMobile  +41-76 344 62 79*
>>>
>>
>>
>>
>> --
>> *Anatole Tresch*
>> Java Engineer & Architect, JSR Spec Lead
>> Glärnischweg 10
>> CH - 8620 Wetzikon
>>
>> *Switzerland, Europe Zurich, GMT+1*
>> *Twitter:  @atsticks*
>> *Blogs: **http://javaremarkables.blogspot.ch/
>> <http://javaremarkables.blogspot.ch/>*
>>
>> *Google: atsticksMobile  +41-76 344 62 79 <%2B41-76%20344%2062%2079>*
>>

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Anatole Tresch <an...@apache.org>.
Basically I dont care. Instead of listing me how bloated things are, start
discussing how it can be solved. I have a crucial use case here, that must
be solved. I have a solution that many users are satisifed with and which
works well in SE as well as in Weblogic (Credit Suisse). Either make a
proposal how things can be improved or live with what we have IMO.

2015-01-11 17:57 GMT+01:00 Anatole Tresch <at...@gmail.com>:

> Basically I dont care. Instead of listing me how bloated things are, start
> discussing how it can be solved. I have a crucial use case here, that must
> be solved. I have a solution that many users are satisifed with and which
> works well in SE as well as in Weblogic (Credit Suisse). Either make a
> proposal how things can be improved or live with what we have IMO.
>
> 2015-01-11 16:40 GMT+01:00 Romain Manni-Bucau <rm...@gmail.com>:
>
>> 2015-01-11 14:52 GMT+01:00 Anatole Tresch <at...@gmail.com>:
>> > Hi Mark
>> >
>> > some more input:
>> >
>> > 2015-01-11 11:54 GMT+01:00 Mark Struberg <st...@yahoo.de>:
>> >
>> >> Hi!
>> >>
>> >> > I do not agree. It works relatively well for
>> >>
>> >> > many cases. Nobody using
>> >> > Spring did much have complains on it.
>> >> a.) They did have huge problems. That was the reason why they have
>> special
>> >> hacks for every JBoss container for example
>> >>
>> > For Credit Suisse and most of my colleagues it does what it should. I
>> > looked at the code of Spring as well, and so only very few specifics,
>> which
>> > does not look to be very specialized for one JBoss version.
>> >
>>
>> what about others? Spring works mainly cause it has other hacks for
>> other environment in other modules as well.
>>
>> >
>> >> b.) Springs solution now is pretty bloated because of that. It's not
>> just
>> >> 20k it's rather 200k and bigger.
>> >>
>> >
>> > That has various reasons, one of the are the abstractions chosen. The
>> > current solution in Tamaya is about 20k and does basically exactly the
>> same
>> > as Spring - despite the special handling of Vfs. Perhaps we should
>> focus on
>> > what was went wrong in the past and I will double check if that would
>> be an
>> > issue with the current apporach.
>> >
>>
>> Mark is really true saying there is *NO* way to do it right without a
>> SPI and letting the user change it for all not default environments
>> (not openjdk based JVMs, custom handlers etc...). And there are more
>> numerous than JBoss.
>>
>> > CU
>> > ANatole
>> >
>> >
>> >
>> >
>> >
>> >>
>> >> > And on top: I do not need a "perfect" solution
>> >> Just like to make you aware of the issue we will face with it.
>> >>
>> >>
>> >>
>> >> > Lets take it up later at the hangout.
>> >> +1
>> >>
>> >> LieGrue,
>> >> strub
>> >>
>> >>
>> >>
>> >>
>> >> > On Sunday, 11 January 2015, 11:33, Anatole Tresch <
>> atsticks@gmail.com>
>> >> wrote:
>> >> > > Hi Mark
>> >> >
>> >> > I do not agree. It works relatively well for many cases. Nobody using
>> >> > Spring did much have complains on it. And on top: I do not need a
>> >> > "perfect"
>> >> > solution, I need a feasible solution. Lets document its limits and be
>> >> with
>> >> > it. And you example and proposal simply does not cover my use case ;(
>> >> >
>> >> > Lets take it up later at the hangout.
>> >> >
>> >> > Cheers,
>> >> > Anatole
>> >> >
>> >> >
>> >> > 2015-01-11 11:16 GMT+01:00 Mark Struberg <st...@yahoo.de>:
>> >> >
>> >> >>  Anatole, again:
>> >> >>
>> >> >>
>> >> >>  > PROTOCOL_WSJAR
>> >> >>
>> >> >>
>> >> >>  All this does NOT work portably!
>> >> >>  Many people tried that many times and it simply does NOT work that
>> >> easily!
>> >> >>  The solution I know to work (xban-finder) explicitly has exit
>> points to
>> >> >>  extend archive handlers. And it is about 200kByte of size
>> alltogether.
>> >> >>
>> >> >>
>> >> >>  The problem with such a solution is that we must support it
>> perfectly
>> >> >>  well, or not at all...
>> >> >>
>> >> >>  What we *could* support is a _very_ easy solution with a prefix
>> >> >>
>> >> >>  classpath-config:mydir/myconfig.properties
>> >> >>  vs a real URL e.g. file://
>> >> >>
>> >> >>  In the first case we would simply use ClassLoader.getResources and
>> >> >>  register 0..n ConfigSources, in the second case we register exactly
>> >> the one
>> >> >>  URL we got handed over as parameter.
>> >> >>
>> >> >>  Also note that any wildcard style in an URL or classpath resource
>> is
>> >> NOT
>> >> >>  widely supported. Some ClassLoaders can handle it in SOME
>> situations,
>> >> but
>> >> >>  most of them don't.
>> >> >>
>> >> >>  LieGrue,
>> >> >>  strub
>> >> >>
>> >> >>
>> >>
>> >
>> >
>> >
>> > --
>> > *Anatole Tresch*
>> > Java Engineer & Architect, JSR Spec Lead
>> > Glärnischweg 10
>> > CH - 8620 Wetzikon
>> >
>> > *Switzerland, Europe Zurich, GMT+1*
>> > *Twitter:  @atsticks*
>> > *Blogs: **http://javaremarkables.blogspot.ch/
>> > <http://javaremarkables.blogspot.ch/>*
>> >
>> > *Google: atsticksMobile  +41-76 344 62 79*
>>
>
>
>
> --
> *Anatole Tresch*
> Java Engineer & Architect, JSR Spec Lead
> Glärnischweg 10
> CH - 8620 Wetzikon
>
> *Switzerland, Europe Zurich, GMT+1*
> *Twitter:  @atsticks*
> *Blogs: **http://javaremarkables.blogspot.ch/
> <http://javaremarkables.blogspot.ch/>*
>
> *Google: atsticksMobile  +41-76 344 62 79 <%2B41-76%20344%2062%2079>*
>

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Romain Manni-Bucau <rm...@gmail.com>.
2015-01-11 14:52 GMT+01:00 Anatole Tresch <at...@gmail.com>:
> Hi Mark
>
> some more input:
>
> 2015-01-11 11:54 GMT+01:00 Mark Struberg <st...@yahoo.de>:
>
>> Hi!
>>
>> > I do not agree. It works relatively well for
>>
>> > many cases. Nobody using
>> > Spring did much have complains on it.
>> a.) They did have huge problems. That was the reason why they have special
>> hacks for every JBoss container for example
>>
> For Credit Suisse and most of my colleagues it does what it should. I
> looked at the code of Spring as well, and so only very few specifics, which
> does not look to be very specialized for one JBoss version.
>

what about others? Spring works mainly cause it has other hacks for
other environment in other modules as well.

>
>> b.) Springs solution now is pretty bloated because of that. It's not just
>> 20k it's rather 200k and bigger.
>>
>
> That has various reasons, one of the are the abstractions chosen. The
> current solution in Tamaya is about 20k and does basically exactly the same
> as Spring - despite the special handling of Vfs. Perhaps we should focus on
> what was went wrong in the past and I will double check if that would be an
> issue with the current apporach.
>

Mark is really true saying there is *NO* way to do it right without a
SPI and letting the user change it for all not default environments
(not openjdk based JVMs, custom handlers etc...). And there are more
numerous than JBoss.

> CU
> ANatole
>
>
>
>
>
>>
>> > And on top: I do not need a "perfect" solution
>> Just like to make you aware of the issue we will face with it.
>>
>>
>>
>> > Lets take it up later at the hangout.
>> +1
>>
>> LieGrue,
>> strub
>>
>>
>>
>>
>> > On Sunday, 11 January 2015, 11:33, Anatole Tresch <at...@gmail.com>
>> wrote:
>> > > Hi Mark
>> >
>> > I do not agree. It works relatively well for many cases. Nobody using
>> > Spring did much have complains on it. And on top: I do not need a
>> > "perfect"
>> > solution, I need a feasible solution. Lets document its limits and be
>> with
>> > it. And you example and proposal simply does not cover my use case ;(
>> >
>> > Lets take it up later at the hangout.
>> >
>> > Cheers,
>> > Anatole
>> >
>> >
>> > 2015-01-11 11:16 GMT+01:00 Mark Struberg <st...@yahoo.de>:
>> >
>> >>  Anatole, again:
>> >>
>> >>
>> >>  > PROTOCOL_WSJAR
>> >>
>> >>
>> >>  All this does NOT work portably!
>> >>  Many people tried that many times and it simply does NOT work that
>> easily!
>> >>  The solution I know to work (xban-finder) explicitly has exit points to
>> >>  extend archive handlers. And it is about 200kByte of size alltogether.
>> >>
>> >>
>> >>  The problem with such a solution is that we must support it perfectly
>> >>  well, or not at all...
>> >>
>> >>  What we *could* support is a _very_ easy solution with a prefix
>> >>
>> >>  classpath-config:mydir/myconfig.properties
>> >>  vs a real URL e.g. file://
>> >>
>> >>  In the first case we would simply use ClassLoader.getResources and
>> >>  register 0..n ConfigSources, in the second case we register exactly
>> the one
>> >>  URL we got handed over as parameter.
>> >>
>> >>  Also note that any wildcard style in an URL or classpath resource is
>> NOT
>> >>  widely supported. Some ClassLoaders can handle it in SOME situations,
>> but
>> >>  most of them don't.
>> >>
>> >>  LieGrue,
>> >>  strub
>> >>
>> >>
>>
>
>
>
> --
> *Anatole Tresch*
> Java Engineer & Architect, JSR Spec Lead
> Glärnischweg 10
> CH - 8620 Wetzikon
>
> *Switzerland, Europe Zurich, GMT+1*
> *Twitter:  @atsticks*
> *Blogs: **http://javaremarkables.blogspot.ch/
> <http://javaremarkables.blogspot.ch/>*
>
> *Google: atsticksMobile  +41-76 344 62 79*

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Anatole Tresch <at...@gmail.com>.
Hi Mark

some more input:

2015-01-11 11:54 GMT+01:00 Mark Struberg <st...@yahoo.de>:

> Hi!
>
> > I do not agree. It works relatively well for
>
> > many cases. Nobody using
> > Spring did much have complains on it.
> a.) They did have huge problems. That was the reason why they have special
> hacks for every JBoss container for example
>
​For Credit Suisse and most of my colleagues it does what it should. ​I
looked at the code of Spring as well, and so only very few specifics, which
does not look to be very specialized for one JBoss version.


> b.) Springs solution now is pretty bloated because of that. It's not just
> 20k it's rather 200k and bigger.
>

​That has various reasons, one of the are the abstractions chosen. The
current solution in Tamaya is about 20k and does basically exactly the same
as Spring - despite the special handling of Vfs. Perhaps we should focus on
what was went wrong in the past and I will double check if that would be an
issue with the current apporach.

​CU
ANatole
​




>
> > And on top: I do not need a "perfect" solution
> Just like to make you aware of the issue we will face with it.
>
>
>
> > Lets take it up later at the hangout.
> +1
>
> LieGrue,
> strub
>
>
>
>
> > On Sunday, 11 January 2015, 11:33, Anatole Tresch <at...@gmail.com>
> wrote:
> > > Hi Mark
> >
> > I do not agree. It works relatively well for many cases. Nobody using
> > Spring did much have complains on it. And on top: I do not need a
> > "perfect"
> > solution, I need a feasible solution. Lets document its limits and be
> with
> > it. And you example and proposal simply does not cover my use case ;(
> >
> > Lets take it up later at the hangout.
> >
> > Cheers,
> > Anatole
> >
> >
> > 2015-01-11 11:16 GMT+01:00 Mark Struberg <st...@yahoo.de>:
> >
> >>  Anatole, again:
> >>
> >>
> >>  > PROTOCOL_WSJAR
> >>
> >>
> >>  All this does NOT work portably!
> >>  Many people tried that many times and it simply does NOT work that
> easily!
> >>  The solution I know to work (xban-finder) explicitly has exit points to
> >>  extend archive handlers. And it is about 200kByte of size alltogether.
> >>
> >>
> >>  The problem with such a solution is that we must support it perfectly
> >>  well, or not at all...
> >>
> >>  What we *could* support is a _very_ easy solution with a prefix
> >>
> >>  classpath-config:mydir/myconfig.properties
> >>  vs a real URL e.g. file://
> >>
> >>  In the first case we would simply use ClassLoader.getResources and
> >>  register 0..n ConfigSources, in the second case we register exactly
> the one
> >>  URL we got handed over as parameter.
> >>
> >>  Also note that any wildcard style in an URL or classpath resource is
> NOT
> >>  widely supported. Some ClassLoaders can handle it in SOME situations,
> but
> >>  most of them don't.
> >>
> >>  LieGrue,
> >>  strub
> >>
> >>
>



-- 
*Anatole Tresch*
Java Engineer & Architect, JSR Spec Lead
Glärnischweg 10
CH - 8620 Wetzikon

*Switzerland, Europe Zurich, GMT+1*
*Twitter:  @atsticks*
*Blogs: **http://javaremarkables.blogspot.ch/
<http://javaremarkables.blogspot.ch/>*

*Google: atsticksMobile  +41-76 344 62 79*

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Mark Struberg <st...@yahoo.de>.
Hi!

> I do not agree. It works relatively well for 

> many cases. Nobody using
> Spring did much have complains on it.
a.) They did have huge problems. That was the reason why they have special hacks for every JBoss container for example

b.) Springs solution now is pretty bloated because of that. It's not just 20k it's rather 200k and bigger.


> And on top: I do not need a "perfect" solution
Just like to make you aware of the issue we will face with it.



> Lets take it up later at the hangout.
+1

LieGrue,
strub




> On Sunday, 11 January 2015, 11:33, Anatole Tresch <at...@gmail.com> wrote:
> > Hi Mark
> 
> I do not agree. It works relatively well for many cases. Nobody using
> Spring did much have complains on it. And on top: I do not need a 
> "perfect"
> solution, I need a feasible solution. Lets document its limits and be with
> it. And you example and proposal simply does not cover my use case ;(
> 
> Lets take it up later at the hangout.
> 
> Cheers,
> Anatole
> 
> 
> 2015-01-11 11:16 GMT+01:00 Mark Struberg <st...@yahoo.de>:
> 
>>  Anatole, again:
>> 
>> 
>>  > PROTOCOL_WSJAR
>> 
>> 
>>  All this does NOT work portably!
>>  Many people tried that many times and it simply does NOT work that easily!
>>  The solution I know to work (xban-finder) explicitly has exit points to
>>  extend archive handlers. And it is about 200kByte of size alltogether.
>> 
>> 
>>  The problem with such a solution is that we must support it perfectly
>>  well, or not at all...
>> 
>>  What we *could* support is a _very_ easy solution with a prefix
>> 
>>  classpath-config:mydir/myconfig.properties
>>  vs a real URL e.g. file://
>> 
>>  In the first case we would simply use ClassLoader.getResources and
>>  register 0..n ConfigSources, in the second case we register exactly the one
>>  URL we got handed over as parameter.
>> 
>>  Also note that any wildcard style in an URL or classpath resource is NOT
>>  widely supported. Some ClassLoaders can handle it in SOME situations, but
>>  most of them don't.
>> 
>>  LieGrue,
>>  strub
>> 
>> 

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Anatole Tresch <at...@gmail.com>.
Hi Mark

I do not agree. It works relatively well for many cases. Nobody using
Spring did much have complains on it. And on top: I do not need a "perfect"
solution, I need a feasible solution. Lets document its limits and be with
it. And you example and proposal simply does not cover my use case ;(

Lets take it up later at the hangout.

Cheers,
Anatole


2015-01-11 11:16 GMT+01:00 Mark Struberg <st...@yahoo.de>:

> Anatole, again:
>
>
> > PROTOCOL_WSJAR
>
>
> All this does NOT work portably!
> Many people tried that many times and it simply does NOT work that easily!
> The solution I know to work (xban-finder) explicitly has exit points to
> extend archive handlers. And it is about 200kByte of size alltogether.
>
>
> The problem with such a solution is that we must support it perfectly
> well, or not at all...
>
> What we *could* support is a _very_ easy solution with a prefix
>
> classpath-config:mydir/myconfig.properties
> vs a real URL e.g. file://
>
> In the first case we would simply use ClassLoader.getResources and
> register 0..n ConfigSources, in the second case we register exactly the one
> URL we got handed over as parameter.
>
> Also note that any wildcard style in an URL or classpath resource is NOT
> widely supported. Some ClassLoaders can handle it in SOME situations, but
> most of them don't.
>
> LieGrue,
> strub
>
>
>
>
>
> > On Sunday, 11 January 2015, 1:44, "anatole@apache.org" <
> anatole@apache.org> wrote:
> > > Repository: incubator-tamaya
> > Updated Branches:
> >   refs/heads/master 2dd0c13e5 -> c48c5794e
> >
> >
> > TAMAYA-43: Implemented ant pattern based resource lookup for files and
> > classpath, about 20k compiled size overall.
> > TAMAYA-43: Removed Resource abstraction in favor of URL.
> >
> >
> > Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
> > Commit:
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/ae66299e
> > Tree:
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/ae66299e
> > Diff:
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/ae66299e
> >
> > Branch: refs/heads/master
> > Commit: ae66299e25b41167008021ffe95cad236f6e2bd3
> > Parents: 2dd0c13
> > Author: anatole <an...@apache.org>
> > Authored: Wed Jan 7 22:49:39 2015 +0100
> > Committer: anatole <an...@apache.org>
> > Committed: Sun Jan 11 01:40:57 2015 +0100
> >
> > ----------------------------------------------------------------------
> > .../tamaya/format/ConfigurationFormat.java      |  10 +-
> > .../apache/tamaya/format/PropertiesFormat.java  |  15 +-
> > .../tamaya/format/PropertiesXmlFormat.java      |  15 +-
> > ...AbstractPathBasedPropertySourceProvider.java |   7 +-
> > .../AbstractResourcePropertySourceProvider.java |  17 +-
> > .../org/apache/tamaya/resource/Resource.java    | 115 --------
> > .../tamaya/resource/ResourceResolver.java       |  25 +-
> > .../resource/internal/ClassPathResource.java    | 187 -------------
> > .../resource/internal/ClasspathCollector.java   | 264 +++++++++++++++++++
> > .../internal/DefaultResourceResolver.java       |  61 ++++-
> > .../tamaya/resource/internal/FileCollector.java | 157 +++++++++++
> > .../tamaya/resource/internal/FileResource.java  | 172 ------------
> > .../resource/internal/InputStreamResource.java  | 117 --------
> > .../tamaya/resource/internal/Locator.java       | 150 +++++++++++
> > .../tamaya/resource/internal/UrlResource.java   | 140 ----------
> > 15 files changed, 671 insertions(+), 781 deletions(-)
> > ----------------------------------------------------------------------
> >
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > index 4a1e06f..924fa7c 100644
> > ---
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > +++
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > @@ -21,9 +21,8 @@ package org.apache.tamaya.format;
> > import org.apache.tamaya.spi.PropertySource;
> >
> > import java.io.IOException;
> > -import java.io.InputStream;
> > +import java.net.URL;
> > import java.util.Collection;
> > -import java.util.function.Supplier;
> >
> > /**
> >   * Implementations current this class encapsulate the mechanism how to
> read a
> > @@ -44,12 +43,11 @@ public interface ConfigurationFormat {
> >       * ladder case multiple PropertySources can be returned, each one
> with its
> > own ordinal and the corresponding
> >       * entries.
> >       *
> > -     * @param sourceName name to be used for constructing a useful name
> for the
> > created
> > -     *                   {@link org.apache.tamaya.spi.PropertySource}
> > instances.
> > -     * @param streamSupplier   the resource represented by a supplier of
> > InputStream, not null
> > +     * @param url the url to read the configuration data from (could be
> a file,
> > a remote location, a classpath
> > +     *            resource or something else.
> >       * @return the corresponding {@link
> > org.apache.tamaya.spi.PropertySource} instances, never {@code null}.
> >       */
> > -    Collection<PropertySource> readConfiguration(String sourceName,
> > Supplier<InputStream> streamSupplier)
> > +    Collection<PropertySource> readConfiguration(URL url)
> >              throws IOException;
> >
> > }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > index 34c9e21..a49e492 100644
> > ---
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > +++
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > @@ -21,6 +21,7 @@ package org.apache.tamaya.format;
> > import org.apache.tamaya.spi.PropertySource;
> >
> > import java.io.InputStream;
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Collection;
> > import java.util.Collections;
> > @@ -28,7 +29,6 @@ import java.util.List;
> > import java.util.Map;
> > import java.util.Objects;
> > import java.util.Properties;
> > -import java.util.function.Supplier;
> > import java.util.logging.Level;
> > import java.util.logging.Logger;
> >
> > @@ -70,10 +70,15 @@ public class PropertiesFormat implements
> ConfigurationFormat
> > {
> >
> >      @SuppressWarnings("unchecked")
> >      @Override
> > -    public Collection<PropertySource> readConfiguration(String
> > sourceName, Supplier<InputStream> streamSupplier) {
> > -        final String name = "Properties(" +
> > Objects.requireNonNull(sourceName) + ')';
> > +    public Collection<PropertySource> readConfiguration(URL url) {
> > +        final String name;
> > +        if (Objects.requireNonNull(url).getQuery() == null) {
> > +            name = "Properties(" +
> > Objects.requireNonNull(url).toString() + ')';
> > +        } else {
> > +            name = Objects.requireNonNull(url).getQuery();
> > +        }
> >          List<PropertySource> propertySources = new ArrayList<>();
> > -        try (InputStream is = streamSupplier.get()) {
> > +        try (InputStream is = url.openStream()) {
> >              if (is != null) {
> >                  final Properties p = new Properties();
> >                  p.load(is);
> > @@ -101,7 +106,7 @@ public class PropertiesFormat implements
> ConfigurationFormat
> > {
> >                  return propertySources;
> >              }
> >          } catch (Exception e) {
> > -            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + sourceName);
> > +            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + url);
> >          }
> >          return Collections.emptyList();
> >      }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > index 8b3468b..ddfe723 100644
> > ---
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > +++
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > @@ -21,6 +21,7 @@ package org.apache.tamaya.format;
> > import org.apache.tamaya.spi.PropertySource;
> >
> > import java.io.InputStream;
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Collection;
> > import java.util.Collections;
> > @@ -28,7 +29,6 @@ import java.util.List;
> > import java.util.Map;
> > import java.util.Objects;
> > import java.util.Properties;
> > -import java.util.function.Supplier;
> > import java.util.logging.Level;
> > import java.util.logging.Logger;
> >
> > @@ -71,10 +71,15 @@ public class PropertiesXmlFormat implements
> > ConfigurationFormat {
> >
> >      @SuppressWarnings("unchecked")
> >      @Override
> > -    public Collection<PropertySource> readConfiguration(String source,
> > Supplier<InputStream> streamSupplier) {
> > -        final String name = "XML-Properties:" +
> > Objects.requireNonNull(source) + ')';
> > +    public Collection<PropertySource> readConfiguration(URL url) {
> > +        final String name;
> > +        if (Objects.requireNonNull(url).getQuery() == null) {
> > +            name = "XML-Properties(" +
> > Objects.requireNonNull(url).toString() + ')';
> > +        } else {
> > +            name = Objects.requireNonNull(url).getQuery();
> > +        }
> >          List<PropertySource> propertySources = new ArrayList<>();
> > -        try (InputStream is = streamSupplier.get()) {
> > +        try (InputStream is = url.openStream()) {
> >              if (is != null) {
> >                  final Properties p = new Properties();
> >                  p.loadFromXML(is);
> > @@ -102,7 +107,7 @@ public class PropertiesXmlFormat implements
> > ConfigurationFormat {
> >                  return propertySources;
> >              }
> >          } catch (Exception e) {
> > -            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + source);
> > +            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + url);
> >          }
> >          return Collections.emptyList();
> >      }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > index c4c5651..58acba3 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > @@ -23,6 +23,7 @@ import org.apache.tamaya.spi.PropertySource;
> > import org.apache.tamaya.spi.PropertySourceProvider;
> > import org.apache.tamaya.spi.ServiceContext;
> >
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > import java.util.Collection;
> > @@ -75,13 +76,13 @@ public abstract class
> > AbstractPathBasedPropertySourceProvider implements Propert
> >      public Collection<PropertySource> getPropertySources() {
> >          List<PropertySource> propertySources = new ArrayList<>();
> >          paths.forEach((path) -> {
> > -            for (Resource res :
> >
> ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path))
> > {
> > +            for (URL res :
> >
> ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path))
> > {
> >                  try {
> >                      for (ConfigurationFormat format : configFormats) {
> > -
> > propertySources.addAll(format.readConfiguration(sourceName, res));
> > +
> propertySources.addAll(format.readConfiguration(res));
> >                      }
> >                  } catch (Exception e) {
> > -                    LOG.log(Level.WARNING, "Failed to add resource based
> > config: " + res.getName(), e);
> > +                    LOG.log(Level.WARNING, "Failed to add resource based
> > config: " + res, e);
> >                  }
> >              }
> >          });
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > index 6edba5b..f1ec885 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > @@ -22,6 +22,7 @@ import org.apache.tamaya.format.ConfigurationFormat;
> > import org.apache.tamaya.spi.PropertySource;
> > import org.apache.tamaya.spi.PropertySourceProvider;
> >
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > import java.util.Collection;
> > @@ -39,25 +40,25 @@ public abstract class
> AbstractResourcePropertySourceProvider
> > implements Property
> >      /** The supported formats. */
> >      private List<ConfigurationFormat> formats = new ArrayList<>();
> >      /** The resource. */
> > -    private Resource resource;
> > +    private URL resource;
> >      /** The source name used for creating the PropertySource names. */
> >      private String sourceName;
> >
> >      /**
> >       * Creates a new instance.
> > -     * @param resource the {@link Resource}, not null.
> > +     * @param resource the {@link URL}, not null.
> >       * @param formats the supported formats, not empty.
> >       */
> > -    public AbstractResourcePropertySourceProvider(String sourceName,
> Resource
> > resource, ConfigurationFormat... formats) {
> > +    public AbstractResourcePropertySourceProvider(String sourceName, URL
> > resource, ConfigurationFormat... formats) {
> >          this(sourceName, resource, Arrays.asList(formats));
> >      }
> >
> >      /**
> >       * Creates a new instance.
> > -     * @param resource the {@link Resource}, not null.
> > +     * @param resource the {@link URL}, not null.
> >       * @param formats the supported formats, not empty.
> >       */
> > -    public AbstractResourcePropertySourceProvider(String sourceName,
> Resource
> > resource, List<ConfigurationFormat> formats) {
> > +    public AbstractResourcePropertySourceProvider(String sourceName, URL
> > resource, List<ConfigurationFormat> formats) {
> >          this.resource = Objects.requireNonNull(resource);
> >          this.sourceName = Objects.requireNonNull(sourceName);
> >          if(formats.size()==0){
> > @@ -72,7 +73,7 @@ public abstract class
> AbstractResourcePropertySourceProvider
> > implements Property
> >       *
> >       * @return the underlying resource, never null.
> >       */
> > -    public Resource getResource() {
> > +    public URL getResource() {
> >          return this.resource;
> >      }
> >
> > @@ -90,9 +91,9 @@ public abstract class
> AbstractResourcePropertySourceProvider
> > implements Property
> >          List<PropertySource> propertySources = new ArrayList<>();
> >          for (ConfigurationFormat format : formats) {
> >              try {
> > -
> propertySources.addAll(format.readConfiguration(sourceName,
> > resource));
> > +
> propertySources.addAll(format.readConfiguration(resource));
> >              } catch (Exception e) {
> > -                LOG.info(() -> "Format was not matching: " +
> > format + " for resource: " + resource.getName());
> > +                LOG.info(() -> "Format was not matching: " +
> > format + " for resource: " + resource);
> >              }
> >          }
> >          return propertySources;
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> > deleted file mode 100644
> > index 39e34e9..0000000
> > ---
> a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> > +++ /dev/null
> > @@ -1,115 +0,0 @@
> > -/*
> > - * 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.resource;
> > -
> > -import java.io.File;
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.util.Objects;
> > -import java.util.function.Supplier;
> > -
> > -/**
> > - * Interface for an abstract resource. The effective resource
> implementation
> > can be completely arbitrary.
> > - * By default files, classpath format and URLs are supported, but
> alternate
> > implementations are possible.
> > - *
> > - * @see #get()
> > - * @see #toURI()
> > - */
> > -public interface Resource extends Supplier<InputStream> {
> > -
> > -    /**
> > -     * Return whether this resource actually exists. Depending on the
> resource
> > this can delegate to
> > -     * {@link java.io.File#exists()} or whatever may be appropriate to
> > check accessibility of the resource.
> > -     */
> > -    default boolean exists() {
> > -        // Try to open a file first, if that fails try to open the
> stream...
> > -        try {
> > -            return new File(toURI()).exists();
> > -        } catch (IOException ex) {
> > -            // Fallback
> > -            try {
> > -                InputStream is = get();
> > -                is.close();
> > -                return true;
> > -            } catch (Exception e) {
> > -                // ignore, just return false for non existing
> > -                return false;
> > -            }
> > -        }
> > -    }
> > -
> > -    /**
> > -     * Checks whether the resource is accessible, meaning {@link #get()}
> > should return a InputStream for reading the
> > -     * resource's content.
> > -     *
> > -     * @see #get()
> > -     */
> > -    default boolean isAccessible() {
> > -        return true;
> > -    }
> > -
> > -    /**
> > -     * Returns the resource as an URI.
> > -     *
> > -     * @throws IOException if the resource cannot be resolved as URI.
> > -     */
> > -    URI toURI() throws IOException;
> > -
> > -    /**
> > -     * Determines the length for this resource.
> > -     *
> > -     * @throws IOException if the resource is not readable.
> > -     */
> > -    default long length() throws IOException {
> > -        try(InputStream is = this.get();) {
> > -            Objects.requireNonNull(is, "resource not available");
> > -            long length = 0;
> > -            byte[] buf = new byte[256];
> > -            int bytesRead;
> > -            while ((bytesRead = is.read(buf)) > 0) {
> > -                length += bytesRead;
> > -            }
> > -            return length;
> > -        }
> > -    }
> > -
> > -    /**
> > -     * Determine the last-modified timestamp for a resource, as UTC ms
> > timestamp
> > -     *
> > -     * @throws IOException if the resource is not accessible.
> > -     */
> > -    default long lastModified() throws IOException{
> > -        return new File(toURI()).lastModified();
> > -    }
> > -
> > -    /**
> > -     * Get a name for the resource. The name should be identifying the
> resource
> > and also
> > -     * never change, so it must be eligible for hashcode/equals
> > implementations.
> > -     */
> > -    default String getName() {
> > -        try {
> > -            return toURI().toString();
> > -        } catch (Exception e) {
> > -            return toString();
> > -        }
> > -    }
> > -
> > -
> > -}
> > \ No newline at end of file
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > index 7901ca6..31856cf 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > @@ -18,6 +18,7 @@
> >   */
> > package org.apache.tamaya.resource;
> >
> > +import java.net.URL;
> > import java.util.Arrays;
> > import java.util.Collection;
> >
> > @@ -28,16 +29,16 @@ import java.util.Collection;
> > public interface ResourceResolver {
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s.
> > Hereby
> > +     * Resolves resource expressions to a list of {@link URL}s. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    default Collection<Resource> getResources(Collection<String>
> > expressions) {
> > +    default Collection<URL> getResources(Collection<String>
> > expressions) {
> >          ClassLoader cl = Thread.currentThread().getContextClassLoader();
> >          if (cl == null) {
> >              cl = getClass().getClassLoader();
> > @@ -46,45 +47,45 @@ public interface ResourceResolver {
> >      }
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s.
> > Hereby
> > +     * Resolves resource expressions to a list of {@link URL}s. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    default Collection<Resource> getResources(String... expressions)
> > {
> > +    default Collection<URL> getResources(String... expressions) {
> >          return getResources(Arrays.asList(expressions));
> >      }
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s,
> > considerubg
> > +     * Resolves resource expressions to a list of {@link URL}s,
> > considerubg
> >       * the given classloader for classloader dependent format. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    default Collection<Resource> getResources(ClassLoader classLoader,
> > String... expressions){
> > +    default Collection<URL> getResources(ClassLoader classLoader,
> > String... expressions){
> >          return getResources(classLoader, Arrays.asList(expressions));
> >      }
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s,
> > considerubg
> > +     * Resolves resource expressions to a list of {@link URL}s,
> > considerubg
> >       * the given classloader for classloader dependent format. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    Collection<Resource> getResources(ClassLoader classLoader,
> > Collection<String> expressions);
> > +    Collection<URL> getResources(ClassLoader classLoader,
> > Collection<String> expressions);
> >
> > }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> > deleted file mode 100644
> > index b901164..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> > +++ /dev/null
> > @@ -1,187 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.net.URISyntaxException;
> > -import java.net.URL;
> > -import java.util.Objects;
> > -import java.util.logging.Level;
> > -import java.util.logging.Logger;
> > -
> > -/**
> > - * Implementation of {@link Resource} to be loaded from the classpath.
> > - */
> > -public class ClassPathResource implements Resource {
> > -
> > -    private static final Logger LOG =
> > Logger.getLogger(ClassPathResource.class.getName());
> > -
> > -    private final String path;
> > -
> > -    private ClassLoader classLoader;
> > -
> > -
> > -    /**
> > -     * Create a new resource using the current context class loader.
> > -     *
> > -     * @param path the resource path, not null
> > -     * @see java.lang.ClassLoader#getResourceAsStream(String)
> > -     */
> > -    public ClassPathResource(String path) {
> > -        this(path, (ClassLoader) null);
> > -    }
> > -
> > -    /**
> > -     * Create a new resource using the given class loader.
> > -     *
> > -     * @param path        the resource path, not null
> > -     * @param classLoader the class loader to load the resource with,
> > -     *                    or {@code null} for the current context class
> > loader
> > -     * @see ClassLoader#getResourceAsStream(String)
> > -     */
> > -    public ClassPathResource(String path, ClassLoader classLoader) {
> > -        Objects.requireNonNull(path, "Path null");
> > -        if (path.startsWith("/")) {
> > -            path = path.substring(1);
> > -        }
> > -        this.path = path.trim();
> > -        if (classLoader == null) {
> > -            classLoader =
> Thread.currentThread().getContextClassLoader();
> > -        }
> > -        if (classLoader == null) {
> > -            classLoader = getClass().getClassLoader();
> > -        }
> > -        this.classLoader = classLoader;
> > -    }
> > -
> > -    /**
> > -     * @return the path for this resource.
> > -     */
> > -    public final String getPath() {
> > -        return this.path;
> > -    }
> > -
> > -    /**
> > -     * @return the ClassLoader that this resource will be accessed from.
> > -     */
> > -    public final ClassLoader getClassLoader() {
> > -        return this.classLoader;
> > -    }
> > -
> > -
> > -    /**
> > -     * Checks if the given resource is resolvable from the configured
> > classloader.
> > -     *
> > -     * @see java.lang.ClassLoader#getResource(String)
> > -     */
> > -    @Override
> > -    public boolean exists() {
> > -        return (resolveURL() != null);
> > -    }
> > -
> > -    /**
> > -     * Resolves a URL for the underlying class path resource.
> > -     *
> > -     * @return the resolved URL, or {@code null}
> > -     */
> > -    protected URL resolveURL() {
> > -        return this.classLoader.getResource(this.path);
> > -    }
> > -
> > -    /**
> > -     * This implementation opens an InputStream for the given class path
> > resource.
> > -     *
> > -     * @see java.lang.ClassLoader#getResourceAsStream(String)
> > -     * @see java.lang.Class#getResourceAsStream(String)
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        try {
> > -            InputStream is =
> this.classLoader.getResourceAsStream(this.path);
> > -            if (is == null) {
> > -                throw new IOException(getName() + " does not exist");
> > -            }
> > -            return is;
> > -        } catch (IOException e) {
> > -            LOG.log(Level.INFO, "Failed to open classpath resource: "
> > + path, e);
> > -            return null;
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        try {
> > -            return resolveURL().toURI();
> > -        } catch (URISyntaxException e) {
> > -            throw new IOException(e);
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public long lastModified() throws IOException {
> > -        return 0;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the name current the file that this
> class
> > path
> > -     * resource refers to.
> > -     */
> > -    @Override
> > -    public String getName() {
> > -        return "classpath:" + path;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns a description that includes the
> class path
> > location.
> > -     */
> > -    @Override
> > -    public String toString() {
> > -        return "ClassPathResource[" + path + ']';
> > -    }
> > -
> > -    /**
> > -     * This implementation compares the underlying class path locations.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        if (obj == this) {
> > -            return true;
> > -        }
> > -        if (obj instanceof ClassPathResource) {
> > -            ClassPathResource otherRes = (ClassPathResource) obj;
> > -            return (this.path.equals(otherRes.path) &&
> > -                    Objects.equals(this.classLoader,
> otherRes.classLoader));
> > -        }
> > -        return false;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the hash code current the underlying
> > -     * class path location.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return getName().hashCode();
> > -    }
> > -
> > -}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> > new file mode 100644
> > index 0000000..3f2093b
> > --- /dev/null
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> > @@ -0,0 +1,264 @@
> > +/*
> > + * 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.resource.internal;
> > +
> > +import java.io.File;
> > +import java.io.IOException;
> > +import java.net.JarURLConnection;
> > +import java.net.MalformedURLException;
> > +import java.net.URISyntaxException;
> > +import java.net.URL;
> > +import java.net.URLConnection;
> > +import java.util.ArrayList;
> > +import java.util.Collection;
> > +import java.util.Enumeration;
> > +import java.util.List;
> > +import java.util.Objects;
> > +import java.util.jar.JarEntry;
> > +import java.util.jar.JarFile;
> > +import java.util.logging.Level;
> > +import java.util.logging.Logger;
> > +
> > +/**
> > + * Collector that searches files based on ant styled patterns. For
> example the
> > following patterns would be matched:
> > + * <pre>
> > + *     classpath:javax/annotations/*
> > + *     javax?/annotations/**/*.class
> > + *     org/apache/tamaya/**/tamayaconfig.properties
> > + * </pre>
> > + */
> > +public class ClasspathCollector {
> > +
> > +    /**
> > +     * JAR protocol.
> > +     */
> > +    public static final String PROTOCOL_JAR = "jar";
> > +
> > +    /**
> > +     * Separator between JAR file URL and the internal jar file path.
> > +     */
> > +    public static final String JAR_URL_SEPARATOR = "!/";
> > +
> > +    /**
> > +     * ZIP protocol.
> > +     */
> > +    public static final String PROTOCOL_ZIP = "zip";
> > +
> > +    /**
> > +     * ZIP protocol for a JBoss jar file entry: "vfszip".
> > +     */
> > +    public static final String PROTOCOL_VFSZIP = "vfszip";
> > +
> > +    /**
> > +     * URL protocol for an WebSphere jar file: "wsjar".
> > +     */
> > +    public static final String PROTOCOL_WSJAR = "wsjar";
> > +
> > +    /**
> > +     * URL protocol for an entry from an OC4J jar.
> > +     */
> > +    public static final String PROTOCOL_CODE_SOURCE = "code-source";
> > +
> > +    /**
> > +     * The logger used.
> > +     */
> > +    private static final Logger LOG =
> > Logger.getLogger(ClasspathCollector.class.getName());
> > +
> > +    /**
> > +     * The classloader used to load the resources.
> > +     */
> > +    private ClassLoader classLoader;
> > +
> > +    /**
> > +     * Creates a new instance.
> > +     *
> > +     * @param classLoader the class loader to be used, not null.
> > +     */
> > +    public ClasspathCollector(ClassLoader classLoader) {
> > +        this.classLoader = Objects.requireNonNull(classLoader);
> > +    }
> > +
> > +    /**
> > +     * Collect all classpath resources given the expression.
> > +     *
> > +     * @param expression the expression, not null.
> > +     * @return the resources found.
> > +     */
> > +    public Collection<URL> collectFiles(String expression) {
> > +        if (expression.startsWith("classpath:")) {
> > +            expression = expression.substring("classpath:".length());
> > +        }
> > +        if (expression.startsWith("/")) {
> > +            expression = expression.substring(1);
> > +        }
> > +        Locator locator = Locator.of(expression);
> > +        List<URL> result = new ArrayList<>();
> > +        String rootPath = locator.getRootPath();
> > +        try {
> > +            Enumeration<URL> rootResources =
> > this.classLoader.getResources(rootPath);
> > +            while (rootResources.hasMoreElements()) {
> > +                URL resource = rootResources.nextElement();
> > +                try {
> > +                    if (isJarFile(resource)) {
> > +
> result.addAll(doFindPathMatchingJarResources(resource,
> > locator.getSubPath()));
> > +                    } else {
> > +                        File file = getFile(resource);
> > +
> > result.addAll(FileCollector.traverseAndSelectFromChildren(file,
> > locator.getSubPathTokens(), 0));
> > +                    }
> > +                } catch (Exception e) {
> > +                    LOG.log(Level.SEVERE, "Error locating resources for:
> > " + expression, e);
> > +                }
> > +            }
> > +        } catch (IOException e) {
> > +            LOG.log(Level.SEVERE, "Error locating resources for: " +
> > expression, e);
> > +        }
> > +        return result;
> > +    }
> > +
> > +
> > +    /**
> > +     * Find all resources in jar files that match the given location
> pattern
> > +     * via the Ant-style PathMatcher.
> > +     *
> > +     * @param rootDirResource the root directory as Resource
> > +     * @param subPattern      the sub pattern to match (below the root
> > directory)
> > +     * @return the Set of matching Resource instances
> > +     * @throws java.io.IOException in case of I/O errors
> > +     * @see java.net.JarURLConnection
> > +     */
> > +    protected Collection<URL> doFindPathMatchingJarResources(URL
> > rootDirResource, String subPattern)
> > +            throws IOException, URISyntaxException {
> > +        subPattern = subPattern.replace("*",
> > ".*").replace("?", ".?").replace(".*.*",
> > ".*");
> > +        URLConnection con =
> rootDirResource.toURI().toURL().openConnection();
> > +        JarFile jarFile;
> > +        boolean newJarFile = false;
> > +        String jarFileUrl;
> > +        String rootEntryPath;
> > +
> > +        if (con instanceof JarURLConnection) {
> > +            // Should usually be the case for traditional JAR files.
> > +            JarURLConnection jarCon = (JarURLConnection) con;
> > +            jarCon.setUseCaches(false);
> > +            jarFile = jarCon.getJarFile();
> > +            jarFileUrl = jarCon.getJarFileURL().toExternalForm();
> > +            JarEntry jarEntry = jarCon.getJarEntry();
> > +            rootEntryPath = (jarEntry != null ? jarEntry.getName() :
> > "");
> > +        } else {
> > +            // No JarURLConnection -> need to resort to URL file
> parsing.
> > +            // We'll assume URLs of the format "jar:path!/entry",
> > with the protocol
> > +            // being arbitrary as long as following the entry format.
> > +            // We'll also handle paths with and without leading
> > "file:" prefix.
> > +            String urlFile = rootDirResource.toURI().toURL().getFile();
> > +            int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
> > +            jarFileUrl = urlFile.substring(0, separatorIndex);
> > +            if (jarFileUrl.startsWith("file:")) {
> > +                jarFileUrl = jarFileUrl.substring("file:".length());
> > +            }
> > +            jarFile = new JarFile(jarFileUrl);
> > +            newJarFile = true;
> > +            jarFileUrl = "file:" + jarFileUrl;
> > +            rootEntryPath = urlFile.substring(separatorIndex +
> > JAR_URL_SEPARATOR.length());
> > +        }
> > +
> > +        try {
> > +            if (LOG.isLoggable(Level.FINEST)) {
> > +                LOG.finest("Looking for matching resources in jar file
> > [" + jarFileUrl + "]");
> > +            }
> > +            if (!rootEntryPath.isEmpty() &&
> > !rootEntryPath.endsWith("/")) {
> > +                // Root entry path must end with slash for correct
> matching
> > +                rootEntryPath = rootEntryPath + '/';
> > +            }
> > +            Collection<URL> result = new ArrayList<>(10);
> > +            for (Enumeration entries = jarFile.entries();
> > entries.hasMoreElements(); ) {
> > +                JarEntry entry = (JarEntry) entries.nextElement();
> > +                String entryPath = entry.getName();
> > +                if (entryPath.startsWith(rootEntryPath)) {
> > +                    String relativePath =
> > entryPath.substring(rootEntryPath.length());
> > +                    if (relativePath.matches(subPattern)) {
> > +                        result.add(createRelativeFrom(rootDirResource,
> > relativePath));
> > +                    }
> > +                }
> > +            }
> > +            return result;
> > +        } finally {
> > +            // Close jar file, but only if freshly obtained -
> > +            // not from JarURLConnection, which might cache the file
> reference.
> > +            if (newJarFile) {
> > +                jarFile.close();
> > +            }
> > +        }
> > +    }
> > +
> > +    /**
> > +     * Creates a new URL based on the given root path and the relative
> path to
> > be added.
> > +     *
> > +     * @param url          the root, not null
> > +     * @param relativePath the relative path to be added, not null
> > +     * @return the new URL instance
> > +     * @throws MalformedURLException
> > +     */
> > +    private URL createRelativeFrom(URL url, String relativePath)
> > +            throws MalformedURLException {
> > +        String rootDirResource = url.toExternalForm();
> > +        if (relativePath.startsWith("/")) {
> > +            relativePath = relativePath.substring(1);
> > +        }
> > +        if (!rootDirResource.endsWith("/")) {
> > +            rootDirResource = rootDirResource + '/';
> > +        }
> > +        return new URL(rootDirResource + relativePath);
> > +    }
> > +
> > +
> > +    /**
> > +     * Small check if a given URL is a jar file URL.
> > +     *
> > +     * @param url the URL to check, not null.
> > +     * @return true if the URL has one of the following protocols: jar,
> zip,
> > vfszip, wsjar, code-source.
> > +     */
> > +    private boolean isJarFile(URL url) {
> > +        String protocol = Objects.requireNonNull(url).getProtocol();
> > +        return (PROTOCOL_JAR.equals(protocol) ||
> > +                PROTOCOL_ZIP.equals(protocol) ||
> > +                PROTOCOL_VFSZIP.equals(protocol) ||
> > +                PROTOCOL_WSJAR.equals(protocol) ||
> > +                (PROTOCOL_CODE_SOURCE.equals(protocol) &&
> > url.getPath().indexOf(JAR_URL_SEPARATOR) != -1));
> > +    }
> > +
> > +    /**
> > +     * Creates a file from an URL.
> > +     *
> > +     * @param resourceUrl the url, not null.
> > +     * @return a new file instance. The instance still may not exist.
> if the
> > url's protocol is not 'file', {@code null}
> > +     * is returned.
> > +     */
> > +    private File getFile(URL resourceUrl) {
> > +        Objects.requireNonNull(resourceUrl, "Resource URL must not be
> > null");
> > +        if (!"file".equals(resourceUrl.getProtocol())) {
> > +            return null;
> > +        }
> > +        try {
> > +            return new
> File(resourceUrl.toURI().getSchemeSpecificPart());
> > +        } catch (Exception ex) {
> > +            // Fallback for URLs that are not valid URIs (should hardly
> ever
> > happen).
> > +            return new File(resourceUrl.getFile());
> > +        }
> > +    }
> > +
> > +}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > index 9fd6fc4..c90e53a 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > @@ -18,7 +18,6 @@
> >   */
> > package org.apache.tamaya.resource.internal;
> >
> > -import org.apache.tamaya.resource.Resource;
> > import org.apache.tamaya.resource.ResourceResolver;
> >
> > import javax.annotation.Priority;
> > @@ -39,10 +38,10 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >      private static final Logger LOG =
> > Logger.getLogger(DefaultResourceResolver.class.getName());
> >
> >      @Override
> > -    public List<Resource> getResources(ClassLoader classLoader,
> > Collection<String> expressions) {
> > -        List<Resource> resources = new ArrayList<>();
> > +    public List<URL> getResources(ClassLoader classLoader,
> > Collection<String> expressions) {
> > +        List<URL> resources = new ArrayList<>();
> >          for (String expression : expressions) {
> > -            if (tryClassPath(classLoader, expression, resources) ||
> > tryFile(expression, resources) ||
> > +            if (tryPath(classLoader, expression, resources) ||
> > tryClassPath(classLoader, expression, resources) || tryFile(expression,
> > resources) ||
> >                      tryURL(expression, resources)) {
> >                  continue;
> >              }
> > @@ -51,12 +50,41 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >          return resources;
> >      }
> >
> > -    private boolean tryClassPath(ClassLoader classLoader, String
> expression,
> > List<Resource> resources) {
> > +    /**
> > +     * Tries to evaluate the location passed by Ant path matching.
> > +     * @param classLoader the class loader to use
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryPath(ClassLoader classLoader, String expression,
> > List<URL> resources) {
> > +        try {
> > +            // 1: try file path
> > +            Collection<URL> found =
> > FileCollector.collectFiles(expression);
> > +            if (found.isEmpty()) {
> > +                found = new
> > ClasspathCollector(classLoader).collectFiles(expression);
> > +            }
> > +            resources.addAll(found);
> > +            return !found.isEmpty();
> > +        } catch (Exception e) {
> > +            LOG.finest(() -> "Failed to load resource from CP: " +
> > expression);
> > +        }
> > +        return false;
> > +    }
> > +
> > +    /**
> > +     * Tries to evaluate the location passed by loading from the
> classloader.
> > +     * @param classLoader the class loader to use
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryClassPath(ClassLoader classLoader, String
> expression,
> > List<URL> resources) {
> >          try {
> >              Enumeration<URL> urls =
> classLoader.getResources(expression);
> >              while (urls.hasMoreElements()) {
> >                  URL url = urls.nextElement();
> > -                resources.add(new UrlResource(url));
> > +                resources.add(url);
> >              }
> >              return !resources.isEmpty();
> >          } catch (Exception e) {
> > @@ -65,11 +93,17 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >          return false;
> >      }
> >
> > -    private boolean tryFile(String expression, List<Resource> resources)
> > {
> > +    /**
> > +     * Tries to evaluate the location passed by lokking up a file.
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryFile(String expression, List<URL> resources)
> > {
> >          try {
> >              File file = new File(expression);
> >              if (file.exists()) {
> > -                resources.add(new FileResource(file));
> > +                resources.add(file.toURI().toURL());
> >                  return true;
> >              }
> >          } catch (Exception e) {
> > @@ -78,16 +112,21 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >          return false;
> >      }
> >
> > -    private boolean tryURL(String expression, List<Resource> resources)
> > {
> > +    /**
> > +     * Tries to interpret the expression as URL.
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryURL(String expression, List<URL> resources) {
> >          try {
> >              URL url = new URL(expression);
> > -            resources.add(new UrlResource(url));
> > +            resources.add(url);
> >              return true;
> >          } catch (Exception e) {
> >              LOG.finest(() -> "Failed to load resource from file: "
> > + expression);
> >          }
> >          return false;
> > -
> >      }
> >
> > }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> > new file mode 100644
> > index 0000000..d506e11
> > --- /dev/null
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> > @@ -0,0 +1,157 @@
> > +/*
> > + * 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.resource.internal;
> > +
> > +import java.io.File;
> > +import java.net.URL;
> > +import java.util.ArrayList;
> > +import java.util.Collection;
> > +import java.util.Collections;
> > +import java.util.List;
> > +import java.util.Objects;
> > +import java.util.logging.Logger;
> > +
> > +/**
> > + * Collector that searches files based on ant styled patterns. For
> example the
> > following patterns would be matched:
> > + * <pre>
> > + *     file:C:/temp/*.txt
> > + *     file:C:\**\*.ini
> > + *     C:\Programs\**/*.ini
> > + *     /user/home/A*b101_?.pid
> > + *     /var/logs/**/*.log
> > + * </pre>
> > + */
> > +public class FileCollector {
> > +
> > +    public static final String FILE_PREFIX = "file:";
> > +
> > +    private FileCollector() {
> > +    }
> > +
> > +    private static final Logger LOG =
> > Logger.getLogger(FileCollector.class.getName());
> > +
> > +    public static Collection<URL> collectFiles(String expression) {
> > +        expression = expression.replace("\\", "/");
> > +        Locator locator = Locator.of(expression);
> > +        List<URL> result = new ArrayList<>();
> > +        String rootPath = locator.getRootPath();
> > +        if (rootPath.startsWith(FILE_PREFIX)) {
> > +            rootPath = rootPath.substring(FILE_PREFIX.length());
> > +        }
> > +        File file = new File(rootPath);
> > +        if (file.exists()) {
> > +            List<String> subTokens = locator.getSubPathTokens();
> > +            result.addAll(traverseAndSelectFromChildren(file,
> subTokens, 0));
> > +        }
> > +        return result;
> > +    }
> > +
> > +    static Collection<URL> traverseAndSelectFromChildren(File dir,
> > List<String> subTokens, int tokenIndex) {
> > +        if (tokenIndex >= subTokens.size() || dir.isFile()) {
> > +            return Collections.emptyList();
> > +        }
> > +        List<URL> result = new ArrayList<>();
> > +        String token = subTokens.get(tokenIndex);
> > +        if (token.equals("**")) {
> > +            result.addAll(traverseAndSelectFromChildren(dir,
> > getSubExpression(subTokens, tokenIndex + 1)));
> > +        } else {
> > +            token = token.replace("*", ".*");
> > +            File[] files = dir.listFiles();
> > +            if (tokenIndex == subTokens.size() - 1) {
> > +                // select files!
> > +                for (File f : files) {
> > +                    if (f.isFile() && f.getName().matches(token))
> > {
> > +                        result.add(getURL(f));
> > +                    }
> > +                }
> > +            } else {
> > +                // check directory pattern
> > +                for (File f : files) {
> > +                    if (f.isDirectory() && f.getName().matches(token))
> > {
> > +                        result.addAll(traverseAndSelectFromChildren(f,
> > subTokens, tokenIndex + 1));
> > +                    }
> > +                }
> > +            }
> > +        }
> > +        return result;
> > +    }
> > +
> > +    static Collection<URL> traverseAndSelectFromChildren(File file,
> > String subExpression) {
> > +        List<URL> result = new ArrayList<>();
> > +        for (File childFile : file.listFiles()) {
> > +            if (childFile.isFile()) {
> > +                if (childFile.getName().matches(subExpression)) {
> > +                    try {
> > +                        result.add(getURL(childFile));
> > +                    } catch (Exception e) {
> > +                        LOG.warning(() -> "File not convertible to URL:
> > " + childFile);
> > +                    }
> > +                }
> > +            } else if (childFile.isDirectory()) {
> > +                result.addAll(traverseAndSelectFromChildren(childFile,
> > subExpression));
> > +            }
> > +        }
> > +        return result;
> > +    }
> > +
> > +    private static boolean matchesFile(File childFile, List<String>
> > subTokens, int tokenIndex) {
> > +        if (tokenIndex < (subTokens.size() - 1)) {
> > +            // not all tokens consumed, so no match!
> > +            return false;
> > +        }
> > +        String tokenToMatch = subTokens.get(tokenIndex);
> > +        tokenToMatch = tokenToMatch.replace("*", ".*");
> > +        return childFile.getName().matches(tokenToMatch);
> > +    }
> > +
> > +    /**
> > +     * Get an URL from a file.
> > +     *
> > +     * @param file the file, not null.
> > +     * @return the URL, never null.
> > +     * @throws java.lang.IllegalStateException if it fails to create
> the URL
> > +     */
> > +    private static URL getURL(File file) {
> > +        Objects.requireNonNull(file);
> > +        try {
> > +            return file.toURI().toURL();
> > +        } catch (Exception e) {
> > +            throw new IllegalStateException("Failed to create URL from
> > file: " + file);
> > +        }
> > +    }
> > +
> > +    /**
> > +     * Constructs a sub expression, using the tokens from {@code
> > subTokens} starting at index {@code startIndex}.
> > +     *
> > +     * @param subTokens  the token list, not null
> > +     * @param startIndex the start index from where tokens should be
> taken to
> > produce the path.
> > +     * @return the constructed path, never null.
> > +     */
> > +    private static String getSubExpression(List<String> subTokens, int
> > startIndex) {
> > +        StringBuilder b = new StringBuilder();
> > +        for (int i = startIndex; i < subTokens.size(); i++) {
> > +            b.append(subTokens.get(i));
> > +            b.append('/');
> > +        }
> > +        if (b.length() > 0) {
> > +            b.setLength(b.length() - 1);
> > +        }
> > +        return b.toString().replaceAll("\\*",
> > ".*").replaceAll("\\?", ".?");
> > +    }
> > +}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> > deleted file mode 100644
> > index c5f521a..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> > +++ /dev/null
> > @@ -1,172 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -import java.io.File;
> > -import java.io.FileInputStream;
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.util.Objects;
> > -import java.util.logging.Level;
> > -import java.util.logging.Logger;
> > -
> > -/**
> > - * Implementation of {@link Resource} to be loaded from a file.
> > - *
> > - * @see java.io.File
> > - */
> > -public class FileResource implements Resource {
> > -
> > -    private static final Logger LOG =
> > Logger.getLogger(FileResource.class.getName());
> > -
> > -    private final File file;
> > -
> > -    /**
> > -     * Creates a new instance.
> > -     *
> > -     * @param file a File, not null.
> > -     */
> > -    public FileResource(File file) {
> > -        this.file = Objects.requireNonNull(file, "File must not be
> > null");
> > -    }
> > -
> > -    /**
> > -     * Crreates a new instance.
> > -     *
> > -     * @param filePath a file path
> > -     */
> > -    public FileResource(String filePath) {
> > -        Objects.requireNonNull(filePath, "Path must not be null");
> > -        this.file = new File(filePath);
> > -    }
> > -
> > -
> > -    /**
> > -     * Get the file path for this resource.
> > -     */
> > -    public final String getPath() {
> > -        return this.file.getPath();
> > -    }
> > -
> > -
> > -    /**
> > -     * This implementation returns whether the underlying file exists.
> > -     *
> > -     * @see java.io.File#exists()
> > -     */
> > -    @Override
> > -    public boolean exists() {
> > -        return this.file.exists();
> > -    }
> > -
> > -    /**
> > -     * This implementation checks whether the underlying file is marked
> as
> > readable
> > -     * (and corresponds to an actual file with content, not to a
> directory).
> > -     *
> > -     * @see java.io.File#canRead()
> > -     * @see java.io.File#isDirectory()
> > -     */
> > -    @Override
> > -    public boolean isAccessible() {
> > -        return (this.file.canRead() && !this.file.isDirectory());
> > -    }
> > -
> > -    /**
> > -     * This implementation opens a FileInputStream for the underlying
> file.
> > -     *
> > -     * @see java.io.FileInputStream
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        try {
> > -            return new FileInputStream(this.file);
> > -        } catch (Exception e) {
> > -            LOG.log(Level.INFO, "Failed to open file: " +
> > file.getAbsolutePath(), e);
> > -            return null;
> > -        }
> > -    }
> > -
> > -    /**
> > -     * This implementation returns a URI for the underlying file.
> > -     *
> > -     * @see java.io.File#toURI()
> > -     */
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        return this.file.toURI();
> > -    }
> > -
> > -    /**
> > -     * Returns the underlying File's length.
> > -     */
> > -    @Override
> > -    public long length() throws IOException {
> > -        return this.file.length();
> > -    }
> > -
> > -    @Override
> > -    public long lastModified() throws IOException {
> > -        return file.lastModified();
> > -    }
> > -
> > -    /**
> > -     * Returns the name of the current file.
> > -     *
> > -     * @see java.io.File#getName()
> > -     */
> > -    @Override
> > -    public String getName() {
> > -        return this.file.getName();
> > -    }
> > -
> > -    /**
> > -     * Returns a description that includes the absolute
> > -     * path of the current file.
> > -     *
> > -     * @see java.io.File#getAbsolutePath()
> > -     */
> > -    @Override
> > -    public String toString() {
> > -        return "File [" + this.file.getAbsolutePath() +
> > "]";
> > -    }
> > -
> > -
> > -    // implementation current WritableResource
> > -
> > -    /**
> > -     * Compares the underlying Files.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        return (obj == this ||
> > -                (obj instanceof FileResource &&
> > this.file.equals(((FileResource) obj).file)));
> > -    }
> > -
> > -    /**
> > -     * Returns hash code current the underlying File reference.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return this.file.hashCode();
> > -    }
> > -
> > -}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> > deleted file mode 100644
> > index d4aa673..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> > +++ /dev/null
> > @@ -1,117 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.util.Objects;
> > -
> > -/**
> > - * Simple Resource encapsulating an InputStream.
> > - */
> > -public class InputStreamResource implements Resource {
> > -
> > -    /** The InputStream. */
> > -    private final InputStream inputStream;
> > -    /** The read flag. */
> > -    private boolean read = false;
> > -    /** The name of the resource. */
> > -    private String name;
> > -
> > -
> > -    /**
> > -     * Create a new InputStreamResource.
> > -     *
> > -     * @param inputStream the InputStream to use
> > -     */
> > -    public InputStreamResource(InputStream inputStream) {
> > -        this(inputStream, "InputStream:");
> > -    }
> > -
> > -    /**
> > -     * Create a new InputStreamResource.
> > -     *
> > -     * @param inputStream the InputStream to use
> > -     * @param name where the InputStream comes from
> > -     */
> > -    public InputStreamResource(InputStream inputStream, String name) {
> > -        this.inputStream = Objects.requireNonNull(inputStream);
> > -        this.name = (name != null ? name : "InputStream");
> > -    }
> > -
> > -
> > -    /**
> > -     * This implementation always returns {@code true}.
> > -     */
> > -    @Override
> > -    public boolean exists() {
> > -        return true;
> > -    }
> > -
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        throw new IOException("URI not available.");
> > -    }
> > -
> > -    @Override
> > -    public long lastModified() throws IOException {
> > -        throw new IOException("lastModified not available.");
> > -    }
> > -
> > -    /**
> > -     * Accesses the input stream. Hereby the input stream can only
> accessed
> > once.
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        if (this.read) {
> > -            throw new IllegalStateException("InputStream can only be
> read
> > once!");
> > -        }
> > -        this.read = true;
> > -        return this.inputStream;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the passed-in description, if any.
> > -     */
> > -    public String toString() {
> > -        return this.name != null ? this.name : super.toString();
> > -    }
> > -
> > -
> > -    /**
> > -     * Compares the underlying InputStream.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        return (obj == this ||
> > -                (obj instanceof InputStreamResource &&
> > ((InputStreamResource) obj).inputStream.equals(this.inputStream)));
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the hash code current the underlying
> > InputStream.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return this.inputStream.hashCode();
> > -    }
> > -
> > -}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> > new file mode 100644
> > index 0000000..8d9e08a
> > --- /dev/null
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> > @@ -0,0 +1,150 @@
> > +/*
> > + * 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.resource.internal;
> > +
> > +import java.util.ArrayList;
> > +import java.util.Arrays;
> > +import java.util.List;
> > +import java.util.stream.Collectors;
> > +
> > +/**
> > + * Small helper class that manages the path parts of a location
> expression.
> > + */
> > +final class Locator {
> > +    /**
> > +     * The tokenized location expression.
> > +     */
> > +    private List<String> tokens;
> > +
> > +    /**
> > +     * Creates a new instances based on the tokenized expression.
> > +     *
> > +     * @param tokens the tokenized expression, not null.
> > +     */
> > +    Locator(List<String> tokens) {
> > +        this.tokens = tokens;
> > +    }
> > +
> > +    /**
> > +     * Creates a new instance of the corresponding expression.
> > +     *
> > +     * @param expression the location expression, not null.
> > +     * @return the tokenized instance.
> > +     */
> > +    public static Locator of(String expression) {
> > +        return new
> > Locator(Arrays.asList(expression.split("/")).stream().filter((s) ->
> > !s.isEmpty()).collect(Collectors.toList()));
> > +    }
> > +
> > +    /**
> > +     * Access the root path, which is the location expression, before
> any
> > wildcards or placeholders are used.
> > +     * It is used as the entry point into the file system or for
> accessing base
> > classpath resources, before
> > +     * further analysis on the file or jar filesystem can be performed.
> > +     *
> > +     * @return the root path, never null.
> > +     */
> > +    public String getRootPath() {
> > +        StringBuilder builder = new StringBuilder();
> > +        for (String token : tokens) {
> > +            if (containsPlaceholder(token)) {
> > +                break;
> > +            } else {
> > +                builder.append(token);
> > +                builder.append('/');
> > +            }
> > +        }
> > +        if (builder.length() > 0) {
> > +            builder.setLength(builder.length() - 1);
> > +        }
> > +        return builder.toString();
> > +    }
> > +
> > +    /**
> > +     * Return the sub expression path, which contains the second part
> of the
> > expression, starting with a placeholder
> > +     * or wildcard token.
> > +     *
> > +     * @return the sub expression part, never null.
> > +     */
> > +    public String getSubPath() {
> > +        StringBuilder builder = new StringBuilder();
> > +        for (String token : getSubPathTokens()) {
> > +            builder.append(token);
> > +            builder.append('/');
> > +        }
> > +        if (builder.length() > 0) {
> > +            builder.setLength(builder.length() - 1);
> > +        }
> > +        return builder.toString();
> > +    }
> > +
> > +    /**
> > +     * This method returns the single tokenized form of the sub
> expression.
> > +     *
> > +     * @return the tokenized version of the sub path.
> > +     * @see #getSubPath()
> > +     */
> > +    public List<String> getSubPathTokens() {
> > +        List<String> subTokens = new ArrayList<>();
> > +        for (String token : tokens) {
> > +            if (!containsPlaceholder(token)) {
> > +                continue;
> > +            } else {
> > +                subTokens.add(token);
> > +            }
> > +        }
> > +        return subTokens;
> > +    }
> > +
> > +    /**
> > +     * Access the full reconstructed path. In most cases this should
> match the
> > original expression.
> > +     *
> > +     * @return the full expression path, never null.
> > +     */
> > +    public String getPath() {
> > +        StringBuilder builder = new StringBuilder();
> > +        for (String token : tokens) {
> > +            builder.append(token);
> > +            builder.append('/');
> > +        }
> > +        if (builder.length() > 0) {
> > +            builder.setLength(builder.length() - 1);
> > +        }
> > +        return builder.toString();
> > +    }
> > +
> > +    /**
> > +     * Short method that checks for '*' and '?' chars.
> > +     *
> > +     * @param token the token to check, not null
> > +     * @return true, if it contains wildcard characters.
> > +     */
> > +    private boolean containsPlaceholder(String token) {
> > +        return token.contains("*") || token.contains("?");
> > +    }
> > +
> > +    /**
> > +     * Return the expressions' path.
> > +     *
> > +     * @return the locator path.
> > +     */
> > +    @Override
> > +    public String toString() {
> > +        return "Locator: " + getPath();
> > +    }
> > +
> > +}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> > deleted file mode 100644
> > index 6522cf5..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> > +++ /dev/null
> > @@ -1,140 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -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;
> > -import java.util.logging.Level;
> > -import java.util.logging.Logger;
> > -
> > -/**
> > - * Implementation of a resource based on a {@code java.net.URL}.
> > - */
> > -public class UrlResource implements Resource {
> > -
> > -    private static final Logger LOG =
> > Logger.getLogger(UrlResource.class.getName());
> > -
> > -    /**
> > -     * Original URL, used for actual access.
> > -     */
> > -    private final URL url;
> > -
> > -    /**
> > -     * Create a new instance based on the given URL.
> > -     *
> > -     * @param url a URL
> > -     */
> > -    public UrlResource(URL url) {
> > -        this.url = Objects.requireNonNull(url, "URL null");
> > -    }
> > -
> > -    /**
> > -     * Create a new URLResource based on a URL path.
> > -     *
> > -     * @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.url = new URL(path);
> > -    }
> > -
> > -
> > -    /**
> > -     * This implementation opens an InputStream for the given URL.
> > -     *
> > -     * @see java.net.URL#openConnection()
> > -     * @see java.net.URLConnection#setUseCaches(boolean)
> > -     * @see java.net.URLConnection#getInputStream()
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        URLConnection con = null;
> > -        try {
> > -            con = this.url.openConnection();
> > -            useCachesIfNecessary(con);
> > -            return con.getInputStream();
> > -        } catch (IOException e) {
> > -            if (con instanceof HttpURLConnection) {
> > -                ((HttpURLConnection) con).disconnect();
> > -            }
> > -            LOG.log(Level.INFO, "Failed to open URL: " + url, e);
> > -            return null;
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        try {
> > -            return this.url.toURI();
> > -        } catch (URISyntaxException e) {
> > -            throw new IOException("Failed to create URI from " +
> > url);
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public String getName() {
> > -        return this.url.toString();
> > -    }
> > -
> > -    @Override
> > -    public String toString() {
> > -        return "URL [" + this.url + "]";
> > -    }
> > -
> > -    /**
> > -     * Compares the underlying URL references.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        return (obj == this ||
> > -                (obj instanceof UrlResource &&
> > this.url.equals(((UrlResource) obj).url)));
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the hash code current the underlying
> URL
> > reference.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return this.url.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 format.
> > -     *
> > -     * @param con the URLConnection to set the flag on
> > -     */
> > -    private void useCachesIfNecessary(URLConnection con) {
> > -
> > con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
> > -    }
> > -
> > -}
> > -
> >
>



-- 
*Anatole Tresch*
Java Engineer & Architect, JSR Spec Lead
Glärnischweg 10
CH - 8620 Wetzikon

*Switzerland, Europe Zurich, GMT+1*
*Twitter:  @atsticks*
*Blogs: **http://javaremarkables.blogspot.ch/
<http://javaremarkables.blogspot.ch/>*

*Google: atsticksMobile  +41-76 344 62 79*

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Why not starting to use vfs for this part?
Le 11 janv. 2015 11:18, "Mark Struberg" <st...@yahoo.de> a écrit :

> Anatole, again:
>
>
> > PROTOCOL_WSJAR
>
>
> All this does NOT work portably!
> Many people tried that many times and it simply does NOT work that easily!
> The solution I know to work (xban-finder) explicitly has exit points to
> extend archive handlers. And it is about 200kByte of size alltogether.
>
>
> The problem with such a solution is that we must support it perfectly
> well, or not at all...
>
> What we *could* support is a _very_ easy solution with a prefix
>
> classpath-config:mydir/myconfig.properties
> vs a real URL e.g. file://
>
> In the first case we would simply use ClassLoader.getResources and
> register 0..n ConfigSources, in the second case we register exactly the one
> URL we got handed over as parameter.
>
> Also note that any wildcard style in an URL or classpath resource is NOT
> widely supported. Some ClassLoaders can handle it in SOME situations, but
> most of them don't.
>
> LieGrue,
> strub
>
>
>
>
>
> > On Sunday, 11 January 2015, 1:44, "anatole@apache.org" <
> anatole@apache.org> wrote:
> > > Repository: incubator-tamaya
> > Updated Branches:
> >   refs/heads/master 2dd0c13e5 -> c48c5794e
> >
> >
> > TAMAYA-43: Implemented ant pattern based resource lookup for files and
> > classpath, about 20k compiled size overall.
> > TAMAYA-43: Removed Resource abstraction in favor of URL.
> >
> >
> > Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
> > Commit:
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/ae66299e
> > Tree:
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/ae66299e
> > Diff:
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/ae66299e
> >
> > Branch: refs/heads/master
> > Commit: ae66299e25b41167008021ffe95cad236f6e2bd3
> > Parents: 2dd0c13
> > Author: anatole <an...@apache.org>
> > Authored: Wed Jan 7 22:49:39 2015 +0100
> > Committer: anatole <an...@apache.org>
> > Committed: Sun Jan 11 01:40:57 2015 +0100
> >
> > ----------------------------------------------------------------------
> > .../tamaya/format/ConfigurationFormat.java      |  10 +-
> > .../apache/tamaya/format/PropertiesFormat.java  |  15 +-
> > .../tamaya/format/PropertiesXmlFormat.java      |  15 +-
> > ...AbstractPathBasedPropertySourceProvider.java |   7 +-
> > .../AbstractResourcePropertySourceProvider.java |  17 +-
> > .../org/apache/tamaya/resource/Resource.java    | 115 --------
> > .../tamaya/resource/ResourceResolver.java       |  25 +-
> > .../resource/internal/ClassPathResource.java    | 187 -------------
> > .../resource/internal/ClasspathCollector.java   | 264 +++++++++++++++++++
> > .../internal/DefaultResourceResolver.java       |  61 ++++-
> > .../tamaya/resource/internal/FileCollector.java | 157 +++++++++++
> > .../tamaya/resource/internal/FileResource.java  | 172 ------------
> > .../resource/internal/InputStreamResource.java  | 117 --------
> > .../tamaya/resource/internal/Locator.java       | 150 +++++++++++
> > .../tamaya/resource/internal/UrlResource.java   | 140 ----------
> > 15 files changed, 671 insertions(+), 781 deletions(-)
> > ----------------------------------------------------------------------
> >
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > index 4a1e06f..924fa7c 100644
> > ---
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > +++
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> > @@ -21,9 +21,8 @@ package org.apache.tamaya.format;
> > import org.apache.tamaya.spi.PropertySource;
> >
> > import java.io.IOException;
> > -import java.io.InputStream;
> > +import java.net.URL;
> > import java.util.Collection;
> > -import java.util.function.Supplier;
> >
> > /**
> >   * Implementations current this class encapsulate the mechanism how to
> read a
> > @@ -44,12 +43,11 @@ public interface ConfigurationFormat {
> >       * ladder case multiple PropertySources can be returned, each one
> with its
> > own ordinal and the corresponding
> >       * entries.
> >       *
> > -     * @param sourceName name to be used for constructing a useful name
> for the
> > created
> > -     *                   {@link org.apache.tamaya.spi.PropertySource}
> > instances.
> > -     * @param streamSupplier   the resource represented by a supplier of
> > InputStream, not null
> > +     * @param url the url to read the configuration data from (could be
> a file,
> > a remote location, a classpath
> > +     *            resource or something else.
> >       * @return the corresponding {@link
> > org.apache.tamaya.spi.PropertySource} instances, never {@code null}.
> >       */
> > -    Collection<PropertySource> readConfiguration(String sourceName,
> > Supplier<InputStream> streamSupplier)
> > +    Collection<PropertySource> readConfiguration(URL url)
> >              throws IOException;
> >
> > }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > index 34c9e21..a49e492 100644
> > ---
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > +++
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> > @@ -21,6 +21,7 @@ package org.apache.tamaya.format;
> > import org.apache.tamaya.spi.PropertySource;
> >
> > import java.io.InputStream;
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Collection;
> > import java.util.Collections;
> > @@ -28,7 +29,6 @@ import java.util.List;
> > import java.util.Map;
> > import java.util.Objects;
> > import java.util.Properties;
> > -import java.util.function.Supplier;
> > import java.util.logging.Level;
> > import java.util.logging.Logger;
> >
> > @@ -70,10 +70,15 @@ public class PropertiesFormat implements
> ConfigurationFormat
> > {
> >
> >      @SuppressWarnings("unchecked")
> >      @Override
> > -    public Collection<PropertySource> readConfiguration(String
> > sourceName, Supplier<InputStream> streamSupplier) {
> > -        final String name = "Properties(" +
> > Objects.requireNonNull(sourceName) + ')';
> > +    public Collection<PropertySource> readConfiguration(URL url) {
> > +        final String name;
> > +        if (Objects.requireNonNull(url).getQuery() == null) {
> > +            name = "Properties(" +
> > Objects.requireNonNull(url).toString() + ')';
> > +        } else {
> > +            name = Objects.requireNonNull(url).getQuery();
> > +        }
> >          List<PropertySource> propertySources = new ArrayList<>();
> > -        try (InputStream is = streamSupplier.get()) {
> > +        try (InputStream is = url.openStream()) {
> >              if (is != null) {
> >                  final Properties p = new Properties();
> >                  p.load(is);
> > @@ -101,7 +106,7 @@ public class PropertiesFormat implements
> ConfigurationFormat
> > {
> >                  return propertySources;
> >              }
> >          } catch (Exception e) {
> > -            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + sourceName);
> > +            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + url);
> >          }
> >          return Collections.emptyList();
> >      }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > index 8b3468b..ddfe723 100644
> > ---
> >
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > +++
> >
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> > @@ -21,6 +21,7 @@ package org.apache.tamaya.format;
> > import org.apache.tamaya.spi.PropertySource;
> >
> > import java.io.InputStream;
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Collection;
> > import java.util.Collections;
> > @@ -28,7 +29,6 @@ import java.util.List;
> > import java.util.Map;
> > import java.util.Objects;
> > import java.util.Properties;
> > -import java.util.function.Supplier;
> > import java.util.logging.Level;
> > import java.util.logging.Logger;
> >
> > @@ -71,10 +71,15 @@ public class PropertiesXmlFormat implements
> > ConfigurationFormat {
> >
> >      @SuppressWarnings("unchecked")
> >      @Override
> > -    public Collection<PropertySource> readConfiguration(String source,
> > Supplier<InputStream> streamSupplier) {
> > -        final String name = "XML-Properties:" +
> > Objects.requireNonNull(source) + ')';
> > +    public Collection<PropertySource> readConfiguration(URL url) {
> > +        final String name;
> > +        if (Objects.requireNonNull(url).getQuery() == null) {
> > +            name = "XML-Properties(" +
> > Objects.requireNonNull(url).toString() + ')';
> > +        } else {
> > +            name = Objects.requireNonNull(url).getQuery();
> > +        }
> >          List<PropertySource> propertySources = new ArrayList<>();
> > -        try (InputStream is = streamSupplier.get()) {
> > +        try (InputStream is = url.openStream()) {
> >              if (is != null) {
> >                  final Properties p = new Properties();
> >                  p.loadFromXML(is);
> > @@ -102,7 +107,7 @@ public class PropertiesXmlFormat implements
> > ConfigurationFormat {
> >                  return propertySources;
> >              }
> >          } catch (Exception e) {
> > -            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + source);
> > +            LOG.log(Level.FINEST, e, () -> "Failed to read config from
> > resource: " + url);
> >          }
> >          return Collections.emptyList();
> >      }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > index c4c5651..58acba3 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> > @@ -23,6 +23,7 @@ import org.apache.tamaya.spi.PropertySource;
> > import org.apache.tamaya.spi.PropertySourceProvider;
> > import org.apache.tamaya.spi.ServiceContext;
> >
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > import java.util.Collection;
> > @@ -75,13 +76,13 @@ public abstract class
> > AbstractPathBasedPropertySourceProvider implements Propert
> >      public Collection<PropertySource> getPropertySources() {
> >          List<PropertySource> propertySources = new ArrayList<>();
> >          paths.forEach((path) -> {
> > -            for (Resource res :
> >
> ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path))
> > {
> > +            for (URL res :
> >
> ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path))
> > {
> >                  try {
> >                      for (ConfigurationFormat format : configFormats) {
> > -
> > propertySources.addAll(format.readConfiguration(sourceName, res));
> > +
> propertySources.addAll(format.readConfiguration(res));
> >                      }
> >                  } catch (Exception e) {
> > -                    LOG.log(Level.WARNING, "Failed to add resource based
> > config: " + res.getName(), e);
> > +                    LOG.log(Level.WARNING, "Failed to add resource based
> > config: " + res, e);
> >                  }
> >              }
> >          });
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > index 6edba5b..f1ec885 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> > @@ -22,6 +22,7 @@ import org.apache.tamaya.format.ConfigurationFormat;
> > import org.apache.tamaya.spi.PropertySource;
> > import org.apache.tamaya.spi.PropertySourceProvider;
> >
> > +import java.net.URL;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > import java.util.Collection;
> > @@ -39,25 +40,25 @@ public abstract class
> AbstractResourcePropertySourceProvider
> > implements Property
> >      /** The supported formats. */
> >      private List<ConfigurationFormat> formats = new ArrayList<>();
> >      /** The resource. */
> > -    private Resource resource;
> > +    private URL resource;
> >      /** The source name used for creating the PropertySource names. */
> >      private String sourceName;
> >
> >      /**
> >       * Creates a new instance.
> > -     * @param resource the {@link Resource}, not null.
> > +     * @param resource the {@link URL}, not null.
> >       * @param formats the supported formats, not empty.
> >       */
> > -    public AbstractResourcePropertySourceProvider(String sourceName,
> Resource
> > resource, ConfigurationFormat... formats) {
> > +    public AbstractResourcePropertySourceProvider(String sourceName, URL
> > resource, ConfigurationFormat... formats) {
> >          this(sourceName, resource, Arrays.asList(formats));
> >      }
> >
> >      /**
> >       * Creates a new instance.
> > -     * @param resource the {@link Resource}, not null.
> > +     * @param resource the {@link URL}, not null.
> >       * @param formats the supported formats, not empty.
> >       */
> > -    public AbstractResourcePropertySourceProvider(String sourceName,
> Resource
> > resource, List<ConfigurationFormat> formats) {
> > +    public AbstractResourcePropertySourceProvider(String sourceName, URL
> > resource, List<ConfigurationFormat> formats) {
> >          this.resource = Objects.requireNonNull(resource);
> >          this.sourceName = Objects.requireNonNull(sourceName);
> >          if(formats.size()==0){
> > @@ -72,7 +73,7 @@ public abstract class
> AbstractResourcePropertySourceProvider
> > implements Property
> >       *
> >       * @return the underlying resource, never null.
> >       */
> > -    public Resource getResource() {
> > +    public URL getResource() {
> >          return this.resource;
> >      }
> >
> > @@ -90,9 +91,9 @@ public abstract class
> AbstractResourcePropertySourceProvider
> > implements Property
> >          List<PropertySource> propertySources = new ArrayList<>();
> >          for (ConfigurationFormat format : formats) {
> >              try {
> > -
> propertySources.addAll(format.readConfiguration(sourceName,
> > resource));
> > +
> propertySources.addAll(format.readConfiguration(resource));
> >              } catch (Exception e) {
> > -                LOG.info(() -> "Format was not matching: " +
> > format + " for resource: " + resource.getName());
> > +                LOG.info(() -> "Format was not matching: " +
> > format + " for resource: " + resource);
> >              }
> >          }
> >          return propertySources;
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> > deleted file mode 100644
> > index 39e34e9..0000000
> > ---
> a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> > +++ /dev/null
> > @@ -1,115 +0,0 @@
> > -/*
> > - * 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.resource;
> > -
> > -import java.io.File;
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.util.Objects;
> > -import java.util.function.Supplier;
> > -
> > -/**
> > - * Interface for an abstract resource. The effective resource
> implementation
> > can be completely arbitrary.
> > - * By default files, classpath format and URLs are supported, but
> alternate
> > implementations are possible.
> > - *
> > - * @see #get()
> > - * @see #toURI()
> > - */
> > -public interface Resource extends Supplier<InputStream> {
> > -
> > -    /**
> > -     * Return whether this resource actually exists. Depending on the
> resource
> > this can delegate to
> > -     * {@link java.io.File#exists()} or whatever may be appropriate to
> > check accessibility of the resource.
> > -     */
> > -    default boolean exists() {
> > -        // Try to open a file first, if that fails try to open the
> stream...
> > -        try {
> > -            return new File(toURI()).exists();
> > -        } catch (IOException ex) {
> > -            // Fallback
> > -            try {
> > -                InputStream is = get();
> > -                is.close();
> > -                return true;
> > -            } catch (Exception e) {
> > -                // ignore, just return false for non existing
> > -                return false;
> > -            }
> > -        }
> > -    }
> > -
> > -    /**
> > -     * Checks whether the resource is accessible, meaning {@link #get()}
> > should return a InputStream for reading the
> > -     * resource's content.
> > -     *
> > -     * @see #get()
> > -     */
> > -    default boolean isAccessible() {
> > -        return true;
> > -    }
> > -
> > -    /**
> > -     * Returns the resource as an URI.
> > -     *
> > -     * @throws IOException if the resource cannot be resolved as URI.
> > -     */
> > -    URI toURI() throws IOException;
> > -
> > -    /**
> > -     * Determines the length for this resource.
> > -     *
> > -     * @throws IOException if the resource is not readable.
> > -     */
> > -    default long length() throws IOException {
> > -        try(InputStream is = this.get();) {
> > -            Objects.requireNonNull(is, "resource not available");
> > -            long length = 0;
> > -            byte[] buf = new byte[256];
> > -            int bytesRead;
> > -            while ((bytesRead = is.read(buf)) > 0) {
> > -                length += bytesRead;
> > -            }
> > -            return length;
> > -        }
> > -    }
> > -
> > -    /**
> > -     * Determine the last-modified timestamp for a resource, as UTC ms
> > timestamp
> > -     *
> > -     * @throws IOException if the resource is not accessible.
> > -     */
> > -    default long lastModified() throws IOException{
> > -        return new File(toURI()).lastModified();
> > -    }
> > -
> > -    /**
> > -     * Get a name for the resource. The name should be identifying the
> resource
> > and also
> > -     * never change, so it must be eligible for hashcode/equals
> > implementations.
> > -     */
> > -    default String getName() {
> > -        try {
> > -            return toURI().toString();
> > -        } catch (Exception e) {
> > -            return toString();
> > -        }
> > -    }
> > -
> > -
> > -}
> > \ No newline at end of file
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > index 7901ca6..31856cf 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> > @@ -18,6 +18,7 @@
> >   */
> > package org.apache.tamaya.resource;
> >
> > +import java.net.URL;
> > import java.util.Arrays;
> > import java.util.Collection;
> >
> > @@ -28,16 +29,16 @@ import java.util.Collection;
> > public interface ResourceResolver {
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s.
> > Hereby
> > +     * Resolves resource expressions to a list of {@link URL}s. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    default Collection<Resource> getResources(Collection<String>
> > expressions) {
> > +    default Collection<URL> getResources(Collection<String>
> > expressions) {
> >          ClassLoader cl = Thread.currentThread().getContextClassLoader();
> >          if (cl == null) {
> >              cl = getClass().getClassLoader();
> > @@ -46,45 +47,45 @@ public interface ResourceResolver {
> >      }
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s.
> > Hereby
> > +     * Resolves resource expressions to a list of {@link URL}s. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    default Collection<Resource> getResources(String... expressions)
> > {
> > +    default Collection<URL> getResources(String... expressions) {
> >          return getResources(Arrays.asList(expressions));
> >      }
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s,
> > considerubg
> > +     * Resolves resource expressions to a list of {@link URL}s,
> > considerubg
> >       * the given classloader for classloader dependent format. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    default Collection<Resource> getResources(ClassLoader classLoader,
> > String... expressions){
> > +    default Collection<URL> getResources(ClassLoader classLoader,
> > String... expressions){
> >          return getResources(classLoader, Arrays.asList(expressions));
> >      }
> >
> >      /**
> > -     * Resolves resource expressions to a list of {@link Resource}s,
> > considerubg
> > +     * Resolves resource expressions to a list of {@link URL}s,
> > considerubg
> >       * the given classloader for classloader dependent format. Hereby
> >       * the ordering of format matches the input of the resolved
> expressions.
> > Nevertheless be aware that
> >       * there is no determined ordering of format located within a
> classloader.
> >       *
> >       * @param expressions the expressions to be resolved, not empty.
> > -     * @return the corresponding collection of current {@link Resource}s
> > found, never
> > +     * @return the corresponding collection of current {@link URL}s
> found,
> > never
> >       * null.
> >       * .
> >       */
> > -    Collection<Resource> getResources(ClassLoader classLoader,
> > Collection<String> expressions);
> > +    Collection<URL> getResources(ClassLoader classLoader,
> > Collection<String> expressions);
> >
> > }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> > deleted file mode 100644
> > index b901164..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> > +++ /dev/null
> > @@ -1,187 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.net.URISyntaxException;
> > -import java.net.URL;
> > -import java.util.Objects;
> > -import java.util.logging.Level;
> > -import java.util.logging.Logger;
> > -
> > -/**
> > - * Implementation of {@link Resource} to be loaded from the classpath.
> > - */
> > -public class ClassPathResource implements Resource {
> > -
> > -    private static final Logger LOG =
> > Logger.getLogger(ClassPathResource.class.getName());
> > -
> > -    private final String path;
> > -
> > -    private ClassLoader classLoader;
> > -
> > -
> > -    /**
> > -     * Create a new resource using the current context class loader.
> > -     *
> > -     * @param path the resource path, not null
> > -     * @see java.lang.ClassLoader#getResourceAsStream(String)
> > -     */
> > -    public ClassPathResource(String path) {
> > -        this(path, (ClassLoader) null);
> > -    }
> > -
> > -    /**
> > -     * Create a new resource using the given class loader.
> > -     *
> > -     * @param path        the resource path, not null
> > -     * @param classLoader the class loader to load the resource with,
> > -     *                    or {@code null} for the current context class
> > loader
> > -     * @see ClassLoader#getResourceAsStream(String)
> > -     */
> > -    public ClassPathResource(String path, ClassLoader classLoader) {
> > -        Objects.requireNonNull(path, "Path null");
> > -        if (path.startsWith("/")) {
> > -            path = path.substring(1);
> > -        }
> > -        this.path = path.trim();
> > -        if (classLoader == null) {
> > -            classLoader =
> Thread.currentThread().getContextClassLoader();
> > -        }
> > -        if (classLoader == null) {
> > -            classLoader = getClass().getClassLoader();
> > -        }
> > -        this.classLoader = classLoader;
> > -    }
> > -
> > -    /**
> > -     * @return the path for this resource.
> > -     */
> > -    public final String getPath() {
> > -        return this.path;
> > -    }
> > -
> > -    /**
> > -     * @return the ClassLoader that this resource will be accessed from.
> > -     */
> > -    public final ClassLoader getClassLoader() {
> > -        return this.classLoader;
> > -    }
> > -
> > -
> > -    /**
> > -     * Checks if the given resource is resolvable from the configured
> > classloader.
> > -     *
> > -     * @see java.lang.ClassLoader#getResource(String)
> > -     */
> > -    @Override
> > -    public boolean exists() {
> > -        return (resolveURL() != null);
> > -    }
> > -
> > -    /**
> > -     * Resolves a URL for the underlying class path resource.
> > -     *
> > -     * @return the resolved URL, or {@code null}
> > -     */
> > -    protected URL resolveURL() {
> > -        return this.classLoader.getResource(this.path);
> > -    }
> > -
> > -    /**
> > -     * This implementation opens an InputStream for the given class path
> > resource.
> > -     *
> > -     * @see java.lang.ClassLoader#getResourceAsStream(String)
> > -     * @see java.lang.Class#getResourceAsStream(String)
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        try {
> > -            InputStream is =
> this.classLoader.getResourceAsStream(this.path);
> > -            if (is == null) {
> > -                throw new IOException(getName() + " does not exist");
> > -            }
> > -            return is;
> > -        } catch (IOException e) {
> > -            LOG.log(Level.INFO, "Failed to open classpath resource: "
> > + path, e);
> > -            return null;
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        try {
> > -            return resolveURL().toURI();
> > -        } catch (URISyntaxException e) {
> > -            throw new IOException(e);
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public long lastModified() throws IOException {
> > -        return 0;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the name current the file that this
> class
> > path
> > -     * resource refers to.
> > -     */
> > -    @Override
> > -    public String getName() {
> > -        return "classpath:" + path;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns a description that includes the
> class path
> > location.
> > -     */
> > -    @Override
> > -    public String toString() {
> > -        return "ClassPathResource[" + path + ']';
> > -    }
> > -
> > -    /**
> > -     * This implementation compares the underlying class path locations.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        if (obj == this) {
> > -            return true;
> > -        }
> > -        if (obj instanceof ClassPathResource) {
> > -            ClassPathResource otherRes = (ClassPathResource) obj;
> > -            return (this.path.equals(otherRes.path) &&
> > -                    Objects.equals(this.classLoader,
> otherRes.classLoader));
> > -        }
> > -        return false;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the hash code current the underlying
> > -     * class path location.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return getName().hashCode();
> > -    }
> > -
> > -}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> > new file mode 100644
> > index 0000000..3f2093b
> > --- /dev/null
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> > @@ -0,0 +1,264 @@
> > +/*
> > + * 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.resource.internal;
> > +
> > +import java.io.File;
> > +import java.io.IOException;
> > +import java.net.JarURLConnection;
> > +import java.net.MalformedURLException;
> > +import java.net.URISyntaxException;
> > +import java.net.URL;
> > +import java.net.URLConnection;
> > +import java.util.ArrayList;
> > +import java.util.Collection;
> > +import java.util.Enumeration;
> > +import java.util.List;
> > +import java.util.Objects;
> > +import java.util.jar.JarEntry;
> > +import java.util.jar.JarFile;
> > +import java.util.logging.Level;
> > +import java.util.logging.Logger;
> > +
> > +/**
> > + * Collector that searches files based on ant styled patterns. For
> example the
> > following patterns would be matched:
> > + * <pre>
> > + *     classpath:javax/annotations/*
> > + *     javax?/annotations/**/*.class
> > + *     org/apache/tamaya/**/tamayaconfig.properties
> > + * </pre>
> > + */
> > +public class ClasspathCollector {
> > +
> > +    /**
> > +     * JAR protocol.
> > +     */
> > +    public static final String PROTOCOL_JAR = "jar";
> > +
> > +    /**
> > +     * Separator between JAR file URL and the internal jar file path.
> > +     */
> > +    public static final String JAR_URL_SEPARATOR = "!/";
> > +
> > +    /**
> > +     * ZIP protocol.
> > +     */
> > +    public static final String PROTOCOL_ZIP = "zip";
> > +
> > +    /**
> > +     * ZIP protocol for a JBoss jar file entry: "vfszip".
> > +     */
> > +    public static final String PROTOCOL_VFSZIP = "vfszip";
> > +
> > +    /**
> > +     * URL protocol for an WebSphere jar file: "wsjar".
> > +     */
> > +    public static final String PROTOCOL_WSJAR = "wsjar";
> > +
> > +    /**
> > +     * URL protocol for an entry from an OC4J jar.
> > +     */
> > +    public static final String PROTOCOL_CODE_SOURCE = "code-source";
> > +
> > +    /**
> > +     * The logger used.
> > +     */
> > +    private static final Logger LOG =
> > Logger.getLogger(ClasspathCollector.class.getName());
> > +
> > +    /**
> > +     * The classloader used to load the resources.
> > +     */
> > +    private ClassLoader classLoader;
> > +
> > +    /**
> > +     * Creates a new instance.
> > +     *
> > +     * @param classLoader the class loader to be used, not null.
> > +     */
> > +    public ClasspathCollector(ClassLoader classLoader) {
> > +        this.classLoader = Objects.requireNonNull(classLoader);
> > +    }
> > +
> > +    /**
> > +     * Collect all classpath resources given the expression.
> > +     *
> > +     * @param expression the expression, not null.
> > +     * @return the resources found.
> > +     */
> > +    public Collection<URL> collectFiles(String expression) {
> > +        if (expression.startsWith("classpath:")) {
> > +            expression = expression.substring("classpath:".length());
> > +        }
> > +        if (expression.startsWith("/")) {
> > +            expression = expression.substring(1);
> > +        }
> > +        Locator locator = Locator.of(expression);
> > +        List<URL> result = new ArrayList<>();
> > +        String rootPath = locator.getRootPath();
> > +        try {
> > +            Enumeration<URL> rootResources =
> > this.classLoader.getResources(rootPath);
> > +            while (rootResources.hasMoreElements()) {
> > +                URL resource = rootResources.nextElement();
> > +                try {
> > +                    if (isJarFile(resource)) {
> > +
> result.addAll(doFindPathMatchingJarResources(resource,
> > locator.getSubPath()));
> > +                    } else {
> > +                        File file = getFile(resource);
> > +
> > result.addAll(FileCollector.traverseAndSelectFromChildren(file,
> > locator.getSubPathTokens(), 0));
> > +                    }
> > +                } catch (Exception e) {
> > +                    LOG.log(Level.SEVERE, "Error locating resources for:
> > " + expression, e);
> > +                }
> > +            }
> > +        } catch (IOException e) {
> > +            LOG.log(Level.SEVERE, "Error locating resources for: " +
> > expression, e);
> > +        }
> > +        return result;
> > +    }
> > +
> > +
> > +    /**
> > +     * Find all resources in jar files that match the given location
> pattern
> > +     * via the Ant-style PathMatcher.
> > +     *
> > +     * @param rootDirResource the root directory as Resource
> > +     * @param subPattern      the sub pattern to match (below the root
> > directory)
> > +     * @return the Set of matching Resource instances
> > +     * @throws java.io.IOException in case of I/O errors
> > +     * @see java.net.JarURLConnection
> > +     */
> > +    protected Collection<URL> doFindPathMatchingJarResources(URL
> > rootDirResource, String subPattern)
> > +            throws IOException, URISyntaxException {
> > +        subPattern = subPattern.replace("*",
> > ".*").replace("?", ".?").replace(".*.*",
> > ".*");
> > +        URLConnection con =
> rootDirResource.toURI().toURL().openConnection();
> > +        JarFile jarFile;
> > +        boolean newJarFile = false;
> > +        String jarFileUrl;
> > +        String rootEntryPath;
> > +
> > +        if (con instanceof JarURLConnection) {
> > +            // Should usually be the case for traditional JAR files.
> > +            JarURLConnection jarCon = (JarURLConnection) con;
> > +            jarCon.setUseCaches(false);
> > +            jarFile = jarCon.getJarFile();
> > +            jarFileUrl = jarCon.getJarFileURL().toExternalForm();
> > +            JarEntry jarEntry = jarCon.getJarEntry();
> > +            rootEntryPath = (jarEntry != null ? jarEntry.getName() :
> > "");
> > +        } else {
> > +            // No JarURLConnection -> need to resort to URL file
> parsing.
> > +            // We'll assume URLs of the format "jar:path!/entry",
> > with the protocol
> > +            // being arbitrary as long as following the entry format.
> > +            // We'll also handle paths with and without leading
> > "file:" prefix.
> > +            String urlFile = rootDirResource.toURI().toURL().getFile();
> > +            int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
> > +            jarFileUrl = urlFile.substring(0, separatorIndex);
> > +            if (jarFileUrl.startsWith("file:")) {
> > +                jarFileUrl = jarFileUrl.substring("file:".length());
> > +            }
> > +            jarFile = new JarFile(jarFileUrl);
> > +            newJarFile = true;
> > +            jarFileUrl = "file:" + jarFileUrl;
> > +            rootEntryPath = urlFile.substring(separatorIndex +
> > JAR_URL_SEPARATOR.length());
> > +        }
> > +
> > +        try {
> > +            if (LOG.isLoggable(Level.FINEST)) {
> > +                LOG.finest("Looking for matching resources in jar file
> > [" + jarFileUrl + "]");
> > +            }
> > +            if (!rootEntryPath.isEmpty() &&
> > !rootEntryPath.endsWith("/")) {
> > +                // Root entry path must end with slash for correct
> matching
> > +                rootEntryPath = rootEntryPath + '/';
> > +            }
> > +            Collection<URL> result = new ArrayList<>(10);
> > +            for (Enumeration entries = jarFile.entries();
> > entries.hasMoreElements(); ) {
> > +                JarEntry entry = (JarEntry) entries.nextElement();
> > +                String entryPath = entry.getName();
> > +                if (entryPath.startsWith(rootEntryPath)) {
> > +                    String relativePath =
> > entryPath.substring(rootEntryPath.length());
> > +                    if (relativePath.matches(subPattern)) {
> > +                        result.add(createRelativeFrom(rootDirResource,
> > relativePath));
> > +                    }
> > +                }
> > +            }
> > +            return result;
> > +        } finally {
> > +            // Close jar file, but only if freshly obtained -
> > +            // not from JarURLConnection, which might cache the file
> reference.
> > +            if (newJarFile) {
> > +                jarFile.close();
> > +            }
> > +        }
> > +    }
> > +
> > +    /**
> > +     * Creates a new URL based on the given root path and the relative
> path to
> > be added.
> > +     *
> > +     * @param url          the root, not null
> > +     * @param relativePath the relative path to be added, not null
> > +     * @return the new URL instance
> > +     * @throws MalformedURLException
> > +     */
> > +    private URL createRelativeFrom(URL url, String relativePath)
> > +            throws MalformedURLException {
> > +        String rootDirResource = url.toExternalForm();
> > +        if (relativePath.startsWith("/")) {
> > +            relativePath = relativePath.substring(1);
> > +        }
> > +        if (!rootDirResource.endsWith("/")) {
> > +            rootDirResource = rootDirResource + '/';
> > +        }
> > +        return new URL(rootDirResource + relativePath);
> > +    }
> > +
> > +
> > +    /**
> > +     * Small check if a given URL is a jar file URL.
> > +     *
> > +     * @param url the URL to check, not null.
> > +     * @return true if the URL has one of the following protocols: jar,
> zip,
> > vfszip, wsjar, code-source.
> > +     */
> > +    private boolean isJarFile(URL url) {
> > +        String protocol = Objects.requireNonNull(url).getProtocol();
> > +        return (PROTOCOL_JAR.equals(protocol) ||
> > +                PROTOCOL_ZIP.equals(protocol) ||
> > +                PROTOCOL_VFSZIP.equals(protocol) ||
> > +                PROTOCOL_WSJAR.equals(protocol) ||
> > +                (PROTOCOL_CODE_SOURCE.equals(protocol) &&
> > url.getPath().indexOf(JAR_URL_SEPARATOR) != -1));
> > +    }
> > +
> > +    /**
> > +     * Creates a file from an URL.
> > +     *
> > +     * @param resourceUrl the url, not null.
> > +     * @return a new file instance. The instance still may not exist.
> if the
> > url's protocol is not 'file', {@code null}
> > +     * is returned.
> > +     */
> > +    private File getFile(URL resourceUrl) {
> > +        Objects.requireNonNull(resourceUrl, "Resource URL must not be
> > null");
> > +        if (!"file".equals(resourceUrl.getProtocol())) {
> > +            return null;
> > +        }
> > +        try {
> > +            return new
> File(resourceUrl.toURI().getSchemeSpecificPart());
> > +        } catch (Exception ex) {
> > +            // Fallback for URLs that are not valid URIs (should hardly
> ever
> > happen).
> > +            return new File(resourceUrl.getFile());
> > +        }
> > +    }
> > +
> > +}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > index 9fd6fc4..c90e53a 100644
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> > @@ -18,7 +18,6 @@
> >   */
> > package org.apache.tamaya.resource.internal;
> >
> > -import org.apache.tamaya.resource.Resource;
> > import org.apache.tamaya.resource.ResourceResolver;
> >
> > import javax.annotation.Priority;
> > @@ -39,10 +38,10 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >      private static final Logger LOG =
> > Logger.getLogger(DefaultResourceResolver.class.getName());
> >
> >      @Override
> > -    public List<Resource> getResources(ClassLoader classLoader,
> > Collection<String> expressions) {
> > -        List<Resource> resources = new ArrayList<>();
> > +    public List<URL> getResources(ClassLoader classLoader,
> > Collection<String> expressions) {
> > +        List<URL> resources = new ArrayList<>();
> >          for (String expression : expressions) {
> > -            if (tryClassPath(classLoader, expression, resources) ||
> > tryFile(expression, resources) ||
> > +            if (tryPath(classLoader, expression, resources) ||
> > tryClassPath(classLoader, expression, resources) || tryFile(expression,
> > resources) ||
> >                      tryURL(expression, resources)) {
> >                  continue;
> >              }
> > @@ -51,12 +50,41 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >          return resources;
> >      }
> >
> > -    private boolean tryClassPath(ClassLoader classLoader, String
> expression,
> > List<Resource> resources) {
> > +    /**
> > +     * Tries to evaluate the location passed by Ant path matching.
> > +     * @param classLoader the class loader to use
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryPath(ClassLoader classLoader, String expression,
> > List<URL> resources) {
> > +        try {
> > +            // 1: try file path
> > +            Collection<URL> found =
> > FileCollector.collectFiles(expression);
> > +            if (found.isEmpty()) {
> > +                found = new
> > ClasspathCollector(classLoader).collectFiles(expression);
> > +            }
> > +            resources.addAll(found);
> > +            return !found.isEmpty();
> > +        } catch (Exception e) {
> > +            LOG.finest(() -> "Failed to load resource from CP: " +
> > expression);
> > +        }
> > +        return false;
> > +    }
> > +
> > +    /**
> > +     * Tries to evaluate the location passed by loading from the
> classloader.
> > +     * @param classLoader the class loader to use
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryClassPath(ClassLoader classLoader, String
> expression,
> > List<URL> resources) {
> >          try {
> >              Enumeration<URL> urls =
> classLoader.getResources(expression);
> >              while (urls.hasMoreElements()) {
> >                  URL url = urls.nextElement();
> > -                resources.add(new UrlResource(url));
> > +                resources.add(url);
> >              }
> >              return !resources.isEmpty();
> >          } catch (Exception e) {
> > @@ -65,11 +93,17 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >          return false;
> >      }
> >
> > -    private boolean tryFile(String expression, List<Resource> resources)
> > {
> > +    /**
> > +     * Tries to evaluate the location passed by lokking up a file.
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryFile(String expression, List<URL> resources)
> > {
> >          try {
> >              File file = new File(expression);
> >              if (file.exists()) {
> > -                resources.add(new FileResource(file));
> > +                resources.add(file.toURI().toURL());
> >                  return true;
> >              }
> >          } catch (Exception e) {
> > @@ -78,16 +112,21 @@ public class DefaultResourceResolver implements
> > ResourceResolver {
> >          return false;
> >      }
> >
> > -    private boolean tryURL(String expression, List<Resource> resources)
> > {
> > +    /**
> > +     * Tries to interpret the expression as URL.
> > +     * @param expression the path expression
> > +     * @param resources the resources for adding the results
> > +     * @return true, if the expression could be resolved.
> > +     */
> > +    private boolean tryURL(String expression, List<URL> resources) {
> >          try {
> >              URL url = new URL(expression);
> > -            resources.add(new UrlResource(url));
> > +            resources.add(url);
> >              return true;
> >          } catch (Exception e) {
> >              LOG.finest(() -> "Failed to load resource from file: "
> > + expression);
> >          }
> >          return false;
> > -
> >      }
> >
> > }
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> > new file mode 100644
> > index 0000000..d506e11
> > --- /dev/null
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> > @@ -0,0 +1,157 @@
> > +/*
> > + * 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.resource.internal;
> > +
> > +import java.io.File;
> > +import java.net.URL;
> > +import java.util.ArrayList;
> > +import java.util.Collection;
> > +import java.util.Collections;
> > +import java.util.List;
> > +import java.util.Objects;
> > +import java.util.logging.Logger;
> > +
> > +/**
> > + * Collector that searches files based on ant styled patterns. For
> example the
> > following patterns would be matched:
> > + * <pre>
> > + *     file:C:/temp/*.txt
> > + *     file:C:\**\*.ini
> > + *     C:\Programs\**/*.ini
> > + *     /user/home/A*b101_?.pid
> > + *     /var/logs/**/*.log
> > + * </pre>
> > + */
> > +public class FileCollector {
> > +
> > +    public static final String FILE_PREFIX = "file:";
> > +
> > +    private FileCollector() {
> > +    }
> > +
> > +    private static final Logger LOG =
> > Logger.getLogger(FileCollector.class.getName());
> > +
> > +    public static Collection<URL> collectFiles(String expression) {
> > +        expression = expression.replace("\\", "/");
> > +        Locator locator = Locator.of(expression);
> > +        List<URL> result = new ArrayList<>();
> > +        String rootPath = locator.getRootPath();
> > +        if (rootPath.startsWith(FILE_PREFIX)) {
> > +            rootPath = rootPath.substring(FILE_PREFIX.length());
> > +        }
> > +        File file = new File(rootPath);
> > +        if (file.exists()) {
> > +            List<String> subTokens = locator.getSubPathTokens();
> > +            result.addAll(traverseAndSelectFromChildren(file,
> subTokens, 0));
> > +        }
> > +        return result;
> > +    }
> > +
> > +    static Collection<URL> traverseAndSelectFromChildren(File dir,
> > List<String> subTokens, int tokenIndex) {
> > +        if (tokenIndex >= subTokens.size() || dir.isFile()) {
> > +            return Collections.emptyList();
> > +        }
> > +        List<URL> result = new ArrayList<>();
> > +        String token = subTokens.get(tokenIndex);
> > +        if (token.equals("**")) {
> > +            result.addAll(traverseAndSelectFromChildren(dir,
> > getSubExpression(subTokens, tokenIndex + 1)));
> > +        } else {
> > +            token = token.replace("*", ".*");
> > +            File[] files = dir.listFiles();
> > +            if (tokenIndex == subTokens.size() - 1) {
> > +                // select files!
> > +                for (File f : files) {
> > +                    if (f.isFile() && f.getName().matches(token))
> > {
> > +                        result.add(getURL(f));
> > +                    }
> > +                }
> > +            } else {
> > +                // check directory pattern
> > +                for (File f : files) {
> > +                    if (f.isDirectory() && f.getName().matches(token))
> > {
> > +                        result.addAll(traverseAndSelectFromChildren(f,
> > subTokens, tokenIndex + 1));
> > +                    }
> > +                }
> > +            }
> > +        }
> > +        return result;
> > +    }
> > +
> > +    static Collection<URL> traverseAndSelectFromChildren(File file,
> > String subExpression) {
> > +        List<URL> result = new ArrayList<>();
> > +        for (File childFile : file.listFiles()) {
> > +            if (childFile.isFile()) {
> > +                if (childFile.getName().matches(subExpression)) {
> > +                    try {
> > +                        result.add(getURL(childFile));
> > +                    } catch (Exception e) {
> > +                        LOG.warning(() -> "File not convertible to URL:
> > " + childFile);
> > +                    }
> > +                }
> > +            } else if (childFile.isDirectory()) {
> > +                result.addAll(traverseAndSelectFromChildren(childFile,
> > subExpression));
> > +            }
> > +        }
> > +        return result;
> > +    }
> > +
> > +    private static boolean matchesFile(File childFile, List<String>
> > subTokens, int tokenIndex) {
> > +        if (tokenIndex < (subTokens.size() - 1)) {
> > +            // not all tokens consumed, so no match!
> > +            return false;
> > +        }
> > +        String tokenToMatch = subTokens.get(tokenIndex);
> > +        tokenToMatch = tokenToMatch.replace("*", ".*");
> > +        return childFile.getName().matches(tokenToMatch);
> > +    }
> > +
> > +    /**
> > +     * Get an URL from a file.
> > +     *
> > +     * @param file the file, not null.
> > +     * @return the URL, never null.
> > +     * @throws java.lang.IllegalStateException if it fails to create
> the URL
> > +     */
> > +    private static URL getURL(File file) {
> > +        Objects.requireNonNull(file);
> > +        try {
> > +            return file.toURI().toURL();
> > +        } catch (Exception e) {
> > +            throw new IllegalStateException("Failed to create URL from
> > file: " + file);
> > +        }
> > +    }
> > +
> > +    /**
> > +     * Constructs a sub expression, using the tokens from {@code
> > subTokens} starting at index {@code startIndex}.
> > +     *
> > +     * @param subTokens  the token list, not null
> > +     * @param startIndex the start index from where tokens should be
> taken to
> > produce the path.
> > +     * @return the constructed path, never null.
> > +     */
> > +    private static String getSubExpression(List<String> subTokens, int
> > startIndex) {
> > +        StringBuilder b = new StringBuilder();
> > +        for (int i = startIndex; i < subTokens.size(); i++) {
> > +            b.append(subTokens.get(i));
> > +            b.append('/');
> > +        }
> > +        if (b.length() > 0) {
> > +            b.setLength(b.length() - 1);
> > +        }
> > +        return b.toString().replaceAll("\\*",
> > ".*").replaceAll("\\?", ".?");
> > +    }
> > +}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> > deleted file mode 100644
> > index c5f521a..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> > +++ /dev/null
> > @@ -1,172 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -import java.io.File;
> > -import java.io.FileInputStream;
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.util.Objects;
> > -import java.util.logging.Level;
> > -import java.util.logging.Logger;
> > -
> > -/**
> > - * Implementation of {@link Resource} to be loaded from a file.
> > - *
> > - * @see java.io.File
> > - */
> > -public class FileResource implements Resource {
> > -
> > -    private static final Logger LOG =
> > Logger.getLogger(FileResource.class.getName());
> > -
> > -    private final File file;
> > -
> > -    /**
> > -     * Creates a new instance.
> > -     *
> > -     * @param file a File, not null.
> > -     */
> > -    public FileResource(File file) {
> > -        this.file = Objects.requireNonNull(file, "File must not be
> > null");
> > -    }
> > -
> > -    /**
> > -     * Crreates a new instance.
> > -     *
> > -     * @param filePath a file path
> > -     */
> > -    public FileResource(String filePath) {
> > -        Objects.requireNonNull(filePath, "Path must not be null");
> > -        this.file = new File(filePath);
> > -    }
> > -
> > -
> > -    /**
> > -     * Get the file path for this resource.
> > -     */
> > -    public final String getPath() {
> > -        return this.file.getPath();
> > -    }
> > -
> > -
> > -    /**
> > -     * This implementation returns whether the underlying file exists.
> > -     *
> > -     * @see java.io.File#exists()
> > -     */
> > -    @Override
> > -    public boolean exists() {
> > -        return this.file.exists();
> > -    }
> > -
> > -    /**
> > -     * This implementation checks whether the underlying file is marked
> as
> > readable
> > -     * (and corresponds to an actual file with content, not to a
> directory).
> > -     *
> > -     * @see java.io.File#canRead()
> > -     * @see java.io.File#isDirectory()
> > -     */
> > -    @Override
> > -    public boolean isAccessible() {
> > -        return (this.file.canRead() && !this.file.isDirectory());
> > -    }
> > -
> > -    /**
> > -     * This implementation opens a FileInputStream for the underlying
> file.
> > -     *
> > -     * @see java.io.FileInputStream
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        try {
> > -            return new FileInputStream(this.file);
> > -        } catch (Exception e) {
> > -            LOG.log(Level.INFO, "Failed to open file: " +
> > file.getAbsolutePath(), e);
> > -            return null;
> > -        }
> > -    }
> > -
> > -    /**
> > -     * This implementation returns a URI for the underlying file.
> > -     *
> > -     * @see java.io.File#toURI()
> > -     */
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        return this.file.toURI();
> > -    }
> > -
> > -    /**
> > -     * Returns the underlying File's length.
> > -     */
> > -    @Override
> > -    public long length() throws IOException {
> > -        return this.file.length();
> > -    }
> > -
> > -    @Override
> > -    public long lastModified() throws IOException {
> > -        return file.lastModified();
> > -    }
> > -
> > -    /**
> > -     * Returns the name of the current file.
> > -     *
> > -     * @see java.io.File#getName()
> > -     */
> > -    @Override
> > -    public String getName() {
> > -        return this.file.getName();
> > -    }
> > -
> > -    /**
> > -     * Returns a description that includes the absolute
> > -     * path of the current file.
> > -     *
> > -     * @see java.io.File#getAbsolutePath()
> > -     */
> > -    @Override
> > -    public String toString() {
> > -        return "File [" + this.file.getAbsolutePath() +
> > "]";
> > -    }
> > -
> > -
> > -    // implementation current WritableResource
> > -
> > -    /**
> > -     * Compares the underlying Files.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        return (obj == this ||
> > -                (obj instanceof FileResource &&
> > this.file.equals(((FileResource) obj).file)));
> > -    }
> > -
> > -    /**
> > -     * Returns hash code current the underlying File reference.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return this.file.hashCode();
> > -    }
> > -
> > -}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> > deleted file mode 100644
> > index d4aa673..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> > +++ /dev/null
> > @@ -1,117 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -import java.io.IOException;
> > -import java.io.InputStream;
> > -import java.net.URI;
> > -import java.util.Objects;
> > -
> > -/**
> > - * Simple Resource encapsulating an InputStream.
> > - */
> > -public class InputStreamResource implements Resource {
> > -
> > -    /** The InputStream. */
> > -    private final InputStream inputStream;
> > -    /** The read flag. */
> > -    private boolean read = false;
> > -    /** The name of the resource. */
> > -    private String name;
> > -
> > -
> > -    /**
> > -     * Create a new InputStreamResource.
> > -     *
> > -     * @param inputStream the InputStream to use
> > -     */
> > -    public InputStreamResource(InputStream inputStream) {
> > -        this(inputStream, "InputStream:");
> > -    }
> > -
> > -    /**
> > -     * Create a new InputStreamResource.
> > -     *
> > -     * @param inputStream the InputStream to use
> > -     * @param name where the InputStream comes from
> > -     */
> > -    public InputStreamResource(InputStream inputStream, String name) {
> > -        this.inputStream = Objects.requireNonNull(inputStream);
> > -        this.name = (name != null ? name : "InputStream");
> > -    }
> > -
> > -
> > -    /**
> > -     * This implementation always returns {@code true}.
> > -     */
> > -    @Override
> > -    public boolean exists() {
> > -        return true;
> > -    }
> > -
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        throw new IOException("URI not available.");
> > -    }
> > -
> > -    @Override
> > -    public long lastModified() throws IOException {
> > -        throw new IOException("lastModified not available.");
> > -    }
> > -
> > -    /**
> > -     * Accesses the input stream. Hereby the input stream can only
> accessed
> > once.
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        if (this.read) {
> > -            throw new IllegalStateException("InputStream can only be
> read
> > once!");
> > -        }
> > -        this.read = true;
> > -        return this.inputStream;
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the passed-in description, if any.
> > -     */
> > -    public String toString() {
> > -        return this.name != null ? this.name : super.toString();
> > -    }
> > -
> > -
> > -    /**
> > -     * Compares the underlying InputStream.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        return (obj == this ||
> > -                (obj instanceof InputStreamResource &&
> > ((InputStreamResource) obj).inputStream.equals(this.inputStream)));
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the hash code current the underlying
> > InputStream.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return this.inputStream.hashCode();
> > -    }
> > -
> > -}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> > new file mode 100644
> > index 0000000..8d9e08a
> > --- /dev/null
> > +++
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> > @@ -0,0 +1,150 @@
> > +/*
> > + * 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.resource.internal;
> > +
> > +import java.util.ArrayList;
> > +import java.util.Arrays;
> > +import java.util.List;
> > +import java.util.stream.Collectors;
> > +
> > +/**
> > + * Small helper class that manages the path parts of a location
> expression.
> > + */
> > +final class Locator {
> > +    /**
> > +     * The tokenized location expression.
> > +     */
> > +    private List<String> tokens;
> > +
> > +    /**
> > +     * Creates a new instances based on the tokenized expression.
> > +     *
> > +     * @param tokens the tokenized expression, not null.
> > +     */
> > +    Locator(List<String> tokens) {
> > +        this.tokens = tokens;
> > +    }
> > +
> > +    /**
> > +     * Creates a new instance of the corresponding expression.
> > +     *
> > +     * @param expression the location expression, not null.
> > +     * @return the tokenized instance.
> > +     */
> > +    public static Locator of(String expression) {
> > +        return new
> > Locator(Arrays.asList(expression.split("/")).stream().filter((s) ->
> > !s.isEmpty()).collect(Collectors.toList()));
> > +    }
> > +
> > +    /**
> > +     * Access the root path, which is the location expression, before
> any
> > wildcards or placeholders are used.
> > +     * It is used as the entry point into the file system or for
> accessing base
> > classpath resources, before
> > +     * further analysis on the file or jar filesystem can be performed.
> > +     *
> > +     * @return the root path, never null.
> > +     */
> > +    public String getRootPath() {
> > +        StringBuilder builder = new StringBuilder();
> > +        for (String token : tokens) {
> > +            if (containsPlaceholder(token)) {
> > +                break;
> > +            } else {
> > +                builder.append(token);
> > +                builder.append('/');
> > +            }
> > +        }
> > +        if (builder.length() > 0) {
> > +            builder.setLength(builder.length() - 1);
> > +        }
> > +        return builder.toString();
> > +    }
> > +
> > +    /**
> > +     * Return the sub expression path, which contains the second part
> of the
> > expression, starting with a placeholder
> > +     * or wildcard token.
> > +     *
> > +     * @return the sub expression part, never null.
> > +     */
> > +    public String getSubPath() {
> > +        StringBuilder builder = new StringBuilder();
> > +        for (String token : getSubPathTokens()) {
> > +            builder.append(token);
> > +            builder.append('/');
> > +        }
> > +        if (builder.length() > 0) {
> > +            builder.setLength(builder.length() - 1);
> > +        }
> > +        return builder.toString();
> > +    }
> > +
> > +    /**
> > +     * This method returns the single tokenized form of the sub
> expression.
> > +     *
> > +     * @return the tokenized version of the sub path.
> > +     * @see #getSubPath()
> > +     */
> > +    public List<String> getSubPathTokens() {
> > +        List<String> subTokens = new ArrayList<>();
> > +        for (String token : tokens) {
> > +            if (!containsPlaceholder(token)) {
> > +                continue;
> > +            } else {
> > +                subTokens.add(token);
> > +            }
> > +        }
> > +        return subTokens;
> > +    }
> > +
> > +    /**
> > +     * Access the full reconstructed path. In most cases this should
> match the
> > original expression.
> > +     *
> > +     * @return the full expression path, never null.
> > +     */
> > +    public String getPath() {
> > +        StringBuilder builder = new StringBuilder();
> > +        for (String token : tokens) {
> > +            builder.append(token);
> > +            builder.append('/');
> > +        }
> > +        if (builder.length() > 0) {
> > +            builder.setLength(builder.length() - 1);
> > +        }
> > +        return builder.toString();
> > +    }
> > +
> > +    /**
> > +     * Short method that checks for '*' and '?' chars.
> > +     *
> > +     * @param token the token to check, not null
> > +     * @return true, if it contains wildcard characters.
> > +     */
> > +    private boolean containsPlaceholder(String token) {
> > +        return token.contains("*") || token.contains("?");
> > +    }
> > +
> > +    /**
> > +     * Return the expressions' path.
> > +     *
> > +     * @return the locator path.
> > +     */
> > +    @Override
> > +    public String toString() {
> > +        return "Locator: " + getPath();
> > +    }
> > +
> > +}
> >
> >
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> > ----------------------------------------------------------------------
> > diff --git
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> >
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> > deleted file mode 100644
> > index 6522cf5..0000000
> > ---
> >
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> > +++ /dev/null
> > @@ -1,140 +0,0 @@
> > -/*
> > - * 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.resource.internal;
> > -
> > -import org.apache.tamaya.resource.Resource;
> > -
> > -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;
> > -import java.util.logging.Level;
> > -import java.util.logging.Logger;
> > -
> > -/**
> > - * Implementation of a resource based on a {@code java.net.URL}.
> > - */
> > -public class UrlResource implements Resource {
> > -
> > -    private static final Logger LOG =
> > Logger.getLogger(UrlResource.class.getName());
> > -
> > -    /**
> > -     * Original URL, used for actual access.
> > -     */
> > -    private final URL url;
> > -
> > -    /**
> > -     * Create a new instance based on the given URL.
> > -     *
> > -     * @param url a URL
> > -     */
> > -    public UrlResource(URL url) {
> > -        this.url = Objects.requireNonNull(url, "URL null");
> > -    }
> > -
> > -    /**
> > -     * Create a new URLResource based on a URL path.
> > -     *
> > -     * @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.url = new URL(path);
> > -    }
> > -
> > -
> > -    /**
> > -     * This implementation opens an InputStream for the given URL.
> > -     *
> > -     * @see java.net.URL#openConnection()
> > -     * @see java.net.URLConnection#setUseCaches(boolean)
> > -     * @see java.net.URLConnection#getInputStream()
> > -     */
> > -    @Override
> > -    public InputStream get() {
> > -        URLConnection con = null;
> > -        try {
> > -            con = this.url.openConnection();
> > -            useCachesIfNecessary(con);
> > -            return con.getInputStream();
> > -        } catch (IOException e) {
> > -            if (con instanceof HttpURLConnection) {
> > -                ((HttpURLConnection) con).disconnect();
> > -            }
> > -            LOG.log(Level.INFO, "Failed to open URL: " + url, e);
> > -            return null;
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public URI toURI() throws IOException {
> > -        try {
> > -            return this.url.toURI();
> > -        } catch (URISyntaxException e) {
> > -            throw new IOException("Failed to create URI from " +
> > url);
> > -        }
> > -    }
> > -
> > -    @Override
> > -    public String getName() {
> > -        return this.url.toString();
> > -    }
> > -
> > -    @Override
> > -    public String toString() {
> > -        return "URL [" + this.url + "]";
> > -    }
> > -
> > -    /**
> > -     * Compares the underlying URL references.
> > -     */
> > -    @Override
> > -    public boolean equals(Object obj) {
> > -        return (obj == this ||
> > -                (obj instanceof UrlResource &&
> > this.url.equals(((UrlResource) obj).url)));
> > -    }
> > -
> > -    /**
> > -     * This implementation returns the hash code current the underlying
> URL
> > reference.
> > -     */
> > -    @Override
> > -    public int hashCode() {
> > -        return this.url.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 format.
> > -     *
> > -     * @param con the URLConnection to set the flag on
> > -     */
> > -    private void useCachesIfNecessary(URLConnection con) {
> > -
> > con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
> > -    }
> > -
> > -}
> > -
> >
>

Re: [1/6] incubator-tamaya git commit: TAMAYA-43: Implemented ant pattern based resource lookup for files and classpath, about 20k compiled size overall. TAMAYA-43: Removed Resource abstraction in favor of URL.

Posted by Mark Struberg <st...@yahoo.de>.
Anatole, again: 


> PROTOCOL_WSJAR


All this does NOT work portably!
Many people tried that many times and it simply does NOT work that easily!
The solution I know to work (xban-finder) explicitly has exit points to extend archive handlers. And it is about 200kByte of size alltogether. 


The problem with such a solution is that we must support it perfectly well, or not at all...

What we *could* support is a _very_ easy solution with a prefix

classpath-config:mydir/myconfig.properties
vs a real URL e.g. file://

In the first case we would simply use ClassLoader.getResources and register 0..n ConfigSources, in the second case we register exactly the one URL we got handed over as parameter.

Also note that any wildcard style in an URL or classpath resource is NOT widely supported. Some ClassLoaders can handle it in SOME situations, but most of them don't.

LieGrue,
strub





> On Sunday, 11 January 2015, 1:44, "anatole@apache.org" <an...@apache.org> wrote:
> > Repository: incubator-tamaya
> Updated Branches:
>   refs/heads/master 2dd0c13e5 -> c48c5794e
> 
> 
> TAMAYA-43: Implemented ant pattern based resource lookup for files and 
> classpath, about 20k compiled size overall.
> TAMAYA-43: Removed Resource abstraction in favor of URL.
> 
> 
> Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
> Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/ae66299e
> Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/ae66299e
> Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/ae66299e
> 
> Branch: refs/heads/master
> Commit: ae66299e25b41167008021ffe95cad236f6e2bd3
> Parents: 2dd0c13
> Author: anatole <an...@apache.org>
> Authored: Wed Jan 7 22:49:39 2015 +0100
> Committer: anatole <an...@apache.org>
> Committed: Sun Jan 11 01:40:57 2015 +0100
> 
> ----------------------------------------------------------------------
> .../tamaya/format/ConfigurationFormat.java      |  10 +-
> .../apache/tamaya/format/PropertiesFormat.java  |  15 +-
> .../tamaya/format/PropertiesXmlFormat.java      |  15 +-
> ...AbstractPathBasedPropertySourceProvider.java |   7 +-
> .../AbstractResourcePropertySourceProvider.java |  17 +-
> .../org/apache/tamaya/resource/Resource.java    | 115 --------
> .../tamaya/resource/ResourceResolver.java       |  25 +-
> .../resource/internal/ClassPathResource.java    | 187 -------------
> .../resource/internal/ClasspathCollector.java   | 264 +++++++++++++++++++
> .../internal/DefaultResourceResolver.java       |  61 ++++-
> .../tamaya/resource/internal/FileCollector.java | 157 +++++++++++
> .../tamaya/resource/internal/FileResource.java  | 172 ------------
> .../resource/internal/InputStreamResource.java  | 117 --------
> .../tamaya/resource/internal/Locator.java       | 150 +++++++++++
> .../tamaya/resource/internal/UrlResource.java   | 140 ----------
> 15 files changed, 671 insertions(+), 781 deletions(-)
> ----------------------------------------------------------------------
> 
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java 
> b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> index 4a1e06f..924fa7c 100644
> --- 
> a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> +++ 
> b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
> @@ -21,9 +21,8 @@ package org.apache.tamaya.format;
> import org.apache.tamaya.spi.PropertySource;
> 
> import java.io.IOException;
> -import java.io.InputStream;
> +import java.net.URL;
> import java.util.Collection;
> -import java.util.function.Supplier;
> 
> /**
>   * Implementations current this class encapsulate the mechanism how to read a
> @@ -44,12 +43,11 @@ public interface ConfigurationFormat {
>       * ladder case multiple PropertySources can be returned, each one with its 
> own ordinal and the corresponding
>       * entries.
>       *
> -     * @param sourceName name to be used for constructing a useful name for the 
> created
> -     *                   {@link org.apache.tamaya.spi.PropertySource} 
> instances.
> -     * @param streamSupplier   the resource represented by a supplier of 
> InputStream, not null
> +     * @param url the url to read the configuration data from (could be a file, 
> a remote location, a classpath
> +     *            resource or something else.
>       * @return the corresponding {@link 
> org.apache.tamaya.spi.PropertySource} instances, never {@code null}.
>       */
> -    Collection<PropertySource> readConfiguration(String sourceName, 
> Supplier<InputStream> streamSupplier)
> +    Collection<PropertySource> readConfiguration(URL url)
>              throws IOException;
> 
> }
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java 
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> index 34c9e21..a49e492 100644
> --- 
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> +++ 
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
> @@ -21,6 +21,7 @@ package org.apache.tamaya.format;
> import org.apache.tamaya.spi.PropertySource;
> 
> import java.io.InputStream;
> +import java.net.URL;
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.Collections;
> @@ -28,7 +29,6 @@ import java.util.List;
> import java.util.Map;
> import java.util.Objects;
> import java.util.Properties;
> -import java.util.function.Supplier;
> import java.util.logging.Level;
> import java.util.logging.Logger;
> 
> @@ -70,10 +70,15 @@ public class PropertiesFormat implements ConfigurationFormat 
> {
> 
>      @SuppressWarnings("unchecked")
>      @Override
> -    public Collection<PropertySource> readConfiguration(String 
> sourceName, Supplier<InputStream> streamSupplier) {
> -        final String name = "Properties(" + 
> Objects.requireNonNull(sourceName) + ')';
> +    public Collection<PropertySource> readConfiguration(URL url) {
> +        final String name;
> +        if (Objects.requireNonNull(url).getQuery() == null) {
> +            name = "Properties(" + 
> Objects.requireNonNull(url).toString() + ')';
> +        } else {
> +            name = Objects.requireNonNull(url).getQuery();
> +        }
>          List<PropertySource> propertySources = new ArrayList<>();
> -        try (InputStream is = streamSupplier.get()) {
> +        try (InputStream is = url.openStream()) {
>              if (is != null) {
>                  final Properties p = new Properties();
>                  p.load(is);
> @@ -101,7 +106,7 @@ public class PropertiesFormat implements ConfigurationFormat 
> {
>                  return propertySources;
>              }
>          } catch (Exception e) {
> -            LOG.log(Level.FINEST, e, () -> "Failed to read config from 
> resource: " + sourceName);
> +            LOG.log(Level.FINEST, e, () -> "Failed to read config from 
> resource: " + url);
>          }
>          return Collections.emptyList();
>      }
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java 
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> index 8b3468b..ddfe723 100644
> --- 
> a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> +++ 
> b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
> @@ -21,6 +21,7 @@ package org.apache.tamaya.format;
> import org.apache.tamaya.spi.PropertySource;
> 
> import java.io.InputStream;
> +import java.net.URL;
> import java.util.ArrayList;
> import java.util.Collection;
> import java.util.Collections;
> @@ -28,7 +29,6 @@ import java.util.List;
> import java.util.Map;
> import java.util.Objects;
> import java.util.Properties;
> -import java.util.function.Supplier;
> import java.util.logging.Level;
> import java.util.logging.Logger;
> 
> @@ -71,10 +71,15 @@ public class PropertiesXmlFormat implements 
> ConfigurationFormat {
> 
>      @SuppressWarnings("unchecked")
>      @Override
> -    public Collection<PropertySource> readConfiguration(String source, 
> Supplier<InputStream> streamSupplier) {
> -        final String name = "XML-Properties:" + 
> Objects.requireNonNull(source) + ')';
> +    public Collection<PropertySource> readConfiguration(URL url) {
> +        final String name;
> +        if (Objects.requireNonNull(url).getQuery() == null) {
> +            name = "XML-Properties(" + 
> Objects.requireNonNull(url).toString() + ')';
> +        } else {
> +            name = Objects.requireNonNull(url).getQuery();
> +        }
>          List<PropertySource> propertySources = new ArrayList<>();
> -        try (InputStream is = streamSupplier.get()) {
> +        try (InputStream is = url.openStream()) {
>              if (is != null) {
>                  final Properties p = new Properties();
>                  p.loadFromXML(is);
> @@ -102,7 +107,7 @@ public class PropertiesXmlFormat implements 
> ConfigurationFormat {
>                  return propertySources;
>              }
>          } catch (Exception e) {
> -            LOG.log(Level.FINEST, e, () -> "Failed to read config from 
> resource: " + source);
> +            LOG.log(Level.FINEST, e, () -> "Failed to read config from 
> resource: " + url);
>          }
>          return Collections.emptyList();
>      }
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> index c4c5651..58acba3 100644
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
> @@ -23,6 +23,7 @@ import org.apache.tamaya.spi.PropertySource;
> import org.apache.tamaya.spi.PropertySourceProvider;
> import org.apache.tamaya.spi.ServiceContext;
> 
> +import java.net.URL;
> import java.util.ArrayList;
> import java.util.Arrays;
> import java.util.Collection;
> @@ -75,13 +76,13 @@ public abstract class 
> AbstractPathBasedPropertySourceProvider implements Propert
>      public Collection<PropertySource> getPropertySources() {
>          List<PropertySource> propertySources = new ArrayList<>();
>          paths.forEach((path) -> {
> -            for (Resource res : 
> ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path)) 
> {
> +            for (URL res : 
> ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path)) 
> {
>                  try {
>                      for (ConfigurationFormat format : configFormats) {
> -                        
> propertySources.addAll(format.readConfiguration(sourceName, res));
> +                        propertySources.addAll(format.readConfiguration(res));
>                      }
>                  } catch (Exception e) {
> -                    LOG.log(Level.WARNING, "Failed to add resource based 
> config: " + res.getName(), e);
> +                    LOG.log(Level.WARNING, "Failed to add resource based 
> config: " + res, e);
>                  }
>              }
>          });
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> index 6edba5b..f1ec885 100644
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
> @@ -22,6 +22,7 @@ import org.apache.tamaya.format.ConfigurationFormat;
> import org.apache.tamaya.spi.PropertySource;
> import org.apache.tamaya.spi.PropertySourceProvider;
> 
> +import java.net.URL;
> import java.util.ArrayList;
> import java.util.Arrays;
> import java.util.Collection;
> @@ -39,25 +40,25 @@ public abstract class AbstractResourcePropertySourceProvider 
> implements Property
>      /** The supported formats. */
>      private List<ConfigurationFormat> formats = new ArrayList<>();
>      /** The resource. */
> -    private Resource resource;
> +    private URL resource;
>      /** The source name used for creating the PropertySource names. */
>      private String sourceName;
> 
>      /**
>       * Creates a new instance.
> -     * @param resource the {@link Resource}, not null.
> +     * @param resource the {@link URL}, not null.
>       * @param formats the supported formats, not empty.
>       */
> -    public AbstractResourcePropertySourceProvider(String sourceName, Resource 
> resource, ConfigurationFormat... formats) {
> +    public AbstractResourcePropertySourceProvider(String sourceName, URL 
> resource, ConfigurationFormat... formats) {
>          this(sourceName, resource, Arrays.asList(formats));
>      }
> 
>      /**
>       * Creates a new instance.
> -     * @param resource the {@link Resource}, not null.
> +     * @param resource the {@link URL}, not null.
>       * @param formats the supported formats, not empty.
>       */
> -    public AbstractResourcePropertySourceProvider(String sourceName, Resource 
> resource, List<ConfigurationFormat> formats) {
> +    public AbstractResourcePropertySourceProvider(String sourceName, URL 
> resource, List<ConfigurationFormat> formats) {
>          this.resource = Objects.requireNonNull(resource);
>          this.sourceName = Objects.requireNonNull(sourceName);
>          if(formats.size()==0){
> @@ -72,7 +73,7 @@ public abstract class AbstractResourcePropertySourceProvider 
> implements Property
>       *
>       * @return the underlying resource, never null.
>       */
> -    public Resource getResource() {
> +    public URL getResource() {
>          return this.resource;
>      }
> 
> @@ -90,9 +91,9 @@ public abstract class AbstractResourcePropertySourceProvider 
> implements Property
>          List<PropertySource> propertySources = new ArrayList<>();
>          for (ConfigurationFormat format : formats) {
>              try {
> -                propertySources.addAll(format.readConfiguration(sourceName, 
> resource));
> +                propertySources.addAll(format.readConfiguration(resource));
>              } catch (Exception e) {
> -                LOG.info(() -> "Format was not matching: " + 
> format + " for resource: " + resource.getName());
> +                LOG.info(() -> "Format was not matching: " + 
> format + " for resource: " + resource);
>              }
>          }
>          return propertySources;
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> deleted file mode 100644
> index 39e34e9..0000000
> --- a/modules/resources/src/main/java/org/apache/tamaya/resource/Resource.java
> +++ /dev/null
> @@ -1,115 +0,0 @@
> -/*
> - * 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.resource;
> -
> -import java.io.File;
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.net.URI;
> -import java.util.Objects;
> -import java.util.function.Supplier;
> -
> -/**
> - * Interface for an abstract resource. The effective resource implementation 
> can be completely arbitrary.
> - * By default files, classpath format and URLs are supported, but alternate 
> implementations are possible.
> - *
> - * @see #get()
> - * @see #toURI()
> - */
> -public interface Resource extends Supplier<InputStream> {
> -
> -    /**
> -     * Return whether this resource actually exists. Depending on the resource 
> this can delegate to
> -     * {@link java.io.File#exists()} or whatever may be appropriate to 
> check accessibility of the resource.
> -     */
> -    default boolean exists() {
> -        // Try to open a file first, if that fails try to open the stream...
> -        try {
> -            return new File(toURI()).exists();
> -        } catch (IOException ex) {
> -            // Fallback
> -            try {
> -                InputStream is = get();
> -                is.close();
> -                return true;
> -            } catch (Exception e) {
> -                // ignore, just return false for non existing
> -                return false;
> -            }
> -        }
> -    }
> -
> -    /**
> -     * Checks whether the resource is accessible, meaning {@link #get()} 
> should return a InputStream for reading the
> -     * resource's content.
> -     *
> -     * @see #get()
> -     */
> -    default boolean isAccessible() {
> -        return true;
> -    }
> -
> -    /**
> -     * Returns the resource as an URI.
> -     *
> -     * @throws IOException if the resource cannot be resolved as URI.
> -     */
> -    URI toURI() throws IOException;
> -
> -    /**
> -     * Determines the length for this resource.
> -     *
> -     * @throws IOException if the resource is not readable.
> -     */
> -    default long length() throws IOException {
> -        try(InputStream is = this.get();) {
> -            Objects.requireNonNull(is, "resource not available");
> -            long length = 0;
> -            byte[] buf = new byte[256];
> -            int bytesRead;
> -            while ((bytesRead = is.read(buf)) > 0) {
> -                length += bytesRead;
> -            }
> -            return length;
> -        }
> -    }
> -
> -    /**
> -     * Determine the last-modified timestamp for a resource, as UTC ms 
> timestamp
> -     *
> -     * @throws IOException if the resource is not accessible.
> -     */
> -    default long lastModified() throws IOException{
> -        return new File(toURI()).lastModified();
> -    }
> -
> -    /**
> -     * Get a name for the resource. The name should be identifying the resource 
> and also
> -     * never change, so it must be eligible for hashcode/equals 
> implementations.
> -     */
> -    default String getName() {
> -        try {
> -            return toURI().toString();
> -        } catch (Exception e) {
> -            return toString();
> -        }
> -    }
> -
> -
> -}
> \ No newline at end of file
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> index 7901ca6..31856cf 100644
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
> @@ -18,6 +18,7 @@
>   */
> package org.apache.tamaya.resource;
> 
> +import java.net.URL;
> import java.util.Arrays;
> import java.util.Collection;
> 
> @@ -28,16 +29,16 @@ import java.util.Collection;
> public interface ResourceResolver {
> 
>      /**
> -     * Resolves resource expressions to a list of {@link Resource}s. 
> Hereby
> +     * Resolves resource expressions to a list of {@link URL}s. Hereby
>       * the ordering of format matches the input of the resolved expressions. 
> Nevertheless be aware that
>       * there is no determined ordering of format located within a classloader.
>       *
>       * @param expressions the expressions to be resolved, not empty.
> -     * @return the corresponding collection of current {@link Resource}s 
> found, never
> +     * @return the corresponding collection of current {@link URL}s found, 
> never
>       * null.
>       * .
>       */
> -    default Collection<Resource> getResources(Collection<String> 
> expressions) {
> +    default Collection<URL> getResources(Collection<String> 
> expressions) {
>          ClassLoader cl = Thread.currentThread().getContextClassLoader();
>          if (cl == null) {
>              cl = getClass().getClassLoader();
> @@ -46,45 +47,45 @@ public interface ResourceResolver {
>      }
> 
>      /**
> -     * Resolves resource expressions to a list of {@link Resource}s. 
> Hereby
> +     * Resolves resource expressions to a list of {@link URL}s. Hereby
>       * the ordering of format matches the input of the resolved expressions. 
> Nevertheless be aware that
>       * there is no determined ordering of format located within a classloader.
>       *
>       * @param expressions the expressions to be resolved, not empty.
> -     * @return the corresponding collection of current {@link Resource}s 
> found, never
> +     * @return the corresponding collection of current {@link URL}s found, 
> never
>       * null.
>       * .
>       */
> -    default Collection<Resource> getResources(String... expressions) 
> {
> +    default Collection<URL> getResources(String... expressions) {
>          return getResources(Arrays.asList(expressions));
>      }
> 
>      /**
> -     * Resolves resource expressions to a list of {@link Resource}s, 
> considerubg
> +     * Resolves resource expressions to a list of {@link URL}s, 
> considerubg
>       * the given classloader for classloader dependent format. Hereby
>       * the ordering of format matches the input of the resolved expressions. 
> Nevertheless be aware that
>       * there is no determined ordering of format located within a classloader.
>       *
>       * @param expressions the expressions to be resolved, not empty.
> -     * @return the corresponding collection of current {@link Resource}s 
> found, never
> +     * @return the corresponding collection of current {@link URL}s found, 
> never
>       * null.
>       * .
>       */
> -    default Collection<Resource> getResources(ClassLoader classLoader, 
> String... expressions){
> +    default Collection<URL> getResources(ClassLoader classLoader, 
> String... expressions){
>          return getResources(classLoader, Arrays.asList(expressions));
>      }
> 
>      /**
> -     * Resolves resource expressions to a list of {@link Resource}s, 
> considerubg
> +     * Resolves resource expressions to a list of {@link URL}s, 
> considerubg
>       * the given classloader for classloader dependent format. Hereby
>       * the ordering of format matches the input of the resolved expressions. 
> Nevertheless be aware that
>       * there is no determined ordering of format located within a classloader.
>       *
>       * @param expressions the expressions to be resolved, not empty.
> -     * @return the corresponding collection of current {@link Resource}s 
> found, never
> +     * @return the corresponding collection of current {@link URL}s found, 
> never
>       * null.
>       * .
>       */
> -    Collection<Resource> getResources(ClassLoader classLoader, 
> Collection<String> expressions);
> +    Collection<URL> getResources(ClassLoader classLoader, 
> Collection<String> expressions);
> 
> }
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> deleted file mode 100644
> index b901164..0000000
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClassPathResource.java
> +++ /dev/null
> @@ -1,187 +0,0 @@
> -/*
> - * 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.resource.internal;
> -
> -import org.apache.tamaya.resource.Resource;
> -
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.net.URI;
> -import java.net.URISyntaxException;
> -import java.net.URL;
> -import java.util.Objects;
> -import java.util.logging.Level;
> -import java.util.logging.Logger;
> -
> -/**
> - * Implementation of {@link Resource} to be loaded from the classpath.
> - */
> -public class ClassPathResource implements Resource {
> -
> -    private static final Logger LOG = 
> Logger.getLogger(ClassPathResource.class.getName());
> -
> -    private final String path;
> -
> -    private ClassLoader classLoader;
> -
> -
> -    /**
> -     * Create a new resource using the current context class loader.
> -     *
> -     * @param path the resource path, not null
> -     * @see java.lang.ClassLoader#getResourceAsStream(String)
> -     */
> -    public ClassPathResource(String path) {
> -        this(path, (ClassLoader) null);
> -    }
> -
> -    /**
> -     * Create a new resource using the given class loader.
> -     *
> -     * @param path        the resource path, not null
> -     * @param classLoader the class loader to load the resource with,
> -     *                    or {@code null} for the current context class 
> loader
> -     * @see ClassLoader#getResourceAsStream(String)
> -     */
> -    public ClassPathResource(String path, ClassLoader classLoader) {
> -        Objects.requireNonNull(path, "Path null");
> -        if (path.startsWith("/")) {
> -            path = path.substring(1);
> -        }
> -        this.path = path.trim();
> -        if (classLoader == null) {
> -            classLoader = Thread.currentThread().getContextClassLoader();
> -        }
> -        if (classLoader == null) {
> -            classLoader = getClass().getClassLoader();
> -        }
> -        this.classLoader = classLoader;
> -    }
> -
> -    /**
> -     * @return the path for this resource.
> -     */
> -    public final String getPath() {
> -        return this.path;
> -    }
> -
> -    /**
> -     * @return the ClassLoader that this resource will be accessed from.
> -     */
> -    public final ClassLoader getClassLoader() {
> -        return this.classLoader;
> -    }
> -
> -
> -    /**
> -     * Checks if the given resource is resolvable from the configured 
> classloader.
> -     *
> -     * @see java.lang.ClassLoader#getResource(String)
> -     */
> -    @Override
> -    public boolean exists() {
> -        return (resolveURL() != null);
> -    }
> -
> -    /**
> -     * Resolves a URL for the underlying class path resource.
> -     *
> -     * @return the resolved URL, or {@code null}
> -     */
> -    protected URL resolveURL() {
> -        return this.classLoader.getResource(this.path);
> -    }
> -
> -    /**
> -     * This implementation opens an InputStream for the given class path 
> resource.
> -     *
> -     * @see java.lang.ClassLoader#getResourceAsStream(String)
> -     * @see java.lang.Class#getResourceAsStream(String)
> -     */
> -    @Override
> -    public InputStream get() {
> -        try {
> -            InputStream is = this.classLoader.getResourceAsStream(this.path);
> -            if (is == null) {
> -                throw new IOException(getName() + " does not exist");
> -            }
> -            return is;
> -        } catch (IOException e) {
> -            LOG.log(Level.INFO, "Failed to open classpath resource: " 
> + path, e);
> -            return null;
> -        }
> -    }
> -
> -    @Override
> -    public URI toURI() throws IOException {
> -        try {
> -            return resolveURL().toURI();
> -        } catch (URISyntaxException e) {
> -            throw new IOException(e);
> -        }
> -    }
> -
> -    @Override
> -    public long lastModified() throws IOException {
> -        return 0;
> -    }
> -
> -    /**
> -     * This implementation returns the name current the file that this class 
> path
> -     * resource refers to.
> -     */
> -    @Override
> -    public String getName() {
> -        return "classpath:" + path;
> -    }
> -
> -    /**
> -     * This implementation returns a description that includes the class path 
> location.
> -     */
> -    @Override
> -    public String toString() {
> -        return "ClassPathResource[" + path + ']';
> -    }
> -
> -    /**
> -     * This implementation compares the underlying class path locations.
> -     */
> -    @Override
> -    public boolean equals(Object obj) {
> -        if (obj == this) {
> -            return true;
> -        }
> -        if (obj instanceof ClassPathResource) {
> -            ClassPathResource otherRes = (ClassPathResource) obj;
> -            return (this.path.equals(otherRes.path) &&
> -                    Objects.equals(this.classLoader, otherRes.classLoader));
> -        }
> -        return false;
> -    }
> -
> -    /**
> -     * This implementation returns the hash code current the underlying
> -     * class path location.
> -     */
> -    @Override
> -    public int hashCode() {
> -        return getName().hashCode();
> -    }
> -
> -}
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> new file mode 100644
> index 0000000..3f2093b
> --- /dev/null
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
> @@ -0,0 +1,264 @@
> +/*
> + * 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.resource.internal;
> +
> +import java.io.File;
> +import java.io.IOException;
> +import java.net.JarURLConnection;
> +import java.net.MalformedURLException;
> +import java.net.URISyntaxException;
> +import java.net.URL;
> +import java.net.URLConnection;
> +import java.util.ArrayList;
> +import java.util.Collection;
> +import java.util.Enumeration;
> +import java.util.List;
> +import java.util.Objects;
> +import java.util.jar.JarEntry;
> +import java.util.jar.JarFile;
> +import java.util.logging.Level;
> +import java.util.logging.Logger;
> +
> +/**
> + * Collector that searches files based on ant styled patterns. For example the 
> following patterns would be matched:
> + * <pre>
> + *     classpath:javax/annotations/*
> + *     javax?/annotations/**/*.class
> + *     org/apache/tamaya/**/tamayaconfig.properties
> + * </pre>
> + */
> +public class ClasspathCollector {
> +
> +    /**
> +     * JAR protocol.
> +     */
> +    public static final String PROTOCOL_JAR = "jar";
> +
> +    /**
> +     * Separator between JAR file URL and the internal jar file path.
> +     */
> +    public static final String JAR_URL_SEPARATOR = "!/";
> +
> +    /**
> +     * ZIP protocol.
> +     */
> +    public static final String PROTOCOL_ZIP = "zip";
> +
> +    /**
> +     * ZIP protocol for a JBoss jar file entry: "vfszip".
> +     */
> +    public static final String PROTOCOL_VFSZIP = "vfszip";
> +
> +    /**
> +     * URL protocol for an WebSphere jar file: "wsjar".
> +     */
> +    public static final String PROTOCOL_WSJAR = "wsjar";
> +
> +    /**
> +     * URL protocol for an entry from an OC4J jar.
> +     */
> +    public static final String PROTOCOL_CODE_SOURCE = "code-source";
> +
> +    /**
> +     * The logger used.
> +     */
> +    private static final Logger LOG = 
> Logger.getLogger(ClasspathCollector.class.getName());
> +
> +    /**
> +     * The classloader used to load the resources.
> +     */
> +    private ClassLoader classLoader;
> +
> +    /**
> +     * Creates a new instance.
> +     *
> +     * @param classLoader the class loader to be used, not null.
> +     */
> +    public ClasspathCollector(ClassLoader classLoader) {
> +        this.classLoader = Objects.requireNonNull(classLoader);
> +    }
> +
> +    /**
> +     * Collect all classpath resources given the expression.
> +     *
> +     * @param expression the expression, not null.
> +     * @return the resources found.
> +     */
> +    public Collection<URL> collectFiles(String expression) {
> +        if (expression.startsWith("classpath:")) {
> +            expression = expression.substring("classpath:".length());
> +        }
> +        if (expression.startsWith("/")) {
> +            expression = expression.substring(1);
> +        }
> +        Locator locator = Locator.of(expression);
> +        List<URL> result = new ArrayList<>();
> +        String rootPath = locator.getRootPath();
> +        try {
> +            Enumeration<URL> rootResources = 
> this.classLoader.getResources(rootPath);
> +            while (rootResources.hasMoreElements()) {
> +                URL resource = rootResources.nextElement();
> +                try {
> +                    if (isJarFile(resource)) {
> +                        result.addAll(doFindPathMatchingJarResources(resource, 
> locator.getSubPath()));
> +                    } else {
> +                        File file = getFile(resource);
> +                        
> result.addAll(FileCollector.traverseAndSelectFromChildren(file, 
> locator.getSubPathTokens(), 0));
> +                    }
> +                } catch (Exception e) {
> +                    LOG.log(Level.SEVERE, "Error locating resources for: 
> " + expression, e);
> +                }
> +            }
> +        } catch (IOException e) {
> +            LOG.log(Level.SEVERE, "Error locating resources for: " + 
> expression, e);
> +        }
> +        return result;
> +    }
> +
> +
> +    /**
> +     * Find all resources in jar files that match the given location pattern
> +     * via the Ant-style PathMatcher.
> +     *
> +     * @param rootDirResource the root directory as Resource
> +     * @param subPattern      the sub pattern to match (below the root 
> directory)
> +     * @return the Set of matching Resource instances
> +     * @throws java.io.IOException in case of I/O errors
> +     * @see java.net.JarURLConnection
> +     */
> +    protected Collection<URL> doFindPathMatchingJarResources(URL 
> rootDirResource, String subPattern)
> +            throws IOException, URISyntaxException {
> +        subPattern = subPattern.replace("*", 
> ".*").replace("?", ".?").replace(".*.*", 
> ".*");
> +        URLConnection con = rootDirResource.toURI().toURL().openConnection();
> +        JarFile jarFile;
> +        boolean newJarFile = false;
> +        String jarFileUrl;
> +        String rootEntryPath;
> +
> +        if (con instanceof JarURLConnection) {
> +            // Should usually be the case for traditional JAR files.
> +            JarURLConnection jarCon = (JarURLConnection) con;
> +            jarCon.setUseCaches(false);
> +            jarFile = jarCon.getJarFile();
> +            jarFileUrl = jarCon.getJarFileURL().toExternalForm();
> +            JarEntry jarEntry = jarCon.getJarEntry();
> +            rootEntryPath = (jarEntry != null ? jarEntry.getName() : 
> "");
> +        } else {
> +            // No JarURLConnection -> need to resort to URL file parsing.
> +            // We'll assume URLs of the format "jar:path!/entry", 
> with the protocol
> +            // being arbitrary as long as following the entry format.
> +            // We'll also handle paths with and without leading 
> "file:" prefix.
> +            String urlFile = rootDirResource.toURI().toURL().getFile();
> +            int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
> +            jarFileUrl = urlFile.substring(0, separatorIndex);
> +            if (jarFileUrl.startsWith("file:")) {
> +                jarFileUrl = jarFileUrl.substring("file:".length());
> +            }
> +            jarFile = new JarFile(jarFileUrl);
> +            newJarFile = true;
> +            jarFileUrl = "file:" + jarFileUrl;
> +            rootEntryPath = urlFile.substring(separatorIndex + 
> JAR_URL_SEPARATOR.length());
> +        }
> +
> +        try {
> +            if (LOG.isLoggable(Level.FINEST)) {
> +                LOG.finest("Looking for matching resources in jar file 
> [" + jarFileUrl + "]");
> +            }
> +            if (!rootEntryPath.isEmpty() && 
> !rootEntryPath.endsWith("/")) {
> +                // Root entry path must end with slash for correct matching
> +                rootEntryPath = rootEntryPath + '/';
> +            }
> +            Collection<URL> result = new ArrayList<>(10);
> +            for (Enumeration entries = jarFile.entries(); 
> entries.hasMoreElements(); ) {
> +                JarEntry entry = (JarEntry) entries.nextElement();
> +                String entryPath = entry.getName();
> +                if (entryPath.startsWith(rootEntryPath)) {
> +                    String relativePath = 
> entryPath.substring(rootEntryPath.length());
> +                    if (relativePath.matches(subPattern)) {
> +                        result.add(createRelativeFrom(rootDirResource, 
> relativePath));
> +                    }
> +                }
> +            }
> +            return result;
> +        } finally {
> +            // Close jar file, but only if freshly obtained -
> +            // not from JarURLConnection, which might cache the file reference.
> +            if (newJarFile) {
> +                jarFile.close();
> +            }
> +        }
> +    }
> +
> +    /**
> +     * Creates a new URL based on the given root path and the relative path to 
> be added.
> +     *
> +     * @param url          the root, not null
> +     * @param relativePath the relative path to be added, not null
> +     * @return the new URL instance
> +     * @throws MalformedURLException
> +     */
> +    private URL createRelativeFrom(URL url, String relativePath)
> +            throws MalformedURLException {
> +        String rootDirResource = url.toExternalForm();
> +        if (relativePath.startsWith("/")) {
> +            relativePath = relativePath.substring(1);
> +        }
> +        if (!rootDirResource.endsWith("/")) {
> +            rootDirResource = rootDirResource + '/';
> +        }
> +        return new URL(rootDirResource + relativePath);
> +    }
> +
> +
> +    /**
> +     * Small check if a given URL is a jar file URL.
> +     *
> +     * @param url the URL to check, not null.
> +     * @return true if the URL has one of the following protocols: jar, zip, 
> vfszip, wsjar, code-source.
> +     */
> +    private boolean isJarFile(URL url) {
> +        String protocol = Objects.requireNonNull(url).getProtocol();
> +        return (PROTOCOL_JAR.equals(protocol) ||
> +                PROTOCOL_ZIP.equals(protocol) ||
> +                PROTOCOL_VFSZIP.equals(protocol) ||
> +                PROTOCOL_WSJAR.equals(protocol) ||
> +                (PROTOCOL_CODE_SOURCE.equals(protocol) && 
> url.getPath().indexOf(JAR_URL_SEPARATOR) != -1));
> +    }
> +
> +    /**
> +     * Creates a file from an URL.
> +     *
> +     * @param resourceUrl the url, not null.
> +     * @return a new file instance. The instance still may not exist. if the 
> url's protocol is not 'file', {@code null}
> +     * is returned.
> +     */
> +    private File getFile(URL resourceUrl) {
> +        Objects.requireNonNull(resourceUrl, "Resource URL must not be 
> null");
> +        if (!"file".equals(resourceUrl.getProtocol())) {
> +            return null;
> +        }
> +        try {
> +            return new File(resourceUrl.toURI().getSchemeSpecificPart());
> +        } catch (Exception ex) {
> +            // Fallback for URLs that are not valid URIs (should hardly ever 
> happen).
> +            return new File(resourceUrl.getFile());
> +        }
> +    }
> +
> +}
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> index 9fd6fc4..c90e53a 100644
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
> @@ -18,7 +18,6 @@
>   */
> package org.apache.tamaya.resource.internal;
> 
> -import org.apache.tamaya.resource.Resource;
> import org.apache.tamaya.resource.ResourceResolver;
> 
> import javax.annotation.Priority;
> @@ -39,10 +38,10 @@ public class DefaultResourceResolver implements 
> ResourceResolver {
>      private static final Logger LOG = 
> Logger.getLogger(DefaultResourceResolver.class.getName());
> 
>      @Override
> -    public List<Resource> getResources(ClassLoader classLoader, 
> Collection<String> expressions) {
> -        List<Resource> resources = new ArrayList<>();
> +    public List<URL> getResources(ClassLoader classLoader, 
> Collection<String> expressions) {
> +        List<URL> resources = new ArrayList<>();
>          for (String expression : expressions) {
> -            if (tryClassPath(classLoader, expression, resources) || 
> tryFile(expression, resources) ||
> +            if (tryPath(classLoader, expression, resources) || 
> tryClassPath(classLoader, expression, resources) || tryFile(expression, 
> resources) ||
>                      tryURL(expression, resources)) {
>                  continue;
>              }
> @@ -51,12 +50,41 @@ public class DefaultResourceResolver implements 
> ResourceResolver {
>          return resources;
>      }
> 
> -    private boolean tryClassPath(ClassLoader classLoader, String expression, 
> List<Resource> resources) {
> +    /**
> +     * Tries to evaluate the location passed by Ant path matching.
> +     * @param classLoader the class loader to use
> +     * @param expression the path expression
> +     * @param resources the resources for adding the results
> +     * @return true, if the expression could be resolved.
> +     */
> +    private boolean tryPath(ClassLoader classLoader, String expression, 
> List<URL> resources) {
> +        try {
> +            // 1: try file path
> +            Collection<URL> found = 
> FileCollector.collectFiles(expression);
> +            if (found.isEmpty()) {
> +                found = new 
> ClasspathCollector(classLoader).collectFiles(expression);
> +            }
> +            resources.addAll(found);
> +            return !found.isEmpty();
> +        } catch (Exception e) {
> +            LOG.finest(() -> "Failed to load resource from CP: " + 
> expression);
> +        }
> +        return false;
> +    }
> +
> +    /**
> +     * Tries to evaluate the location passed by loading from the classloader.
> +     * @param classLoader the class loader to use
> +     * @param expression the path expression
> +     * @param resources the resources for adding the results
> +     * @return true, if the expression could be resolved.
> +     */
> +    private boolean tryClassPath(ClassLoader classLoader, String expression, 
> List<URL> resources) {
>          try {
>              Enumeration<URL> urls = classLoader.getResources(expression);
>              while (urls.hasMoreElements()) {
>                  URL url = urls.nextElement();
> -                resources.add(new UrlResource(url));
> +                resources.add(url);
>              }
>              return !resources.isEmpty();
>          } catch (Exception e) {
> @@ -65,11 +93,17 @@ public class DefaultResourceResolver implements 
> ResourceResolver {
>          return false;
>      }
> 
> -    private boolean tryFile(String expression, List<Resource> resources) 
> {
> +    /**
> +     * Tries to evaluate the location passed by lokking up a file.
> +     * @param expression the path expression
> +     * @param resources the resources for adding the results
> +     * @return true, if the expression could be resolved.
> +     */
> +    private boolean tryFile(String expression, List<URL> resources) 
> {
>          try {
>              File file = new File(expression);
>              if (file.exists()) {
> -                resources.add(new FileResource(file));
> +                resources.add(file.toURI().toURL());
>                  return true;
>              }
>          } catch (Exception e) {
> @@ -78,16 +112,21 @@ public class DefaultResourceResolver implements 
> ResourceResolver {
>          return false;
>      }
> 
> -    private boolean tryURL(String expression, List<Resource> resources) 
> {
> +    /**
> +     * Tries to interpret the expression as URL.
> +     * @param expression the path expression
> +     * @param resources the resources for adding the results
> +     * @return true, if the expression could be resolved.
> +     */
> +    private boolean tryURL(String expression, List<URL> resources) {
>          try {
>              URL url = new URL(expression);
> -            resources.add(new UrlResource(url));
> +            resources.add(url);
>              return true;
>          } catch (Exception e) {
>              LOG.finest(() -> "Failed to load resource from file: " 
> + expression);
>          }
>          return false;
> -
>      }
> 
> }
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> new file mode 100644
> index 0000000..d506e11
> --- /dev/null
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
> @@ -0,0 +1,157 @@
> +/*
> + * 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.resource.internal;
> +
> +import java.io.File;
> +import java.net.URL;
> +import java.util.ArrayList;
> +import java.util.Collection;
> +import java.util.Collections;
> +import java.util.List;
> +import java.util.Objects;
> +import java.util.logging.Logger;
> +
> +/**
> + * Collector that searches files based on ant styled patterns. For example the 
> following patterns would be matched:
> + * <pre>
> + *     file:C:/temp/*.txt
> + *     file:C:\**\*.ini
> + *     C:\Programs\**/*.ini
> + *     /user/home/A*b101_?.pid
> + *     /var/logs/**/*.log
> + * </pre>
> + */
> +public class FileCollector {
> +
> +    public static final String FILE_PREFIX = "file:";
> +
> +    private FileCollector() {
> +    }
> +
> +    private static final Logger LOG = 
> Logger.getLogger(FileCollector.class.getName());
> +
> +    public static Collection<URL> collectFiles(String expression) {
> +        expression = expression.replace("\\", "/");
> +        Locator locator = Locator.of(expression);
> +        List<URL> result = new ArrayList<>();
> +        String rootPath = locator.getRootPath();
> +        if (rootPath.startsWith(FILE_PREFIX)) {
> +            rootPath = rootPath.substring(FILE_PREFIX.length());
> +        }
> +        File file = new File(rootPath);
> +        if (file.exists()) {
> +            List<String> subTokens = locator.getSubPathTokens();
> +            result.addAll(traverseAndSelectFromChildren(file, subTokens, 0));
> +        }
> +        return result;
> +    }
> +
> +    static Collection<URL> traverseAndSelectFromChildren(File dir, 
> List<String> subTokens, int tokenIndex) {
> +        if (tokenIndex >= subTokens.size() || dir.isFile()) {
> +            return Collections.emptyList();
> +        }
> +        List<URL> result = new ArrayList<>();
> +        String token = subTokens.get(tokenIndex);
> +        if (token.equals("**")) {
> +            result.addAll(traverseAndSelectFromChildren(dir, 
> getSubExpression(subTokens, tokenIndex + 1)));
> +        } else {
> +            token = token.replace("*", ".*");
> +            File[] files = dir.listFiles();
> +            if (tokenIndex == subTokens.size() - 1) {
> +                // select files!
> +                for (File f : files) {
> +                    if (f.isFile() && f.getName().matches(token)) 
> {
> +                        result.add(getURL(f));
> +                    }
> +                }
> +            } else {
> +                // check directory pattern
> +                for (File f : files) {
> +                    if (f.isDirectory() && f.getName().matches(token)) 
> {
> +                        result.addAll(traverseAndSelectFromChildren(f, 
> subTokens, tokenIndex + 1));
> +                    }
> +                }
> +            }
> +        }
> +        return result;
> +    }
> +
> +    static Collection<URL> traverseAndSelectFromChildren(File file, 
> String subExpression) {
> +        List<URL> result = new ArrayList<>();
> +        for (File childFile : file.listFiles()) {
> +            if (childFile.isFile()) {
> +                if (childFile.getName().matches(subExpression)) {
> +                    try {
> +                        result.add(getURL(childFile));
> +                    } catch (Exception e) {
> +                        LOG.warning(() -> "File not convertible to URL: 
> " + childFile);
> +                    }
> +                }
> +            } else if (childFile.isDirectory()) {
> +                result.addAll(traverseAndSelectFromChildren(childFile, 
> subExpression));
> +            }
> +        }
> +        return result;
> +    }
> +
> +    private static boolean matchesFile(File childFile, List<String> 
> subTokens, int tokenIndex) {
> +        if (tokenIndex < (subTokens.size() - 1)) {
> +            // not all tokens consumed, so no match!
> +            return false;
> +        }
> +        String tokenToMatch = subTokens.get(tokenIndex);
> +        tokenToMatch = tokenToMatch.replace("*", ".*");
> +        return childFile.getName().matches(tokenToMatch);
> +    }
> +
> +    /**
> +     * Get an URL from a file.
> +     *
> +     * @param file the file, not null.
> +     * @return the URL, never null.
> +     * @throws java.lang.IllegalStateException if it fails to create the URL
> +     */
> +    private static URL getURL(File file) {
> +        Objects.requireNonNull(file);
> +        try {
> +            return file.toURI().toURL();
> +        } catch (Exception e) {
> +            throw new IllegalStateException("Failed to create URL from 
> file: " + file);
> +        }
> +    }
> +
> +    /**
> +     * Constructs a sub expression, using the tokens from {@code 
> subTokens} starting at index {@code startIndex}.
> +     *
> +     * @param subTokens  the token list, not null
> +     * @param startIndex the start index from where tokens should be taken to 
> produce the path.
> +     * @return the constructed path, never null.
> +     */
> +    private static String getSubExpression(List<String> subTokens, int 
> startIndex) {
> +        StringBuilder b = new StringBuilder();
> +        for (int i = startIndex; i < subTokens.size(); i++) {
> +            b.append(subTokens.get(i));
> +            b.append('/');
> +        }
> +        if (b.length() > 0) {
> +            b.setLength(b.length() - 1);
> +        }
> +        return b.toString().replaceAll("\\*", 
> ".*").replaceAll("\\?", ".?");
> +    }
> +}
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> deleted file mode 100644
> index c5f521a..0000000
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileResource.java
> +++ /dev/null
> @@ -1,172 +0,0 @@
> -/*
> - * 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.resource.internal;
> -
> -import org.apache.tamaya.resource.Resource;
> -
> -import java.io.File;
> -import java.io.FileInputStream;
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.net.URI;
> -import java.util.Objects;
> -import java.util.logging.Level;
> -import java.util.logging.Logger;
> -
> -/**
> - * Implementation of {@link Resource} to be loaded from a file.
> - *
> - * @see java.io.File
> - */
> -public class FileResource implements Resource {
> -
> -    private static final Logger LOG = 
> Logger.getLogger(FileResource.class.getName());
> -
> -    private final File file;
> -
> -    /**
> -     * Creates a new instance.
> -     *
> -     * @param file a File, not null.
> -     */
> -    public FileResource(File file) {
> -        this.file = Objects.requireNonNull(file, "File must not be 
> null");
> -    }
> -
> -    /**
> -     * Crreates a new instance.
> -     *
> -     * @param filePath a file path
> -     */
> -    public FileResource(String filePath) {
> -        Objects.requireNonNull(filePath, "Path must not be null");
> -        this.file = new File(filePath);
> -    }
> -
> -
> -    /**
> -     * Get the file path for this resource.
> -     */
> -    public final String getPath() {
> -        return this.file.getPath();
> -    }
> -
> -
> -    /**
> -     * This implementation returns whether the underlying file exists.
> -     *
> -     * @see java.io.File#exists()
> -     */
> -    @Override
> -    public boolean exists() {
> -        return this.file.exists();
> -    }
> -
> -    /**
> -     * This implementation checks whether the underlying file is marked as 
> readable
> -     * (and corresponds to an actual file with content, not to a directory).
> -     *
> -     * @see java.io.File#canRead()
> -     * @see java.io.File#isDirectory()
> -     */
> -    @Override
> -    public boolean isAccessible() {
> -        return (this.file.canRead() && !this.file.isDirectory());
> -    }
> -
> -    /**
> -     * This implementation opens a FileInputStream for the underlying file.
> -     *
> -     * @see java.io.FileInputStream
> -     */
> -    @Override
> -    public InputStream get() {
> -        try {
> -            return new FileInputStream(this.file);
> -        } catch (Exception e) {
> -            LOG.log(Level.INFO, "Failed to open file: " + 
> file.getAbsolutePath(), e);
> -            return null;
> -        }
> -    }
> -
> -    /**
> -     * This implementation returns a URI for the underlying file.
> -     *
> -     * @see java.io.File#toURI()
> -     */
> -    @Override
> -    public URI toURI() throws IOException {
> -        return this.file.toURI();
> -    }
> -
> -    /**
> -     * Returns the underlying File's length.
> -     */
> -    @Override
> -    public long length() throws IOException {
> -        return this.file.length();
> -    }
> -
> -    @Override
> -    public long lastModified() throws IOException {
> -        return file.lastModified();
> -    }
> -
> -    /**
> -     * Returns the name of the current file.
> -     *
> -     * @see java.io.File#getName()
> -     */
> -    @Override
> -    public String getName() {
> -        return this.file.getName();
> -    }
> -
> -    /**
> -     * Returns a description that includes the absolute
> -     * path of the current file.
> -     *
> -     * @see java.io.File#getAbsolutePath()
> -     */
> -    @Override
> -    public String toString() {
> -        return "File [" + this.file.getAbsolutePath() + 
> "]";
> -    }
> -
> -
> -    // implementation current WritableResource
> -
> -    /**
> -     * Compares the underlying Files.
> -     */
> -    @Override
> -    public boolean equals(Object obj) {
> -        return (obj == this ||
> -                (obj instanceof FileResource && 
> this.file.equals(((FileResource) obj).file)));
> -    }
> -
> -    /**
> -     * Returns hash code current the underlying File reference.
> -     */
> -    @Override
> -    public int hashCode() {
> -        return this.file.hashCode();
> -    }
> -
> -}
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> deleted file mode 100644
> index d4aa673..0000000
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/InputStreamResource.java
> +++ /dev/null
> @@ -1,117 +0,0 @@
> -/*
> - * 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.resource.internal;
> -
> -import org.apache.tamaya.resource.Resource;
> -
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.net.URI;
> -import java.util.Objects;
> -
> -/**
> - * Simple Resource encapsulating an InputStream.
> - */
> -public class InputStreamResource implements Resource {
> -
> -    /** The InputStream. */
> -    private final InputStream inputStream;
> -    /** The read flag. */
> -    private boolean read = false;
> -    /** The name of the resource. */
> -    private String name;
> -
> -
> -    /**
> -     * Create a new InputStreamResource.
> -     *
> -     * @param inputStream the InputStream to use
> -     */
> -    public InputStreamResource(InputStream inputStream) {
> -        this(inputStream, "InputStream:");
> -    }
> -
> -    /**
> -     * Create a new InputStreamResource.
> -     *
> -     * @param inputStream the InputStream to use
> -     * @param name where the InputStream comes from
> -     */
> -    public InputStreamResource(InputStream inputStream, String name) {
> -        this.inputStream = Objects.requireNonNull(inputStream);
> -        this.name = (name != null ? name : "InputStream");
> -    }
> -
> -
> -    /**
> -     * This implementation always returns {@code true}.
> -     */
> -    @Override
> -    public boolean exists() {
> -        return true;
> -    }
> -
> -    @Override
> -    public URI toURI() throws IOException {
> -        throw new IOException("URI not available.");
> -    }
> -
> -    @Override
> -    public long lastModified() throws IOException {
> -        throw new IOException("lastModified not available.");
> -    }
> -
> -    /**
> -     * Accesses the input stream. Hereby the input stream can only accessed 
> once.
> -     */
> -    @Override
> -    public InputStream get() {
> -        if (this.read) {
> -            throw new IllegalStateException("InputStream can only be read 
> once!");
> -        }
> -        this.read = true;
> -        return this.inputStream;
> -    }
> -
> -    /**
> -     * This implementation returns the passed-in description, if any.
> -     */
> -    public String toString() {
> -        return this.name != null ? this.name : super.toString();
> -    }
> -
> -
> -    /**
> -     * Compares the underlying InputStream.
> -     */
> -    @Override
> -    public boolean equals(Object obj) {
> -        return (obj == this ||
> -                (obj instanceof InputStreamResource && 
> ((InputStreamResource) obj).inputStream.equals(this.inputStream)));
> -    }
> -
> -    /**
> -     * This implementation returns the hash code current the underlying 
> InputStream.
> -     */
> -    @Override
> -    public int hashCode() {
> -        return this.inputStream.hashCode();
> -    }
> -
> -}
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> new file mode 100644
> index 0000000..8d9e08a
> --- /dev/null
> +++ 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
> @@ -0,0 +1,150 @@
> +/*
> + * 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.resource.internal;
> +
> +import java.util.ArrayList;
> +import java.util.Arrays;
> +import java.util.List;
> +import java.util.stream.Collectors;
> +
> +/**
> + * Small helper class that manages the path parts of a location expression.
> + */
> +final class Locator {
> +    /**
> +     * The tokenized location expression.
> +     */
> +    private List<String> tokens;
> +
> +    /**
> +     * Creates a new instances based on the tokenized expression.
> +     *
> +     * @param tokens the tokenized expression, not null.
> +     */
> +    Locator(List<String> tokens) {
> +        this.tokens = tokens;
> +    }
> +
> +    /**
> +     * Creates a new instance of the corresponding expression.
> +     *
> +     * @param expression the location expression, not null.
> +     * @return the tokenized instance.
> +     */
> +    public static Locator of(String expression) {
> +        return new 
> Locator(Arrays.asList(expression.split("/")).stream().filter((s) -> 
> !s.isEmpty()).collect(Collectors.toList()));
> +    }
> +
> +    /**
> +     * Access the root path, which is the location expression, before any 
> wildcards or placeholders are used.
> +     * It is used as the entry point into the file system or for accessing base 
> classpath resources, before
> +     * further analysis on the file or jar filesystem can be performed.
> +     *
> +     * @return the root path, never null.
> +     */
> +    public String getRootPath() {
> +        StringBuilder builder = new StringBuilder();
> +        for (String token : tokens) {
> +            if (containsPlaceholder(token)) {
> +                break;
> +            } else {
> +                builder.append(token);
> +                builder.append('/');
> +            }
> +        }
> +        if (builder.length() > 0) {
> +            builder.setLength(builder.length() - 1);
> +        }
> +        return builder.toString();
> +    }
> +
> +    /**
> +     * Return the sub expression path, which contains the second part of the 
> expression, starting with a placeholder
> +     * or wildcard token.
> +     *
> +     * @return the sub expression part, never null.
> +     */
> +    public String getSubPath() {
> +        StringBuilder builder = new StringBuilder();
> +        for (String token : getSubPathTokens()) {
> +            builder.append(token);
> +            builder.append('/');
> +        }
> +        if (builder.length() > 0) {
> +            builder.setLength(builder.length() - 1);
> +        }
> +        return builder.toString();
> +    }
> +
> +    /**
> +     * This method returns the single tokenized form of the sub expression.
> +     *
> +     * @return the tokenized version of the sub path.
> +     * @see #getSubPath()
> +     */
> +    public List<String> getSubPathTokens() {
> +        List<String> subTokens = new ArrayList<>();
> +        for (String token : tokens) {
> +            if (!containsPlaceholder(token)) {
> +                continue;
> +            } else {
> +                subTokens.add(token);
> +            }
> +        }
> +        return subTokens;
> +    }
> +
> +    /**
> +     * Access the full reconstructed path. In most cases this should match the 
> original expression.
> +     *
> +     * @return the full expression path, never null.
> +     */
> +    public String getPath() {
> +        StringBuilder builder = new StringBuilder();
> +        for (String token : tokens) {
> +            builder.append(token);
> +            builder.append('/');
> +        }
> +        if (builder.length() > 0) {
> +            builder.setLength(builder.length() - 1);
> +        }
> +        return builder.toString();
> +    }
> +
> +    /**
> +     * Short method that checks for '*' and '?' chars.
> +     *
> +     * @param token the token to check, not null
> +     * @return true, if it contains wildcard characters.
> +     */
> +    private boolean containsPlaceholder(String token) {
> +        return token.contains("*") || token.contains("?");
> +    }
> +
> +    /**
> +     * Return the expressions' path.
> +     *
> +     * @return the locator path.
> +     */
> +    @Override
> +    public String toString() {
> +        return "Locator: " + getPath();
> +    }
> +
> +}
> 
> http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/ae66299e/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> ----------------------------------------------------------------------
> diff --git 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java 
> b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> deleted file mode 100644
> index 6522cf5..0000000
> --- 
> a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/UrlResource.java
> +++ /dev/null
> @@ -1,140 +0,0 @@
> -/*
> - * 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.resource.internal;
> -
> -import org.apache.tamaya.resource.Resource;
> -
> -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;
> -import java.util.logging.Level;
> -import java.util.logging.Logger;
> -
> -/**
> - * Implementation of a resource based on a {@code java.net.URL}.
> - */
> -public class UrlResource implements Resource {
> -
> -    private static final Logger LOG = 
> Logger.getLogger(UrlResource.class.getName());
> -
> -    /**
> -     * Original URL, used for actual access.
> -     */
> -    private final URL url;
> -
> -    /**
> -     * Create a new instance based on the given URL.
> -     *
> -     * @param url a URL
> -     */
> -    public UrlResource(URL url) {
> -        this.url = Objects.requireNonNull(url, "URL null");
> -    }
> -
> -    /**
> -     * Create a new URLResource based on a URL path.
> -     *
> -     * @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.url = new URL(path);
> -    }
> -
> -
> -    /**
> -     * This implementation opens an InputStream for the given URL.
> -     *
> -     * @see java.net.URL#openConnection()
> -     * @see java.net.URLConnection#setUseCaches(boolean)
> -     * @see java.net.URLConnection#getInputStream()
> -     */
> -    @Override
> -    public InputStream get() {
> -        URLConnection con = null;
> -        try {
> -            con = this.url.openConnection();
> -            useCachesIfNecessary(con);
> -            return con.getInputStream();
> -        } catch (IOException e) {
> -            if (con instanceof HttpURLConnection) {
> -                ((HttpURLConnection) con).disconnect();
> -            }
> -            LOG.log(Level.INFO, "Failed to open URL: " + url, e);
> -            return null;
> -        }
> -    }
> -
> -    @Override
> -    public URI toURI() throws IOException {
> -        try {
> -            return this.url.toURI();
> -        } catch (URISyntaxException e) {
> -            throw new IOException("Failed to create URI from " + 
> url);
> -        }
> -    }
> -
> -    @Override
> -    public String getName() {
> -        return this.url.toString();
> -    }
> -
> -    @Override
> -    public String toString() {
> -        return "URL [" + this.url + "]";
> -    }
> -
> -    /**
> -     * Compares the underlying URL references.
> -     */
> -    @Override
> -    public boolean equals(Object obj) {
> -        return (obj == this ||
> -                (obj instanceof UrlResource && 
> this.url.equals(((UrlResource) obj).url)));
> -    }
> -
> -    /**
> -     * This implementation returns the hash code current the underlying URL 
> reference.
> -     */
> -    @Override
> -    public int hashCode() {
> -        return this.url.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 format.
> -     *
> -     * @param con the URLConnection to set the flag on
> -     */
> -    private void useCachesIfNecessary(URLConnection con) {
> -        
> con.setUseCaches(con.getClass().getSimpleName().startsWith("JNLP"));
> -    }
> -
> -}
> -
> 

[4/6] incubator-tamaya git commit: TAMAYA-43: Added missing Javadocs.

Posted by an...@apache.org.
TAMAYA-43: Added missing Javadocs.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/202e9ac3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/202e9ac3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/202e9ac3

Branch: refs/heads/master
Commit: 202e9ac3a705676ad9fd358b58ef88a2705f12f9
Parents: 842b33e
Author: anatole <an...@apache.org>
Authored: Thu Jan 8 04:29:51 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Jan 11 01:40:59 2015 +0100

----------------------------------------------------------------------
 .../resource/internal/ClasspathCollector.java   | 29 +++++++------
 .../tamaya/resource/internal/FileCollector.java | 44 ++++++++++++++++----
 2 files changed, 53 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/202e9ac3/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
index 3f2093b..6124dca 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
@@ -48,37 +48,42 @@ public class ClasspathCollector {
     /**
      * JAR protocol.
      */
-    public static final String PROTOCOL_JAR = "jar";
+    private static final String PROTOCOL_JAR = "jar";
 
     /**
      * Separator between JAR file URL and the internal jar file path.
      */
-    public static final String JAR_URL_SEPARATOR = "!/";
+    private static final String JAR_URL_SEPARATOR = "!/";
 
     /**
      * ZIP protocol.
      */
-    public static final String PROTOCOL_ZIP = "zip";
+    private static final String PROTOCOL_ZIP = "zip";
 
     /**
      * ZIP protocol for a JBoss jar file entry: "vfszip".
      */
-    public static final String PROTOCOL_VFSZIP = "vfszip";
+    private static final String PROTOCOL_VFSZIP = "vfszip";
 
     /**
      * URL protocol for an WebSphere jar file: "wsjar".
      */
-    public static final String PROTOCOL_WSJAR = "wsjar";
+    private static final String PROTOCOL_WSJAR = "wsjar";
 
     /**
      * URL protocol for an entry from an OC4J jar.
      */
-    public static final String PROTOCOL_CODE_SOURCE = "code-source";
+    private static final String PROTOCOL_CODE_SOURCE = "code-source";
 
     /**
      * The logger used.
      */
     private static final Logger LOG = Logger.getLogger(ClasspathCollector.class.getName());
+    
+    /**
+     * Prefix used for explicitly selecting this collector.
+     */
+    public static final String CLASSPATH_PREFIX = "classpath:";
 
     /**
      * The classloader used to load the resources.
@@ -101,25 +106,24 @@ public class ClasspathCollector {
      * @return the resources found.
      */
     public Collection<URL> collectFiles(String expression) {
-        if (expression.startsWith("classpath:")) {
-            expression = expression.substring("classpath:".length());
+        if (expression.startsWith(CLASSPATH_PREFIX)) {
+            expression = expression.substring(CLASSPATH_PREFIX.length());
         }
         if (expression.startsWith("/")) {
             expression = expression.substring(1);
         }
         Locator locator = Locator.of(expression);
         List<URL> result = new ArrayList<>();
-        String rootPath = locator.getRootPath();
         try {
-            Enumeration<URL> rootResources = this.classLoader.getResources(rootPath);
+            Enumeration<URL> rootResources = this.classLoader.getResources(locator.getRootPath());
             while (rootResources.hasMoreElements()) {
                 URL resource = rootResources.nextElement();
                 try {
                     if (isJarFile(resource)) {
                         result.addAll(doFindPathMatchingJarResources(resource, locator.getSubPath()));
                     } else {
-                        File file = getFile(resource);
-                        result.addAll(FileCollector.traverseAndSelectFromChildren(file, locator.getSubPathTokens(), 0));
+                        result.addAll(FileCollector.traverseAndSelectFromChildren(getFile(resource),
+                                locator.getSubPathTokens(), 0));
                     }
                 } catch (Exception e) {
                     LOG.log(Level.SEVERE, "Error locating resources for: " + expression, e);
@@ -152,7 +156,6 @@ public class ClasspathCollector {
         String rootEntryPath;
 
         if (con instanceof JarURLConnection) {
-            // Should usually be the case for traditional JAR files.
             JarURLConnection jarCon = (JarURLConnection) con;
             jarCon.setUseCaches(false);
             jarFile = jarCon.getJarFile();

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/202e9ac3/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
index d506e11..0dcad83 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
@@ -38,14 +38,23 @@ import java.util.logging.Logger;
  * </pre>
  */
 public class FileCollector {
-
+    /** The prefix used to explicitly select this collector. */
     public static final String FILE_PREFIX = "file:";
 
+    /** The logger instance. */
+    private static final Logger LOG = Logger.getLogger(FileCollector.class.getName());
+
+    /**
+     * private constructor.
+     */
     private FileCollector() {
     }
 
-    private static final Logger LOG = Logger.getLogger(FileCollector.class.getName());
-
+    /**
+     * Collects the files given the expression.
+     * @param expression the expression in Ant-styled format, not null.
+     * @return the URLs found.
+     */
     public static Collection<URL> collectFiles(String expression) {
         expression = expression.replace("\\", "/");
         Locator locator = Locator.of(expression);
@@ -62,6 +71,14 @@ public class FileCollector {
         return result;
     }
 
+    /**
+     * Internal method to traverse the file system down, hereby comparing the new path elements with the
+     * elements given by {@code subTokens}, starting at the given {@code tokenIndex}.
+     * @param dir the directory to start
+     * @param subTokens the overall subtoken to be analyzed
+     * @param tokenIndex the index where in the token list to start comparing
+     * @return the URLs matching the tokens
+     */
     static Collection<URL> traverseAndSelectFromChildren(File dir, List<String> subTokens, int tokenIndex) {
         if (tokenIndex >= subTokens.size() || dir.isFile()) {
             return Collections.emptyList();
@@ -92,11 +109,17 @@ public class FileCollector {
         return result;
     }
 
-    static Collection<URL> traverseAndSelectFromChildren(File file, String subExpression) {
+    /**
+     * Internal method to traverse the file system and comparing all child file names with the given expression.
+     * @param file the root directory
+     * @param expression the regular expression to match
+     * @return the URLs matching the expression
+     */
+    static Collection<URL> traverseAndSelectFromChildren(File file, String expression) {
         List<URL> result = new ArrayList<>();
         for (File childFile : file.listFiles()) {
             if (childFile.isFile()) {
-                if (childFile.getName().matches(subExpression)) {
+                if (childFile.getName().matches(expression)) {
                     try {
                         result.add(getURL(childFile));
                     } catch (Exception e) {
@@ -104,19 +127,26 @@ public class FileCollector {
                     }
                 }
             } else if (childFile.isDirectory()) {
-                result.addAll(traverseAndSelectFromChildren(childFile, subExpression));
+                result.addAll(traverseAndSelectFromChildren(childFile, expression));
             }
         }
         return result;
     }
 
+    /**
+     * Simple matcher method for a single token.
+     * @param childFile the file to match
+     * @param subTokens the subtoken list
+     * @param tokenIndex the index where to start
+     * @return true if the file matches and should be selected.
+     */
     private static boolean matchesFile(File childFile, List<String> subTokens, int tokenIndex) {
         if (tokenIndex < (subTokens.size() - 1)) {
             // not all tokens consumed, so no match!
             return false;
         }
         String tokenToMatch = subTokens.get(tokenIndex);
-        tokenToMatch = tokenToMatch.replace("*", ".*");
+        tokenToMatch = tokenToMatch.replace("*", ".*").replace("?", ".?");
         return childFile.getName().matches(tokenToMatch);
     }
 


[5/6] incubator-tamaya git commit: Adapted format implementations to new interface.

Posted by an...@apache.org.
Adapted format implementations to new interface.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/1bd7ce1a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/1bd7ce1a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/1bd7ce1a

Branch: refs/heads/master
Commit: 1bd7ce1a655bed2031af72821d3c21734c581a77
Parents: 202e9ac
Author: anatole <an...@apache.org>
Authored: Thu Jan 8 04:40:13 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Jan 11 01:42:07 2015 +0100

----------------------------------------------------------------------
 ...hBasedMultiFormatPropertySourceProvider.java | 28 ++++----
 .../tamaya/format/ConfigurationFormat.java      |  7 +-
 .../apache/tamaya/format/PropertiesFormat.java  | 71 ++++----------------
 .../tamaya/format/PropertiesXmlFormat.java      | 71 ++++----------------
 4 files changed, 44 insertions(+), 133 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1bd7ce1a/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java b/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
index 992878d..ed59f39 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
@@ -62,8 +62,8 @@ public abstract class BasePathBasedMultiFormatPropertySourceProvider implements
     /**
      * Creates a new instance.
      *
-     * @param formats    the formats to be used, not null, not empty.
-     * @param paths      the paths to be resolved, not null, not empty.
+     * @param formats the formats to be used, not null, not empty.
+     * @param paths   the paths to be resolved, not null, not empty.
      */
     public BasePathBasedMultiFormatPropertySourceProvider(
             List<ConfigurationFormat> formats,
@@ -75,8 +75,8 @@ public abstract class BasePathBasedMultiFormatPropertySourceProvider implements
     /**
      * Creates a new instance.
      *
-     * @param formats    the formats to be used, not null, not empty.
-     * @param paths      the paths to be resolved, not null, not empty.
+     * @param formats the formats to be used, not null, not empty.
+     * @param paths   the paths to be resolved, not null, not empty.
      */
     public BasePathBasedMultiFormatPropertySourceProvider(
             ClassLoader classLoader,
@@ -88,14 +88,15 @@ public abstract class BasePathBasedMultiFormatPropertySourceProvider implements
 
     /**
      * Method to create a {@link org.apache.tamaya.spi.PropertySource} based on the given entries read.
+     *
      * @param entryTypeName the entry type of the entries read, not null.
-     * @param entries the entries read by the {@link org.apache.tamaya.format.ConfigurationFormat}
-     * @param formatUsed the format instance used to read the entries.
+     * @param entries       the entries read by the {@link org.apache.tamaya.format.ConfigurationFormat}
+     * @param formatUsed    the format instance used to read the entries.
      * @return the {@link org.apache.tamaya.spi.PropertySource} instance ready to be registered.
      * @see org.apache.tamaya.format.ConfigurationFormat#getEntryTypes()
      */
-    protected abstract PropertySource getPropertySource(String entryTypeName, Map<String,String> entries,
-                                     ConfigurationFormat formatUsed);
+    protected abstract PropertySource getPropertySource(String entryTypeName, Map<String, String> entries,
+                                                        ConfigurationFormat formatUsed);
 
     /**
      * This method does dynamically resolve the paths using the current ClassLoader set. If no ClassLoader was
@@ -114,14 +115,13 @@ public abstract class BasePathBasedMultiFormatPropertySourceProvider implements
                 try {
                     for (ConfigurationFormat format : configFormats) {
                         Map<String, Map<String, String>> entries = format.readConfiguration(res);
-                        for(Map.Entry<String, Map<String, String>> en:entries.entrySet()) {
+                        for (Map.Entry<String, Map<String, String>> en : entries.entrySet()) {
                             PropertySource ps = getPropertySource(en.getKey(), en.getValue(), format);
-                            if(ps!=null) {
+                            if (ps != null) {
                                 propertySources.add(ps);
-                            }
-                            else{
-                                LOG.info(() -> "Config Entries read ignored by PropertySourceFactory: format="+format+
-                                        ", entryType="+en.getKey());
+                            } else {
+                                LOG.info(() -> "Config Entries read ignored by PropertySourceFactory: format=" + format +
+                                        ", entryType=" + en.getKey());
                             }
                         }
                     }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1bd7ce1a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
index 970d0c5..2e43c17 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
@@ -18,11 +18,8 @@
  */
 package org.apache.tamaya.format;
 
-import org.apache.tamaya.spi.PropertySource;
-
 import java.io.IOException;
 import java.net.URL;
-import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 
@@ -30,9 +27,9 @@ import java.util.Set;
  * Implementations current this class encapsulate the mechanism how to read a
  * resource including interpreting the format correctly (e.g. xml vs.
  * properties). In most cases file only contains entries of the same priority, which would then
- * result in only one {@link PropertySource}. Complex file formats, hoiwever, may contain entries
+ * result in only one {@link org.apache.tamaya.spi.PropertySource}. Complex file formats, hoiwever, may contain entries
  * of different priorities. In this cases, each ordinal type found must be returned as a separate
- * {@link PropertySource} instance.
+ * {@link org.apache.tamaya.spi.PropertySource} instance.
  */
 public interface ConfigurationFormat {
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1bd7ce1a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
index a49e492..ab7b029 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesFormat.java
@@ -18,17 +18,14 @@
  */
 package org.apache.tamaya.format;
 
-import org.apache.tamaya.spi.PropertySource;
-
 import java.io.InputStream;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -44,77 +41,37 @@ public class PropertiesFormat implements ConfigurationFormat {
     private final static Logger LOG = Logger.getLogger(PropertiesFormat.class.getName());
 
     /**
-     * The target ordinal.
-     */
-    private int ordinal;
-
-    /**
-     * Creates a new format instance, hereby producing entries with the given ordinal, if not overridden by the
-     * configuration itself.
-     * TODO document and implement override feature
-     *
-     * @param ordinal the target ordinal.
+     * Creates a new format instance.
      */
-    public PropertiesFormat(int ordinal) {
-        this.ordinal = ordinal;
+    public PropertiesFormat() {
     }
 
-    /**
-     * Get the target ordinal, produced by this format.
-     *
-     * @return the target ordinal
-     */
-    public int getOrdinal() {
-        return ordinal;
+    @Override
+    public Set<String> getEntryTypes() {
+        Set<String> set = new HashSet<>();
+        set.add(ConfigurationFormat.DEFAULT_ENTRY_TYPE);
+        return set;
     }
 
     @SuppressWarnings("unchecked")
     @Override
-    public Collection<PropertySource> readConfiguration(URL url) {
+    public Map<String, Map<String, String>> readConfiguration(URL url) {
         final String name;
         if (Objects.requireNonNull(url).getQuery() == null) {
             name = "Properties(" + Objects.requireNonNull(url).toString() + ')';
         } else {
             name = Objects.requireNonNull(url).getQuery();
         }
-        List<PropertySource> propertySources = new ArrayList<>();
+        Map<String, Map<String, String>> result = new HashMap<>();
         try (InputStream is = url.openStream()) {
             if (is != null) {
                 final Properties p = new Properties();
                 p.load(is);
-                propertySources.add(new PropertySource() {
-                    @Override
-                    public int getOrdinal() {
-                        return ordinal;
-                    }
-
-                    @Override
-                    public String getName() {
-                        return name;
-                    }
-
-                    @Override
-                    public String get(String key) {
-                        return p.getProperty(key);
-                    }
-
-                    @Override
-                    public Map<String, String> getProperties() {
-                        return Map.class.cast(p);
-                    }
-                });
-                return propertySources;
+                result.put(ConfigurationFormat.DEFAULT_ENTRY_TYPE, Map.class.cast(p));
             }
         } catch (Exception e) {
             LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + url);
         }
-        return Collections.emptyList();
-    }
-
-    @Override
-    public String toString() {
-        return "PropertiesFormat{" +
-                "ordinal=" + ordinal +
-                '}';
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/1bd7ce1a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
index ddfe723..7aa549b 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/PropertiesXmlFormat.java
@@ -18,17 +18,14 @@
  */
 package org.apache.tamaya.format;
 
-import org.apache.tamaya.spi.PropertySource;
-
 import java.io.InputStream;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Properties;
+import java.util.Set;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -45,77 +42,37 @@ public class PropertiesXmlFormat implements ConfigurationFormat {
     private final static Logger LOG = Logger.getLogger(PropertiesXmlFormat.class.getName());
 
     /**
-     * The target ordinal.
+     * Creates a new format instance.
      */
-    private int ordinal;
+    public PropertiesXmlFormat() { }
 
-    /**
-     * Creates a new format instance, producing entries for the given ordinal, if not overridden by a
-     * config entry itself.
-     * TODO document and implement override feature
-     *
-     * @param ordinal the target ordinal.
-     */
-    public PropertiesXmlFormat(int ordinal) {
-        this.ordinal = ordinal;
+    @Override
+    public Set<String> getEntryTypes() {
+        Set<String> set = new HashSet<>();
+        set.add(ConfigurationFormat.DEFAULT_ENTRY_TYPE);
+        return set;
     }
 
-    /**
-     * Get the target ordinal, produced by this format.
-     *
-     * @return the target ordinal
-     */
-    public int getOrdinal() {
-        return ordinal;
-    }
 
     @SuppressWarnings("unchecked")
     @Override
-    public Collection<PropertySource> readConfiguration(URL url) {
+    public Map<String, Map<String, String>> readConfiguration(URL url) {
         final String name;
         if (Objects.requireNonNull(url).getQuery() == null) {
             name = "XML-Properties(" + Objects.requireNonNull(url).toString() + ')';
         } else {
             name = Objects.requireNonNull(url).getQuery();
         }
-        List<PropertySource> propertySources = new ArrayList<>();
+        Map<String, Map<String, String>> result = new HashMap<>();
         try (InputStream is = url.openStream()) {
             if (is != null) {
                 final Properties p = new Properties();
                 p.loadFromXML(is);
-                propertySources.add(new PropertySource() {
-                    @Override
-                    public int getOrdinal() {
-                        return ordinal;
-                    }
-
-                    @Override
-                    public String getName() {
-                        return name;
-                    }
-
-                    @Override
-                    public String get(String key) {
-                        return p.getProperty(key);
-                    }
-
-                    @Override
-                    public Map<String, String> getProperties() {
-                        return Map.class.cast(p);
-                    }
-                });
-                return propertySources;
+                result.put(ConfigurationFormat.DEFAULT_ENTRY_TYPE, Map.class.cast(p));
             }
         } catch (Exception e) {
             LOG.log(Level.FINEST, e, () -> "Failed to read config from resource: " + url);
         }
-        return Collections.emptyList();
-    }
-
-    @Override
-    public String toString() {
-        return "PropertiesXmlFormat{" +
-                "ordinal=" + ordinal +
-                '}';
+        return result;
     }
 }


[2/6] incubator-tamaya git commit: TAMAYA-43: Bugfix and minor improvements.

Posted by an...@apache.org.
TAMAYA-43: Bugfix and minor improvements.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/842b33e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/842b33e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/842b33e8

Branch: refs/heads/master
Commit: 842b33e8b3410ce213762cde1883dc2111b9bf3c
Parents: e8cc566
Author: anatole <an...@apache.org>
Authored: Thu Jan 8 04:14:49 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Jan 11 01:40:58 2015 +0100

----------------------------------------------------------------------
 modules/resources/pom.xml                       |   5 -
 ...AbstractPathBasedPropertySourceProvider.java |  92 -----------------
 .../AbstractResourcePropertySourceProvider.java | 102 -------------------
 .../tamaya/resource/ResourceResolver.java       |  20 +++-
 .../tamaya/resource/internal/Locator.java       |  41 +++-----
 5 files changed, 34 insertions(+), 226 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/842b33e8/modules/resources/pom.xml
----------------------------------------------------------------------
diff --git a/modules/resources/pom.xml b/modules/resources/pom.xml
index fa1f34e..a932887 100644
--- a/modules/resources/pom.xml
+++ b/modules/resources/pom.xml
@@ -36,10 +36,5 @@ under the License.
             <artifactId>tamaya-api</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.tamaya.ext</groupId>
-            <artifactId>tamaya-formats</artifactId>
-            <version>${project.version}</version>
-        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/842b33e8/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
deleted file mode 100644
index 58acba3..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractPathBasedPropertySourceProvider.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.resource;
-
-import org.apache.tamaya.format.ConfigurationFormat;
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertySourceProvider;
-import org.apache.tamaya.spi.ServiceContext;
-
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Implementation of a {@link PropertySourceProvider} that reads configuration from some given resource paths
- * and using the given formats. The resource path are resolved using the current
- * {@link org.apache.tamaya.resource.ResourceResolver} active.
- */
-public abstract class AbstractPathBasedPropertySourceProvider implements PropertySourceProvider {
-    /** The logger used. */
-    private static final Logger LOG = Logger.getLogger(AbstractPathBasedPropertySourceProvider.class.getName());
-    /** The property source base name, will be used for creating a useful name of the
-     * {@link org.apache.tamaya.spi.PropertySource} created. */
-    private String sourceName;
-    /** The config formats supported for the given location/resource paths. */
-    private List<ConfigurationFormat> configFormats = new ArrayList<>();
-    /** The paths to be evaluated. */
-    private List<String> paths = new ArrayList<>();
-
-    /**
-     * Creates a new instance.
-     * @param sourceName the base name of the configuration, used for creating PropertySource child names.
-     * @param formats the formats to be used, not null, not empty.
-     * @param paths the paths to be resolved, not null, not empty.
-     */
-    public AbstractPathBasedPropertySourceProvider(String sourceName, List<ConfigurationFormat> formats, String... paths) {
-        this.sourceName = Objects.requireNonNull(sourceName);
-        this.configFormats.addAll(Objects.requireNonNull(formats));
-        this.paths.addAll(Arrays.asList(Objects.requireNonNull(paths)));
-    }
-
-    /**
-     * Creates a new instance.
-     * @param sourceName the base name of the configuration, used for creating PropertySource child names.
-     * @param format the format to be used.
-     * @param paths the paths to be resolved, not null, not empty.
-     */
-    public AbstractPathBasedPropertySourceProvider(String sourceName, ConfigurationFormat format, String... paths) {
-        this.sourceName = Objects.requireNonNull(sourceName);
-        this.configFormats.add(Objects.requireNonNull(format));
-        this.paths.addAll(Arrays.asList(Objects.requireNonNull(paths)));
-    }
-
-    @Override
-    public Collection<PropertySource> getPropertySources() {
-        List<PropertySource> propertySources = new ArrayList<>();
-        paths.forEach((path) -> {
-            for (URL res : ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(path)) {
-                try {
-                    for (ConfigurationFormat format : configFormats) {
-                        propertySources.addAll(format.readConfiguration(res));
-                    }
-                } catch (Exception e) {
-                    LOG.log(Level.WARNING, "Failed to add resource based config: " + res, e);
-                }
-            }
-        });
-        return propertySources;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/842b33e8/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java b/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
deleted file mode 100644
index f1ec885..0000000
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/AbstractResourcePropertySourceProvider.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.resource;
-
-import org.apache.tamaya.format.ConfigurationFormat;
-import org.apache.tamaya.spi.PropertySource;
-import org.apache.tamaya.spi.PropertySourceProvider;
-
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Objects;
-import java.util.logging.Logger;
-
-/**
- * Implementation of a {@link org.apache.tamaya.spi.PropertySourceProvider} that is based on a single resource
- * and a number of formats.
- */
-public abstract class AbstractResourcePropertySourceProvider implements PropertySourceProvider {
-    /** The logger used. */
-    private static final Logger LOG = Logger.getLogger(AbstractResourcePropertySourceProvider.class.getName());
-    /** The supported formats. */
-    private List<ConfigurationFormat> formats = new ArrayList<>();
-    /** The resource. */
-    private URL resource;
-    /** The source name used for creating the PropertySource names. */
-    private String sourceName;
-
-    /**
-     * Creates a new instance.
-     * @param resource the {@link URL}, not null.
-     * @param formats the supported formats, not empty.
-     */
-    public AbstractResourcePropertySourceProvider(String sourceName, URL resource, ConfigurationFormat... formats) {
-        this(sourceName, resource, Arrays.asList(formats));
-    }
-
-    /**
-     * Creates a new instance.
-     * @param resource the {@link URL}, not null.
-     * @param formats the supported formats, not empty.
-     */
-    public AbstractResourcePropertySourceProvider(String sourceName, URL resource, List<ConfigurationFormat> formats) {
-        this.resource = Objects.requireNonNull(resource);
-        this.sourceName = Objects.requireNonNull(sourceName);
-        if(formats.size()==0){
-            throw new IllegalArgumentException("Format required.");
-        }
-        this.formats.addAll(formats);
-    }
-
-
-    /**
-     * Get the underlying resource.
-     *
-     * @return the underlying resource, never null.
-     */
-    public URL getResource() {
-        return this.resource;
-    }
-
-
-    @Override
-    public String toString() {
-        return "ResourcePropertySourceProvider{" +
-                "resource=" + resource +
-                ", formats=+" + formats +
-                '}';
-    }
-
-    @Override
-    public Collection<PropertySource> getPropertySources() {
-        List<PropertySource> propertySources = new ArrayList<>();
-        for (ConfigurationFormat format : formats) {
-            try {
-                propertySources.addAll(format.readConfiguration(resource));
-            } catch (Exception e) {
-                LOG.info(() -> "Format was not matching: " + format + " for resource: " + resource);
-            }
-        }
-        return propertySources;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/842b33e8/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
index 31856cf..3dcf6fa 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
@@ -23,8 +23,24 @@ import java.util.Arrays;
 import java.util.Collection;
 
 /**
- * Interface to be implemented by modules. By default only direct file/resource resolution is supported, whereas
- * extension modules may add functionality to perform ant styled pattern resolution of format.
+ * Interface to be implemented by modules. It supports loading of files or classpath resources either directly or by
+ * defining a Ant-styled resource pattern:
+ * <ul>
+ *     <li>'*' is a placeholder for any character (0..n)</li>
+ *     <li>'**' is a placeholder for any number of subdirectories going down a directory structure recursively.</li>
+ *     <li>'?' is a placeholder for exact one character</li>
+ * </ul>
+ * Given that the following expressions are valid expressions:
+ * <pre>
+ *     classpath:javax/annotations/*
+ *     javax?/annotations&#47;**&#47;*.class
+ *     org/apache/tamaya&#47;**&#47;tamayaconfig.properties
+ *     file:C:/temp/*.txt
+ *     file:C:\**\*.ini
+ *     C:\Programs\**&#47;*.ini
+ *     /user/home/A*b101_?.pid
+ *     /var/logs&#47;**&#47;*.log
+ * </pre>
  */
 public interface ResourceResolver {
 

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/842b33e8/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
index 8d9e08a..8b61f03 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
@@ -21,6 +21,7 @@ package org.apache.tamaya.resource.internal;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
 /**
@@ -59,19 +60,15 @@ final class Locator {
      * @return the root path, never null.
      */
     public String getRootPath() {
-        StringBuilder builder = new StringBuilder();
-        for (String token : tokens) {
+        StringJoiner sj = new StringJoiner("/");
+        for (String token : getSubPathTokens()) {
             if (containsPlaceholder(token)) {
                 break;
             } else {
-                builder.append(token);
-                builder.append('/');
+                sj.add(token);
             }
         }
-        if (builder.length() > 0) {
-            builder.setLength(builder.length() - 1);
-        }
-        return builder.toString();
+        return sj.toString();
     }
 
     /**
@@ -81,15 +78,11 @@ final class Locator {
      * @return the sub expression part, never null.
      */
     public String getSubPath() {
-        StringBuilder builder = new StringBuilder();
+        StringJoiner sj = new StringJoiner("/");
         for (String token : getSubPathTokens()) {
-            builder.append(token);
-            builder.append('/');
-        }
-        if (builder.length() > 0) {
-            builder.setLength(builder.length() - 1);
+            sj.add(token);
         }
-        return builder.toString();
+        return sj.toString();
     }
 
     /**
@@ -100,10 +93,12 @@ final class Locator {
      */
     public List<String> getSubPathTokens() {
         List<String> subTokens = new ArrayList<>();
+        boolean subTokensStarted = false;
         for (String token : tokens) {
-            if (!containsPlaceholder(token)) {
-                continue;
-            } else {
+            if(subTokensStarted){
+                subTokens.add(token);
+            } else if (containsPlaceholder(token)) {
+                subTokensStarted = true;
                 subTokens.add(token);
             }
         }
@@ -116,15 +111,11 @@ final class Locator {
      * @return the full expression path, never null.
      */
     public String getPath() {
-        StringBuilder builder = new StringBuilder();
+        StringJoiner sj = new StringJoiner("/");
         for (String token : tokens) {
-            builder.append(token);
-            builder.append('/');
-        }
-        if (builder.length() > 0) {
-            builder.setLength(builder.length() - 1);
+            sj.add(token);
         }
-        return builder.toString();
+        return sj.toString();
     }
 
     /**


[6/6] incubator-tamaya git commit: TAMAYA-43: Bugfix and added tests for CP and FS resolution.

Posted by an...@apache.org.
TAMAYA-43: Bugfix and added tests for CP and FS resolution.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/c48c5794
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/c48c5794
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/c48c5794

Branch: refs/heads/master
Commit: c48c5794e50b421989f9bf331864e38599cc0ced
Parents: 1bd7ce1
Author: anatole <an...@apache.org>
Authored: Sun Jan 11 01:39:27 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Jan 11 01:42:08 2015 +0100

----------------------------------------------------------------------
 modules/resources/pom.xml                       |  6 +-
 .../tamaya/resource/ResourceResolver.java       | 24 +++---
 .../resource/internal/ClasspathCollector.java   | 18 ++--
 .../internal/DefaultResourceResolver.java       |  2 +-
 .../tamaya/resource/internal/FileCollector.java |  8 +-
 .../tamaya/resource/internal/Locator.java       | 10 +--
 .../internal/ClasspathCollectorTest.java        | 91 ++++++++++++++++++++
 .../internal/DefaultResourceResolverTest.java   | 62 +++++++++++++
 .../resource/internal/FileCollectorTest.java    | 71 +++++++++++++++
 .../resources/resources_testroot/aa_a/a1_1.file | 18 ++++
 .../resources/resources_testroot/aa_a/a1_2.file | 18 ++++
 .../resources/resources_testroot/aa_a/a2.file   | 18 ++++
 .../resources/resources_testroot/aa_a/a3.file   | 18 ++++
 .../resources/resources_testroot/aa_a/z3.file   | 18 ++++
 .../resources_testroot/bb/b1/b2/b12.file        | 18 ++++
 .../resources_testroot/bb/b2/b2_1.file          | 18 ++++
 .../resources_testroot/bb/b2/b2_2.datei         | 18 ++++
 .../resources/resources_testroot/bb/b2/b3.foo   | 18 ++++
 18 files changed, 424 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/pom.xml
----------------------------------------------------------------------
diff --git a/modules/resources/pom.xml b/modules/resources/pom.xml
index a932887..cdb1030 100644
--- a/modules/resources/pom.xml
+++ b/modules/resources/pom.xml
@@ -5,7 +5,7 @@ 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 current the License at
+with the License.  You may obtain aa_a copy current the License at
 
    http://www.apache.org/licenses/LICENSE-2.0
 
@@ -36,5 +36,9 @@ under the License.
             <artifactId>tamaya-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
index 3dcf6fa..167a5e1 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/ResourceResolver.java
@@ -24,11 +24,11 @@ import java.util.Collection;
 
 /**
  * Interface to be implemented by modules. It supports loading of files or classpath resources either directly or by
- * defining a Ant-styled resource pattern:
+ * defining aa_a Ant-styled resource pattern:
  * <ul>
- *     <li>'*' is a placeholder for any character (0..n)</li>
- *     <li>'**' is a placeholder for any number of subdirectories going down a directory structure recursively.</li>
- *     <li>'?' is a placeholder for exact one character</li>
+ *     <li>'*' is aa_a placeholder for any character (0..n)</li>
+ *     <li>'**' is aa_a placeholder for any number of subdirectories going down aa_a directory structure recursively.</li>
+ *     <li>'?' is aa_a placeholder for exact one character</li>
  * </ul>
  * Given that the following expressions are valid expressions:
  * <pre>
@@ -45,9 +45,9 @@ import java.util.Collection;
 public interface ResourceResolver {
 
     /**
-     * Resolves resource expressions to a list of {@link URL}s. Hereby
+     * Resolves resource expressions to aa_a list of {@link URL}s. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
-     * there is no determined ordering of format located within a classloader.
+     * there is no determined ordering of format located within aa_a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
      * @return the corresponding collection of current {@link URL}s found, never
@@ -63,9 +63,9 @@ public interface ResourceResolver {
     }
 
     /**
-     * Resolves resource expressions to a list of {@link URL}s. Hereby
+     * Resolves resource expressions to aa_a list of {@link URL}s. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
-     * there is no determined ordering of format located within a classloader.
+     * there is no determined ordering of format located within aa_a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
      * @return the corresponding collection of current {@link URL}s found, never
@@ -77,10 +77,10 @@ public interface ResourceResolver {
     }
 
     /**
-     * Resolves resource expressions to a list of {@link URL}s, considerubg
+     * Resolves resource expressions to aa_a list of {@link URL}s, considerubg
      * the given classloader for classloader dependent format. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
-     * there is no determined ordering of format located within a classloader.
+     * there is no determined ordering of format located within aa_a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
      * @return the corresponding collection of current {@link URL}s found, never
@@ -92,10 +92,10 @@ public interface ResourceResolver {
     }
 
     /**
-     * Resolves resource expressions to a list of {@link URL}s, considerubg
+     * Resolves resource expressions to aa_a list of {@link URL}s, considerubg
      * the given classloader for classloader dependent format. Hereby
      * the ordering of format matches the input of the resolved expressions. Nevertheless be aware that
-     * there is no determined ordering of format located within a classloader.
+     * there is no determined ordering of format located within aa_a classloader.
      *
      * @param expressions the expressions to be resolved, not empty.
      * @return the corresponding collection of current {@link URL}s found, never

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
index 6124dca..bbab3fc 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/ClasspathCollector.java
@@ -61,7 +61,7 @@ public class ClasspathCollector {
     private static final String PROTOCOL_ZIP = "zip";
 
     /**
-     * ZIP protocol for a JBoss jar file entry: "vfszip".
+     * ZIP protocol for aa_a JBoss jar file entry: "vfszip".
      */
     private static final String PROTOCOL_VFSZIP = "vfszip";
 
@@ -79,7 +79,7 @@ public class ClasspathCollector {
      * The logger used.
      */
     private static final Logger LOG = Logger.getLogger(ClasspathCollector.class.getName());
-    
+
     /**
      * Prefix used for explicitly selecting this collector.
      */
@@ -91,7 +91,7 @@ public class ClasspathCollector {
     private ClassLoader classLoader;
 
     /**
-     * Creates a new instance.
+     * Creates aa_a new instance.
      *
      * @param classLoader the class loader to be used, not null.
      */
@@ -154,6 +154,7 @@ public class ClasspathCollector {
         boolean newJarFile = false;
         String jarFileUrl;
         String rootEntryPath;
+        boolean isFileExpression = !subPattern.contains("/");
 
         if (con instanceof JarURLConnection) {
             JarURLConnection jarCon = (JarURLConnection) con;
@@ -193,6 +194,9 @@ public class ClasspathCollector {
                 String entryPath = entry.getName();
                 if (entryPath.startsWith(rootEntryPath)) {
                     String relativePath = entryPath.substring(rootEntryPath.length());
+                    if(relativePath.contains("/") && isFileExpression){
+                        continue;
+                    }
                     if (relativePath.matches(subPattern)) {
                         result.add(createRelativeFrom(rootDirResource, relativePath));
                     }
@@ -209,7 +213,7 @@ public class ClasspathCollector {
     }
 
     /**
-     * Creates a new URL based on the given root path and the relative path to be added.
+     * Creates aa_a new URL based on the given root path and the relative path to be added.
      *
      * @param url          the root, not null
      * @param relativePath the relative path to be added, not null
@@ -230,7 +234,7 @@ public class ClasspathCollector {
 
 
     /**
-     * Small check if a given URL is a jar file URL.
+     * Small check if aa_a given URL is aa_a jar file URL.
      *
      * @param url the URL to check, not null.
      * @return true if the URL has one of the following protocols: jar, zip, vfszip, wsjar, code-source.
@@ -245,10 +249,10 @@ public class ClasspathCollector {
     }
 
     /**
-     * Creates a file from an URL.
+     * Creates aa_a file from an URL.
      *
      * @param resourceUrl the url, not null.
-     * @return a new file instance. The instance still may not exist. if the url's protocol is not 'file', {@code null}
+     * @return aa_a new file instance. The instance still may not exist. if the url's protocol is not 'file', {@code null}
      * is returned.
      */
     private File getFile(URL resourceUrl) {

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
index c90e53a..f5cbefd 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/DefaultResourceResolver.java
@@ -94,7 +94,7 @@ public class DefaultResourceResolver implements ResourceResolver {
     }
 
     /**
-     * Tries to evaluate the location passed by lokking up a file.
+     * Tries to evaluate the location passed by lokking up aa_a file.
      * @param expression the path expression
      * @param resources the resources for adding the results
      * @return true, if the expression could be resolved.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
index 0dcad83..ef26e76 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/FileCollector.java
@@ -88,7 +88,7 @@ public class FileCollector {
         if (token.equals("**")) {
             result.addAll(traverseAndSelectFromChildren(dir, getSubExpression(subTokens, tokenIndex + 1)));
         } else {
-            token = token.replace("*", ".*");
+            token = token.replace("*", ".*").replace("?", ".?");
             File[] files = dir.listFiles();
             if (tokenIndex == subTokens.size() - 1) {
                 // select files!
@@ -134,7 +134,7 @@ public class FileCollector {
     }
 
     /**
-     * Simple matcher method for a single token.
+     * Simple matcher method for aa_a single token.
      * @param childFile the file to match
      * @param subTokens the subtoken list
      * @param tokenIndex the index where to start
@@ -151,7 +151,7 @@ public class FileCollector {
     }
 
     /**
-     * Get an URL from a file.
+     * Get an URL from aa_a file.
      *
      * @param file the file, not null.
      * @return the URL, never null.
@@ -167,7 +167,7 @@ public class FileCollector {
     }
 
     /**
-     * Constructs a sub expression, using the tokens from {@code subTokens} starting at index {@code startIndex}.
+     * Constructs aa_a sub expression, using the tokens from {@code subTokens} starting at index {@code startIndex}.
      *
      * @param subTokens  the token list, not null
      * @param startIndex the start index from where tokens should be taken to produce the path.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
index 8b61f03..8e40fc6 100644
--- a/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
+++ b/modules/resources/src/main/java/org/apache/tamaya/resource/internal/Locator.java
@@ -25,7 +25,7 @@ import java.util.StringJoiner;
 import java.util.stream.Collectors;
 
 /**
- * Small helper class that manages the path parts of a location expression.
+ * Small helper class that manages the path parts of aa_a location expression.
  */
 final class Locator {
     /**
@@ -34,7 +34,7 @@ final class Locator {
     private List<String> tokens;
 
     /**
-     * Creates a new instances based on the tokenized expression.
+     * Creates aa_a new instances based on the tokenized expression.
      *
      * @param tokens the tokenized expression, not null.
      */
@@ -43,7 +43,7 @@ final class Locator {
     }
 
     /**
-     * Creates a new instance of the corresponding expression.
+     * Creates aa_a new instance of the corresponding expression.
      *
      * @param expression the location expression, not null.
      * @return the tokenized instance.
@@ -61,7 +61,7 @@ final class Locator {
      */
     public String getRootPath() {
         StringJoiner sj = new StringJoiner("/");
-        for (String token : getSubPathTokens()) {
+        for (String token : this.tokens) {
             if (containsPlaceholder(token)) {
                 break;
             } else {
@@ -72,7 +72,7 @@ final class Locator {
     }
 
     /**
-     * Return the sub expression path, which contains the second part of the expression, starting with a placeholder
+     * Return the sub expression path, which contains the second part of the expression, starting with aa_a placeholder
      * or wildcard token.
      *
      * @return the sub expression part, never null.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java
new file mode 100644
index 0000000..5827d6b
--- /dev/null
+++ b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.resource.internal;
+
+import java.net.URL;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This tests is using testing the classpath collector functionality, either by accessing/searching entries
+ * from the java.annotation jar as well from the current (file-based classpath).
+ */
+public class ClasspathCollectorTest {
+
+    @org.junit.Test
+    public void testCollectAllClasses() throws Exception {
+        ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader());
+        Collection<URL> found = cpc.collectFiles("classpath:javax/annotation/*.class");
+        assertEquals(8, found.size()); // 7 ordinary, 1 inner class.
+        System.out.println("classpath:javax/annotation/*.class: " + found);
+        Collection<URL> found2 = cpc.collectFiles("javax/annotation/*.class");
+        assertEquals(found, found2);
+    }
+
+    @org.junit.Test
+    public void testCollectAllInPackage() throws Exception {
+        ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader());
+        Collection<URL> found = cpc.collectFiles("classpath:javax/**/sql/*.class");
+        assertEquals(2, found.size());
+        System.out.println("classpath:javax/**/sql/*.class: " + found);
+        Collection<URL> found2 = cpc.collectFiles("javax/**/sql/*.class");
+        assertEquals(found, found2);
+    }
+
+    @org.junit.Test
+    public void testCollectClassNames() throws Exception {
+        ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader());
+        Collection<URL> found = cpc.collectFiles("classpath:javax/annotation/**/R*.class");
+        assertEquals(2, found.size());
+        System.out.println("classpath:javax/annotation/**/A*.class: " + found);
+        Collection<URL> found2 = cpc.collectFiles("javax/annotation/**/R*.class");
+        assertEquals(found, found2);
+    }
+
+    @org.junit.Test
+    public void testCollectWithExpression() throws Exception {
+        ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader());
+        Collection<URL> found = cpc.collectFiles("classpath:javax/annotation/R?so*.class");
+        assertEquals(3, found.size());
+        System.out.println("classpath:javax/annotation/R?so*.class: " + found);
+        Collection<URL> found2 = cpc.collectFiles("javax/annotation/R?so*.class");
+        assertEquals(found, found2);
+    }
+
+    @org.junit.Test
+    public void testCollectResources() throws Exception {
+        ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader());
+        Collection<URL> found = cpc.collectFiles("classpath:META-INF/maven/org.apache.geronimo.specs/**/*");
+        assertEquals(3, found.size());
+        System.out.println("classpath:META-INF/maven/org.apache.geronimo.specs/**/*: " + found);
+        Collection<URL> found2 = cpc.collectFiles("META-INF/maven/org.apache.geronimo.specs/**/*");
+        assertEquals(found, found2);
+    }
+
+    @org.junit.Test
+    public void testCollectResourcesFromLocalFSPath() throws Exception {
+        ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader());
+        Collection<URL> found = cpc.collectFiles("classpath:resources_testRoot/**/*.file");
+        assertEquals(7, found.size());
+        System.out.println("classpath:resources_testRoot/**/*.file: " + found);
+        Collection<URL> found2 = cpc.collectFiles("resources_testRoot/**/*.file");
+        assertEquals(found, found2);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/java/org/apache/tamaya/resource/internal/DefaultResourceResolverTest.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/DefaultResourceResolverTest.java b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/DefaultResourceResolverTest.java
new file mode 100644
index 0000000..66e3246
--- /dev/null
+++ b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/DefaultResourceResolverTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.resource.internal;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collection;
+
+import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests the {@link org.apache.tamaya.resource.internal.DefaultResourceResolver} using CP and FS path expressions.
+ */
+public class DefaultResourceResolverTest {
+
+    private DefaultResourceResolver resolver = new DefaultResourceResolver();
+
+
+    @Test
+    public void testGetResources_CP() throws Exception {
+        Collection<URL> found = resolver.getResources("classpath:resources_testRoot/**/*.file");
+        assertEquals(7, found.size());
+        System.out.println("classpath:resources_testRoot/**/*.file: " + found);
+        Collection<URL> found2 = resolver.getResources("resources_testRoot/**/*.file");
+        assertEquals(found, found2);
+    }
+
+    @Test
+    public void testGetResources_FS() throws Exception {
+        String resDir = getResourceDir();
+        Collection<URL> found = resolver.getResources("file:" + resDir + "/resources_testroot/aa?a/*.file");
+        assertEquals(5, found.size());
+        System.out.println("file:" + resDir + "/resources_testroot/aa?a/*.file: " + found);
+        Collection<URL> found2 = resolver.getResources(resDir + "/resources_testroot/aa?a/*.file");
+        assertEquals(found, found2);
+    }
+
+    private String getResourceDir() throws URISyntaxException {
+        URL res = getClass().getResource("/resources_testroot/");
+        return new File(res.toURI()).getParentFile().getAbsolutePath();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java
new file mode 100644
index 0000000..f7f5772
--- /dev/null
+++ b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.resource.internal;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collection;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test for checking correct lookup using the filesystem.
+ */
+public class FileCollectorTest {
+
+    private String getResourceDir() throws URISyntaxException {
+        URL res = getClass().getResource("/resources_testroot/");
+        return new File(res.toURI()).getParentFile().getAbsolutePath();
+    }
+
+    @Test
+    public void testCollectResourcesFromLocalFSPath() throws Exception {
+        String resDir = getResourceDir();
+        Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/**/*.file");
+        assertEquals(7, found.size());
+        System.out.println("file:" + resDir + "/**/*.file: " + found);
+        Collection<URL> found2 = FileCollector.collectFiles(resDir + "/**/*.file");
+        assertEquals(found, found2);
+    }
+
+    @Test
+    public void testCollectResourcesFromLocalFSPath_WithFolderPlaceholder() throws Exception {
+        String resDir = getResourceDir();
+        Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/resources_testroot/aa?a/*.file");
+        assertEquals(5, found.size());
+        System.out.println("file:" + resDir + "/resources_testroot/aa?a/*.file: " + found);
+        Collection<URL> found2 = FileCollector.collectFiles(resDir + "/resources_testroot/aa?a/*.file");
+        assertEquals(found, found2);
+    }
+
+    @Test
+    public void testCollectResourcesFromLocalFSPath_WithFolderAny() throws Exception {
+        String resDir = getResourceDir();
+        Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/resources_testroot/b*/b?/*.file");
+        assertEquals(1, found.size());
+        System.out.println("file:" + resDir + "/resources_testroot/b*/b?/*.file: " + found);
+        Collection<URL> found2 = FileCollector.collectFiles(resDir + "/resources_testroot/b*/b?/*.file");
+        assertEquals(found, found2);
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/aa_a/a1_1.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/aa_a/a1_1.file b/modules/resources/src/test/resources/resources_testroot/aa_a/a1_1.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/aa_a/a1_1.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/aa_a/a1_2.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/aa_a/a1_2.file b/modules/resources/src/test/resources/resources_testroot/aa_a/a1_2.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/aa_a/a1_2.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/aa_a/a2.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/aa_a/a2.file b/modules/resources/src/test/resources/resources_testroot/aa_a/a2.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/aa_a/a2.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/aa_a/a3.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/aa_a/a3.file b/modules/resources/src/test/resources/resources_testroot/aa_a/a3.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/aa_a/a3.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/aa_a/z3.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/aa_a/z3.file b/modules/resources/src/test/resources/resources_testroot/aa_a/z3.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/aa_a/z3.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/bb/b1/b2/b12.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/bb/b1/b2/b12.file b/modules/resources/src/test/resources/resources_testroot/bb/b1/b2/b12.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/bb/b1/b2/b12.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_1.file
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_1.file b/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_1.file
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_1.file
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_2.datei
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_2.datei b/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_2.datei
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/bb/b2/b2_2.datei
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/c48c5794/modules/resources/src/test/resources/resources_testroot/bb/b2/b3.foo
----------------------------------------------------------------------
diff --git a/modules/resources/src/test/resources/resources_testroot/bb/b2/b3.foo b/modules/resources/src/test/resources/resources_testroot/bb/b2/b3.foo
new file mode 100644
index 0000000..7220975
--- /dev/null
+++ b/modules/resources/src/test/resources/resources_testroot/bb/b2/b3.foo
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
\ No newline at end of file


[3/6] incubator-tamaya git commit: Reorganized format module. Redesigned format interface.

Posted by an...@apache.org.
Reorganized format module.
Redesigned format interface.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/e8cc5666
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/e8cc5666
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/e8cc5666

Branch: refs/heads/master
Commit: e8cc5666d583f795f6bb8190c97995fe90c60e55
Parents: ae66299
Author: anatole <an...@apache.org>
Authored: Thu Jan 8 04:13:49 2015 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Jan 11 01:40:58 2015 +0100

----------------------------------------------------------------------
 modules/formats/pom.xml                         |   5 +
 ...hBasedMultiFormatPropertySourceProvider.java | 136 +++++++++++++++++++
 .../BaseSimpleFormatPropertySourceProvider.java | 103 ++++++++++++++
 .../tamaya/format/ConfigurationFormat.java      |  34 ++++-
 4 files changed, 275 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e8cc5666/modules/formats/pom.xml
----------------------------------------------------------------------
diff --git a/modules/formats/pom.xml b/modules/formats/pom.xml
index 5c98c76..65b40f4 100644
--- a/modules/formats/pom.xml
+++ b/modules/formats/pom.xml
@@ -36,5 +36,10 @@ under the License.
             <artifactId>tamaya-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-resources</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e8cc5666/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java b/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
new file mode 100644
index 0000000..992878d
--- /dev/null
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/BasePathBasedMultiFormatPropertySourceProvider.java
@@ -0,0 +1,136 @@
+/*
+ * 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.format;
+
+import org.apache.tamaya.resource.ResourceResolver;
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+import org.apache.tamaya.spi.ServiceContext;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of a {@link PropertySourceProvider} that reads configuration from some given resource paths
+ * and using the given formats. The resource path are resolved using the current
+ * {@link org.apache.tamaya.resource.ResourceResolver} active. For each resource found the configuration formats
+ * passed get a chance to read the resource, if they succeed the result is taken as the providers PropertySources
+ * to be exposed.
+ */
+public abstract class BasePathBasedMultiFormatPropertySourceProvider implements PropertySourceProvider {
+    /**
+     * The logger used.
+     */
+    private static final Logger LOG = Logger.getLogger(BasePathBasedMultiFormatPropertySourceProvider.class.getName());
+    /**
+     * The config formats supported for the given location/resource paths.
+     */
+    private List<ConfigurationFormat> configFormats = new ArrayList<>();
+    /**
+     * The paths to be evaluated.
+     */
+    private List<String> paths = new ArrayList<>();
+    /**
+     * The ClassLoader to use.
+     */
+    private Optional<ClassLoader> classLoader;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param formats    the formats to be used, not null, not empty.
+     * @param paths      the paths to be resolved, not null, not empty.
+     */
+    public BasePathBasedMultiFormatPropertySourceProvider(
+            List<ConfigurationFormat> formats,
+            String... paths) {
+        this.configFormats.addAll(Objects.requireNonNull(formats));
+        this.paths.addAll(Arrays.asList(Objects.requireNonNull(paths)));
+    }
+
+    /**
+     * Creates a new instance.
+     *
+     * @param formats    the formats to be used, not null, not empty.
+     * @param paths      the paths to be resolved, not null, not empty.
+     */
+    public BasePathBasedMultiFormatPropertySourceProvider(
+            ClassLoader classLoader,
+            List<ConfigurationFormat> formats, String... paths) {
+        this.classLoader = Optional.ofNullable(classLoader);
+        this.configFormats.addAll(Objects.requireNonNull(formats));
+        this.paths.addAll(Arrays.asList(Objects.requireNonNull(paths)));
+    }
+
+    /**
+     * Method to create a {@link org.apache.tamaya.spi.PropertySource} based on the given entries read.
+     * @param entryTypeName the entry type of the entries read, not null.
+     * @param entries the entries read by the {@link org.apache.tamaya.format.ConfigurationFormat}
+     * @param formatUsed the format instance used to read the entries.
+     * @return the {@link org.apache.tamaya.spi.PropertySource} instance ready to be registered.
+     * @see org.apache.tamaya.format.ConfigurationFormat#getEntryTypes()
+     */
+    protected abstract PropertySource getPropertySource(String entryTypeName, Map<String,String> entries,
+                                     ConfigurationFormat formatUsed);
+
+    /**
+     * This method does dynamically resolve the paths using the current ClassLoader set. If no ClassLoader was
+     * explcitly set during creation the current Thread context ClassLoader is used. If none of the supported
+     * formats is able to parse a resource a WARNING log is written.
+     *
+     * @return the PropertySources successfully read
+     */
+    @Override
+    public Collection<PropertySource> getPropertySources() {
+        List<PropertySource> propertySources = new ArrayList<>();
+        paths.forEach((path) -> {
+            for (URL res : ServiceContext.getInstance().getService(ResourceResolver.class).get().getResources(
+                    this.classLoader.orElse(Thread.currentThread().getContextClassLoader()),
+                    path)) {
+                try {
+                    for (ConfigurationFormat format : configFormats) {
+                        Map<String, Map<String, String>> entries = format.readConfiguration(res);
+                        for(Map.Entry<String, Map<String, String>> en:entries.entrySet()) {
+                            PropertySource ps = getPropertySource(en.getKey(), en.getValue(), format);
+                            if(ps!=null) {
+                                propertySources.add(ps);
+                            }
+                            else{
+                                LOG.info(() -> "Config Entries read ignored by PropertySourceFactory: format="+format+
+                                        ", entryType="+en.getKey());
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    LOG.log(Level.WARNING, "Failed to add resource based config: " + res, e);
+                }
+            }
+        });
+        return propertySources;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e8cc5666/modules/formats/src/main/java/org/apache/tamaya/format/BaseSimpleFormatPropertySourceProvider.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/BaseSimpleFormatPropertySourceProvider.java b/modules/formats/src/main/java/org/apache/tamaya/format/BaseSimpleFormatPropertySourceProvider.java
new file mode 100644
index 0000000..1fe08c2
--- /dev/null
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/BaseSimpleFormatPropertySourceProvider.java
@@ -0,0 +1,103 @@
+/*
+ * 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.format;
+
+import org.apache.tamaya.spi.PropertySource;
+import org.apache.tamaya.spi.PropertySourceProvider;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Implementation of a {@link org.apache.tamaya.spi.PropertySourceProvider} that reads configuration from
+ * a given resource and in a given format.
+ */
+public abstract class BaseSimpleFormatPropertySourceProvider implements PropertySourceProvider {
+    /**
+     * The logger used.
+     */
+    private static final Logger LOG = Logger.getLogger(BaseSimpleFormatPropertySourceProvider.class.getName());
+    /**
+     * The config formats supported, not null.
+     */
+    private ConfigurationFormat configFormat;
+    /**
+     * The resource to be read, not null.
+     */
+    private URL resource;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param format   the formas to be used, not null.
+     * @param resource the resource to be read, not null.
+     */
+    public BaseSimpleFormatPropertySourceProvider(
+            ConfigurationFormat format,
+            URL resource) {
+        this.configFormat = Objects.requireNonNull(format);
+        this.resource = Objects.requireNonNull(resource);
+    }
+
+    /**
+     * Method to create a {@link org.apache.tamaya.spi.PropertySource} based on the given entries read.
+     *
+     * @param entryTypeName the entry type of the entries read, not null.
+     * @param entries       the entries read by the {@link ConfigurationFormat}
+     * @param formatUsed    the format instance used to read the entries.
+     * @return the {@link org.apache.tamaya.spi.PropertySource} instance ready to be registered.
+     * @see ConfigurationFormat#getEntryTypes()
+     */
+    protected abstract PropertySource getPropertySource(String entryTypeName, Map<String, String> entries,
+                                                        ConfigurationFormat formatUsed);
+
+    /**
+     * This method does dynamically resolve the paths using the current ClassLoader set. If no ClassLoader was
+     * explcitly set during creation the current Thread context ClassLoader is used. If none of the supported
+     * formats is able to parse a resource a WARNING log is written.
+     *
+     * @return the PropertySources successfully read
+     */
+    @Override
+    public Collection<PropertySource> getPropertySources() {
+        List<PropertySource> propertySources = new ArrayList<>();
+        try {
+            Map<String, Map<String, String>> entries = configFormat.readConfiguration(resource);
+            for (Map.Entry<String, Map<String, String>> en : entries.entrySet()) {
+                PropertySource ps = getPropertySource(en.getKey(), en.getValue(), configFormat);
+                if (ps != null) {
+                    propertySources.add(ps);
+                } else {
+                    LOG.info(() -> "Config Entries read ignored by PropertySourceFactory: format=" + configFormat +
+                            ", entryType=" + en.getKey());
+                }
+            }
+        } catch (Exception e) {
+            LOG.log(Level.WARNING, "Failed to add resource based config: " + resource, e);
+        }
+        return propertySources;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e8cc5666/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
----------------------------------------------------------------------
diff --git a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
index 924fa7c..970d0c5 100644
--- a/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
+++ b/modules/formats/src/main/java/org/apache/tamaya/format/ConfigurationFormat.java
@@ -23,6 +23,8 @@ import org.apache.tamaya.spi.PropertySource;
 import java.io.IOException;
 import java.net.URL;
 import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Implementations current this class encapsulate the mechanism how to read a
@@ -32,10 +34,35 @@ import java.util.Collection;
  * of different priorities. In this cases, each ordinal type found must be returned as a separate
  * {@link PropertySource} instance.
  */
-@FunctionalInterface
 public interface ConfigurationFormat {
 
     /**
+     * The default entry type returned if a format implementation does not support any explicit entry types.
+     */
+    public static final String DEFAULT_ENTRY_TYPE = "default";
+
+    /**
+     * Access the different entry types a format supports. Entries of the same entry type hereby share the same
+     * configuration priority. The reason for this concept is that a configuration format can produce different
+     * types of properties, e.g. default properties, named properties, overriding ones as illustrated below:
+     * <pre>
+     *     [defaults]
+     *     a.b.c=alphabet
+     *     foo.bar=any
+     *
+     *     [staged:development]
+     *     a.b.myEntry=1234
+     *
+     *     [management-overrides]
+     *     a.b.d=Alphabet
+     * </pre>
+     * If just using ordinary property files, of course, only one entry type is returned, called 'default'.
+     * #see DEFAULT_ENTRY_TYPE
+     * @return the set of supported entry types, never null and never empty.
+     */
+    public Set<String> getEntryTypes();
+
+    /**
      * Reads a list {@link org.apache.tamaya.spi.PropertySource} instances from a resource, using this format.
      * If the configuration format only contains entries of one ordinal type, normally only one single
      * instance of PropertySource is returned. Nevertheless custom formats may contain different sections or parts,
@@ -45,9 +72,10 @@ public interface ConfigurationFormat {
      *
      * @param url the url to read the configuration data from (could be a file, a remote location, a classpath
      *            resource or something else.
-     * @return the corresponding {@link org.apache.tamaya.spi.PropertySource} instances, never {@code null}.
+     * @return the corresponding {@link java.util.Map} instances of properties read, never {@code null}. Each
+     * {@link java.util.Map} instance hereby is provided using a type key.
      */
-    Collection<PropertySource> readConfiguration(URL url)
+    Map<String, Map<String,String>> readConfiguration(URL url)
             throws IOException;
 
 }