// Path: rsimulator-core/src/main/java/com/github/bjuvensjo/rsimulator/core/Simulator.java
// @ImplementedBy(SimulatorImpl.class)
// public interface Simulator {
// 
//     /**
//      * Returns a SimulatorResponse that matches the specified request.
//      *
//      * @param rootPath         the root path on which to search recursively for matches to the specified request
//      * @param rootRelativePath the path on which to search recursively for matches to the specified request
//      * @param request          the request
//      * @param contentType      the content type of the request, e.g. txt or xml
//      * @param vars             vars that can be used in for example scripts
//      * @return a SimulatorResponse that matches the specified request
//      */
//     Optional<SimulatorResponse> service(String rootPath, String rootRelativePath, String request, String contentType, Map<String, Object>... vars);
// }
// 
// Path: rsimulator-core/src/main/java/com/github/bjuvensjo/rsimulator/core/config/CoreModule.java
// public class CoreModule extends AbstractModule {
//     private final Logger log = LoggerFactory.getLogger(CoreModule.class);
//     private static final CacheManager cacheManager = CacheManager.create();
// 
//     @Provides
//     @Named("rsimulator-core-properties")
//     java.util.Properties provideProperties() {
//         java.util.Properties properties = new java.util.Properties();
//         URL resource = getClass().getResource("/rsimulator.properties");
//         if (resource == null) {
//             properties.setProperty("simulatorCache", "false");
//             properties.setProperty("ignoreXmlNamespaces", "false");
//         } else {
//             try (BufferedInputStream bis = new BufferedInputStream(resource.openStream())) {
//                 properties.load(bis);
//             } catch (Exception e) {
//                 log.error("Error reading properties from: {}", resource.getPath(), e);
//             }
//         }
//         return properties;
//     }
// 
//     @Override
//     protected void configure() {
//         MapBinder<String, Handler> map = MapBinder.newMapBinder(binder(), String.class, Handler.class);
//         map.addBinding("json").to(JsonHandler.class);
//         map.addBinding("txt").to(TxtHandler.class);
//         map.addBinding("xml").to(XmlHandler.class);
// 
//         // ***** Interceptors for cache and script *****
//         Arrays.asList("SimulatorCache", "FileUtilsCache", "PropsCache").forEach(name ->
//                 bind(net.sf.ehcache.Cache.class).annotatedWith(Names.named(name)).toInstance(cacheManager.getCache(name)));
// 
// 
//         SimulatorPropertiesInterceptor simulatorPropertiesInterceptor = new SimulatorPropertiesInterceptor();
//         SimulatorCacheInterceptor simulatorCacheInterceptor = new SimulatorCacheInterceptor();
//         SimulatorScriptInterceptor simulatorScriptInterceptor = new SimulatorScriptInterceptor();
//         FileUtilsCacheInterceptor fileUtilsCacheInterceptor = new FileUtilsCacheInterceptor();
//         PropsCacheInterceptor propsCacheInterceptor = new PropsCacheInterceptor();
// 
//         requestInjection(simulatorPropertiesInterceptor);
//         requestInjection(simulatorCacheInterceptor);
//         requestInjection(simulatorScriptInterceptor);
//         requestInjection(fileUtilsCacheInterceptor);
//         requestInjection(propsCacheInterceptor);
// 
//         // Order is significant
//         bindInterceptor(Matchers.subclassesOf(Simulator.class), Matchers.annotatedWith(Properties.class),
//                 simulatorPropertiesInterceptor);
//         bindInterceptor(Matchers.subclassesOf(Simulator.class), Matchers.annotatedWith(Cache.class),
//                 simulatorCacheInterceptor);
//         bindInterceptor(Matchers.subclassesOf(Simulator.class), Matchers.annotatedWith(Script.class),
//                 simulatorScriptInterceptor);
//         bindInterceptor(Matchers.subclassesOf(FileUtils.class), Matchers.annotatedWith(Cache.class),
//                 fileUtilsCacheInterceptor);
//         bindInterceptor(Matchers.subclassesOf(Props.class), Matchers.annotatedWith(Cache.class),
//                 propsCacheInterceptor);
//     }
// }


