package cucumber.runtime.java.guice;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import cucumber.runtime.java.ObjectFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import static java.util.Collections.emptyList;

/**
 * Guice implementation of the ObjectFactory. This will register all given step classes as singletons within a scenario
 * specific Injector.
 */
public class GuiceFactory implements ObjectFactory {
    private final List<Module> modules;
    private final Set<Class<?>> classes = new HashSet<Class<?>>();
    private Injector injector;

    public GuiceFactory() throws IOException {
        this(loadCucumberGuiceProperties());
    }

    GuiceFactory(Properties properties) throws IOException {
        String guiceModuleClassName = properties.getProperty("guiceModule");
        if (guiceModuleClassName == null) {
            this.modules = emptyList();
        } else {
            this.modules = new ModuleInstantiator().instantiate(guiceModuleClassName);
        }
    }

    private static Properties loadCucumberGuiceProperties() throws IOException {
        Properties properties = new Properties();
        InputStream inputStream = GuiceFactory.class.getClassLoader().getResourceAsStream("cucumber-guice.properties");
        if (inputStream != null) {
            try {
                properties.load(inputStream);
            } finally {
                inputStream.close();
            }
        }
        return properties;
    }

    public void addClass(Class<?> clazz) {
        classes.add(clazz);
    }

    public void createInstances() {
        injector = Guice.createInjector(new CucumberModule(classes, modules));
    }

    public void disposeInstances() {
        injector = null;
    }

    public <T> T getInstance(Class<T> clazz) {
        return injector.getInstance(clazz);
    }

    /**
     * Guice module that configures all added classes to the module as singletons and installs all dynamically loaded
     * modules.
     */
    private static final class CucumberModule extends AbstractModule {

        private final Set<Class<?>> classes;
        private final List<Module> modules;

        private CucumberModule(Set<Class<?>> classes, List<Module> modules) {
            this.classes = classes;
            this.modules = modules;
        }

        @Override
        protected void configure() {
            for (Class<?> aClass : classes) {
                bind(aClass).in(javax.inject.Singleton.class);
            }
            for (Module module : modules) {
                install(module);
            }
        }
    }
}

@@ -1394,25 +1394,8 @@
 ass.
-getClassLoader().
 getR
@@ -1411,16 +1411,17 @@
 Stream(%22
+/
 cucumber

Change the method used to load the properties file from the classloader to the class method. This fixes problems when running the tests in a multi module/multi class loader setup