// Path: src/main/java/com/tngtech/propertyloader/impl/interfaces/PropertyLoaderFilter.java
// public interface PropertyLoaderFilter {
// 
//     void filter(Properties properties);
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/ClassLoaderOpener.java
// public class ClassLoaderOpener implements PropertyLoaderOpener {
// 
//     private final ClassLoader classLoader;
// 
//     public ClassLoaderOpener(ClassLoader classLoader) {
//         this.classLoader = classLoader;
//     }
// 
//     public InputStream open(String fileName) {
//         return classLoader.getResourceAsStream(fileName);
//     }
// 
//     @Override
//     public String toString() {
//         return "by classloader " + classLoader;
//     }
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/ContextClassLoaderOpener.java
// public class ContextClassLoaderOpener implements PropertyLoaderOpener {
// 
//     public InputStream open(String fileName) {
//         ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//         return contextClassLoader.getResourceAsStream(fileName);
//     }
// 
//     @Override
//     public String toString() {
//         return "in classpath";
//     }
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/RelativeToClassOpener.java
// public class RelativeToClassOpener implements PropertyLoaderOpener {
// 
//     private final Class<?> reference;
// 
//     public RelativeToClassOpener(Class<?> reference) {
//         this.reference = reference;
//     }
// 
//     public InputStream open(String filename) {
//         return reference.getResourceAsStream(filename);
//     }
// 
//     @Override
//     public String toString() {
//         return "near " + reference;
//     }
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/URLFileOpener.java
// public class URLFileOpener implements PropertyLoaderOpener {
// 
//     private URL url;
// 
//     public URLFileOpener() {
//         try {
//             this.url = new File("").toURI().toURL();
//         } catch (MalformedURLException e) {
//             throw new RuntimeException(String.format("THIS CAN NOT HAPPEN: error while forming URL from path '%s'", ""), e);
//         }
//     }
// 
//     public URLFileOpener(URL url) {
//         this.url = url;
//     }
// 
//     public URLFileOpener(String address) {
//         try {
//             this.url = new File(address.replace("/", File.separator)).toURI().toURL();
//         } catch (MalformedURLException e) {
//             throw new RuntimeException(String.format("THIS SHOULD NOT HAPPEN: error while forming URL from path '%s'", address), e);
//         }
//     }
// 
//     /**
//      * Tries to open the given file.
//      * A filename that starts with '/' is understood as an absolute path,
//      * i.e. the URLFileOpener forgets about its path.
//      *
//      * @param fileName the filename
//      * @return InputStream of the resource found at the given URL
//      */
//     public InputStream open(String fileName) {
//         try {
//             URL urlToFile = new URL(url, fileName);
//             return urlToFile.openStream();
//         } catch (MalformedURLException e) {
//             throw new RuntimeException(String.format("error while forming new URL from URL %s and filename %s", url.getPath(), fileName), e);
//         } catch (IOException e) {
//             return null;
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return "in path " + url.getPath();
//     }
// }