import com.github.bjuvensjo.rsimulator.core.Simulator;
import com.github.bjuvensjo.rsimulator.core.config.CoreModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import org.apache.cxf.Bus;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.AbstractTransportFactory;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.ConduitInitiator;
import org.apache.cxf.transport.http.HTTPTransportFactory;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import java.util.Collections;
import java.util.List;
import java.util.Set;
package com.github.bjuvensjo.rsimulator.cxf.transport;



/**
 * Custom transport factory for CXF that provides Conduits which uses RSimulator CoreModule to match outgoing requests
 * with responses.
 * <p>
 * The purpose is to be able to use the simulator easily and efficient without the requirement of using the http-protocol.
 */
public class RSimulatorTransportFactory extends AbstractTransportFactory implements ConduitInitiator {
    private final Set<String> uriPrefixes;
    private final String rootPath;
    @Inject
    private Simulator simulator;

    /**
     * Minimal constructor that registers itself as a factory for the "http://"-protocol.
     *
     * @param rootPath absolute path where the simulator should use as root when trying to find response
     */
    public RSimulatorTransportFactory(String rootPath) {
        this(rootPath, Collections.singletonList("http://"));
    }

    /**
     * Constructor that accepts a list of protocols and a rootPath.
     *
     * @param rootPath  absolute path where the simulator should use as root when trying to find response
     * @param protocols list of protocols for which this transport factory should be used
     */
    public RSimulatorTransportFactory(String rootPath, List<String> protocols) {
        super(HTTPTransportFactory.DEFAULT_NAMESPACES);
// Path: rsimulator-core/src/main/java/com/github/bjuvensjo/rsimulator/core/Simulator.java
// @ImplementedBy(SimulatorImpl.class)
// public interface Simulator {
// 
//     /**
//      * Returns a SimulatorResponse that matches the specified request.
//      *
//      * @param rootPath         the root path on which to search recursively for matches to the specified request
//      * @param rootRelativePath the path on which to search recursively for matches to the specified request
//      * @param request          the request
//      * @param contentType      the content type of the request, e.g. txt or xml
//      * @param vars             vars that can be used in for example scripts
//      * @return a SimulatorResponse that matches the specified request
//      */
//     Optional<SimulatorResponse> service(String rootPath, String rootRelativePath, String request, String contentType, Map<String, Object>... vars);
// }
// 
// Path: rsimulator-core/src/main/java/com/github/bjuvensjo/rsimulator/core/config/CoreModule.java
// public class CoreModule extends AbstractModule {
//     private final Logger log = LoggerFactory.getLogger(CoreModule.class);
//     private static final CacheManager cacheManager = CacheManager.create();
// 
//     @Provides
//     @Named("rsimulator-core-properties")
//     java.util.Properties provideProperties() {
//         java.util.Properties properties = new java.util.Properties();
//         URL resource = getClass().getResource("/rsimulator.properties");
//         if (resource == null) {
//             properties.setProperty("simulatorCache", "false");
//             properties.setProperty("ignoreXmlNamespaces", "false");
//         } else {
//             try (BufferedInputStream bis = new BufferedInputStream(resource.openStream())) {
//                 properties.load(bis);
//             } catch (Exception e) {
//                 log.error("Error reading properties from: {}", resource.getPath(), e);
//             }
//         }
//         return properties;
//     }
// 
//     @Override
//     protected void configure() {
//         MapBinder<String, Handler> map = MapBinder.newMapBinder(binder(), String.class, Handler.class);
//         map.addBinding("json").to(JsonHandler.class);
//         map.addBinding("txt").to(TxtHandler.class);
//         map.addBinding("xml").to(XmlHandler.class);
// 
//         // ***** Interceptors for cache and script *****
//         Arrays.asList("SimulatorCache", "FileUtilsCache", "PropsCache").forEach(name ->
//                 bind(net.sf.ehcache.Cache.class).annotatedWith(Names.named(name)).toInstance(cacheManager.getCache(name)));
// 
// 
//         SimulatorPropertiesInterceptor simulatorPropertiesInterceptor = new SimulatorPropertiesInterceptor();
//         SimulatorCacheInterceptor simulatorCacheInterceptor = new SimulatorCacheInterceptor();
//         SimulatorScriptInterceptor simulatorScriptInterceptor = new SimulatorScriptInterceptor();
//         FileUtilsCacheInterceptor fileUtilsCacheInterceptor = new FileUtilsCacheInterceptor();
//         PropsCacheInterceptor propsCacheInterceptor = new PropsCacheInterceptor();
// 
//         requestInjection(simulatorPropertiesInterceptor);
//         requestInjection(simulatorCacheInterceptor);
//         requestInjection(simulatorScriptInterceptor);
//         requestInjection(fileUtilsCacheInterceptor);
//         requestInjection(propsCacheInterceptor);
// 
//         // Order is significant
//         bindInterceptor(Matchers.subclassesOf(Simulator.class), Matchers.annotatedWith(Properties.class),
//                 simulatorPropertiesInterceptor);
//         bindInterceptor(Matchers.subclassesOf(Simulator.class), Matchers.annotatedWith(Cache.class),
//                 simulatorCacheInterceptor);
//         bindInterceptor(Matchers.subclassesOf(Simulator.class), Matchers.annotatedWith(Script.class),
//                 simulatorScriptInterceptor);
//         bindInterceptor(Matchers.subclassesOf(FileUtils.class), Matchers.annotatedWith(Cache.class),
//                 fileUtilsCacheInterceptor);
//         bindInterceptor(Matchers.subclassesOf(Props.class), Matchers.annotatedWith(Cache.class),
//                 propsCacheInterceptor);
//     }
// }


// Path: rsimulator-cxf-rt-transport/src/main/java/com/github/bjuvensjo/rsimulator/cxf/transport/RSimulatorTransportFactory.java
import com.github.bjuvensjo.rsimulator.core.Simulator;
import com.github.bjuvensjo.rsimulator.core.config.CoreModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import org.apache.cxf.Bus;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.AbstractTransportFactory;
import org.apache.cxf.transport.Conduit;
import org.apache.cxf.transport.ConduitInitiator;
import org.apache.cxf.transport.http.HTTPTransportFactory;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import java.util.Collections;
import java.util.List;
import java.util.Set;

package com.github.bjuvensjo.rsimulator.cxf.transport;



/**
 * Custom transport factory for CXF that provides Conduits which uses RSimulator CoreModule to match outgoing requests
 * with responses.
 * <p>
 * The purpose is to be able to use the simulator easily and efficient without the requirement of using the http-protocol.
 */
public class RSimulatorTransportFactory extends AbstractTransportFactory implements ConduitInitiator {
    private final Set<String> uriPrefixes;
    private final String rootPath;
    @Inject
    private Simulator simulator;

    /**
     * Minimal constructor that registers itself as a factory for the "http://"-protocol.
     *
     * @param rootPath absolute path where the simulator should use as root when trying to find response
     */
    public RSimulatorTransportFactory(String rootPath) {
        this(rootPath, Collections.singletonList("http://"));
    }

    /**
     * Constructor that accepts a list of protocols and a rootPath.
     *
     * @param rootPath  absolute path where the simulator should use as root when trying to find response
     * @param protocols list of protocols for which this transport factory should be used
     */
    public RSimulatorTransportFactory(String rootPath, List<String> protocols) {
        super(HTTPTransportFactory.DEFAULT_NAMESPACES);
        Injector injector = Guice.createInjector(new CoreModule());