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 <[email protected]>:

> 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, "[email protected]" <
> [email protected]> 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 <[email protected]>
> > Authored: Wed Jan 7 22:49:39 2015 +0100
> > Committer: anatole <[email protected]>
> > 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*

Reply via email to