import com.tngtech.propertyloader.impl.filters.*;
import com.tngtech.propertyloader.impl.interfaces.PropertyLoaderFilter;
import com.tngtech.propertyloader.impl.openers.ClassLoaderOpener;
import com.tngtech.propertyloader.impl.openers.ContextClassLoaderOpener;
import com.tngtech.propertyloader.impl.openers.RelativeToClassOpener;
import com.tngtech.propertyloader.impl.openers.URLFileOpener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Properties;
import java.util.Stack;

    public Properties getEmptyProperties() {
        return new Properties();
    }

    public InputStreamReader getInputStreamReader(InputStream stream, String encoding) throws IOException {
        return new InputStreamReader(stream, encoding);
    }

    public URLFileOpener getURLFileOpener() {
        return new URLFileOpener();
    }

    public URLFileOpener getURLFileOpener(String directory) {
        return new URLFileOpener(directory);
    }

    public ContextClassLoaderOpener getContextClassLoaderOpener() {
        return new ContextClassLoaderOpener();
    }

    public RelativeToClassOpener getRelativeToClass(Class<?> tClass) {
        return new RelativeToClassOpener(tClass);
    }

    public ClassLoaderOpener getClassLoaderOpener(ClassLoader classLoader) {
        return new ClassLoaderOpener(classLoader);
    }

    public URLFileOpener getURLFileOpener(URL url) {
// Path: src/main/java/com/tngtech/propertyloader/impl/interfaces/PropertyLoaderFilter.java
// public interface PropertyLoaderFilter {
// 
//     void filter(Properties properties);
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/ClassLoaderOpener.java
// public class ClassLoaderOpener implements PropertyLoaderOpener {
// 
//     private final ClassLoader classLoader;
// 
//     public ClassLoaderOpener(ClassLoader classLoader) {
//         this.classLoader = classLoader;
//     }
// 
//     public InputStream open(String fileName) {
//         return classLoader.getResourceAsStream(fileName);
//     }
// 
//     @Override
//     public String toString() {
//         return "by classloader " + classLoader;
//     }
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/ContextClassLoaderOpener.java
// public class ContextClassLoaderOpener implements PropertyLoaderOpener {
// 
//     public InputStream open(String fileName) {
//         ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//         return contextClassLoader.getResourceAsStream(fileName);
//     }
// 
//     @Override
//     public String toString() {
//         return "in classpath";
//     }
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/RelativeToClassOpener.java
// public class RelativeToClassOpener implements PropertyLoaderOpener {
// 
//     private final Class<?> reference;
// 
//     public RelativeToClassOpener(Class<?> reference) {
//         this.reference = reference;
//     }
// 
//     public InputStream open(String filename) {
//         return reference.getResourceAsStream(filename);
//     }
// 
//     @Override
//     public String toString() {
//         return "near " + reference;
//     }
// }
// 
// Path: src/main/java/com/tngtech/propertyloader/impl/openers/URLFileOpener.java
// public class URLFileOpener implements PropertyLoaderOpener {
// 
//     private URL url;
// 
//     public URLFileOpener() {
//         try {
//             this.url = new File("").toURI().toURL();
//         } catch (MalformedURLException e) {
//             throw new RuntimeException(String.format("THIS CAN NOT HAPPEN: error while forming URL from path '%s'", ""), e);
//         }
//     }
// 
//     public URLFileOpener(URL url) {
//         this.url = url;
//     }
// 
//     public URLFileOpener(String address) {
//         try {
//             this.url = new File(address.replace("/", File.separator)).toURI().toURL();
//         } catch (MalformedURLException e) {
//             throw new RuntimeException(String.format("THIS SHOULD NOT HAPPEN: error while forming URL from path '%s'", address), e);
//         }
//     }
// 
//     /**
//      * Tries to open the given file.
//      * A filename that starts with '/' is understood as an absolute path,
//      * i.e. the URLFileOpener forgets about its path.
//      *
//      * @param fileName the filename
//      * @return InputStream of the resource found at the given URL
//      */
//     public InputStream open(String fileName) {
//         try {
//             URL urlToFile = new URL(url, fileName);
//             return urlToFile.openStream();
//         } catch (MalformedURLException e) {
//             throw new RuntimeException(String.format("error while forming new URL from URL %s and filename %s", url.getPath(), fileName), e);
//         } catch (IOException e) {
//             return null;
//         }
//     }
// 
//     @Override
//     public String toString() {
//         return "in path " + url.getPath();
//     }
// }


// Path: src/main/java/com/tngtech/propertyloader/impl/PropertyLoaderFactory.java
import com.tngtech.propertyloader.impl.filters.*;
import com.tngtech.propertyloader.impl.interfaces.PropertyLoaderFilter;
import com.tngtech.propertyloader.impl.openers.ClassLoaderOpener;
import com.tngtech.propertyloader.impl.openers.ContextClassLoaderOpener;
import com.tngtech.propertyloader.impl.openers.RelativeToClassOpener;
import com.tngtech.propertyloader.impl.openers.URLFileOpener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Properties;
import java.util.Stack;


    public Properties getEmptyProperties() {
        return new Properties();
    }

    public InputStreamReader getInputStreamReader(InputStream stream, String encoding) throws IOException {
        return new InputStreamReader(stream, encoding);
    }

    public URLFileOpener getURLFileOpener() {
        return new URLFileOpener();
    }

    public URLFileOpener getURLFileOpener(String directory) {
        return new URLFileOpener(directory);
    }

    public ContextClassLoaderOpener getContextClassLoaderOpener() {
        return new ContextClassLoaderOpener();
    }

    public RelativeToClassOpener getRelativeToClass(Class<?> tClass) {
        return new RelativeToClassOpener(tClass);
    }

    public ClassLoaderOpener getClassLoaderOpener(ClassLoader classLoader) {
        return new ClassLoaderOpener(classLoader);
    }

    public URLFileOpener getURLFileOpener(URL url) {
        return new URLFileOpener(url);