// 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/SimulatorResponse.java
// public interface SimulatorResponse {
// 
//     /**
//      * Returns the properties of a specific test data request and response pair. If the name of the test data request
//      * file for instance is Test1Request.xml, the properties file must be named Test1.properties. For supported
//      * properties, see *PropertiesInterceptor classes.
//      *
//      * @return the properties of a specific test data request and response pair
//      */
//     Optional<Properties> getProperties();
// 
//     /**
//      * Sets the specified properties.
//      *
//      * @param properties the properties to set
//      */
//     void setProperties(Optional<Properties> properties);
// 
//     /**
//      * Returns the test data response.
//      *
//      * @return the test data response
//      */
//     String getResponse();
// 
//     /**
//      * Sets the specified response.
//      *
//      * @param response the response to set
//      */
//     void setResponse(String response);
// 
//     /**
//      * Returns the matching request path.
//      *
//      * @return the matching request path
//      */
//     Path getMatchingRequest();
// 
//     /**
//      * Sets the specified path.
//      *
//      * @param path the path to set
//      */
//     void setMatchingRequest(Path path);
// }


import com.github.bjuvensjo.rsimulator.core.Simulator;
import com.github.bjuvensjo.rsimulator.core.SimulatorResponse;
import org.apache.cxf.Bus;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.AbstractConduit;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.Properties;
import java.util.logging.Logger;
        }
    }

    private boolean isInbound(Message message) {
        return Boolean.TRUE.equals(message.get("org.apache.cxf.message.inbound"));
    }

    private Message createResponseMessage(Message requestMessage) throws IOException {
        Message responseMessage = new MessageImpl();
        OutputStream os = requestMessage.getContent(OutputStream.class);
        String encoding = getEncoding(requestMessage);
        String request = toString((CachedOutputStream) os, encoding);
        Optional<SimulatorResponse> response = findResponse(getPath(requestMessage), request);
        if (response.isPresent()) {
            responseMessage.setContent(InputStream.class, toInputStream(response.get().getResponse(), encoding));
            Optional<Properties> properties = response.get().getProperties();
            int responseCode = 200;
            if (properties != null && properties.isPresent() && properties.get().containsKey("responseCode")) {
                responseCode = Integer.parseInt((String) properties.get().get("responseCode"));
            }
            updateMessageExchange(requestMessage, responseMessage, responseCode);
        }
        return responseMessage;
    }

    private String getEncoding(Message message) {
        return (String) message.get("org.apache.cxf.message.Message.ENCODING");
    }

    @SuppressWarnings("unchecked")
// 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/SimulatorResponse.java
// public interface SimulatorResponse {
// 
//     /**
//      * Returns the properties of a specific test data request and response pair. If the name of the test data request
//      * file for instance is Test1Request.xml, the properties file must be named Test1.properties. For supported
//      * properties, see *PropertiesInterceptor classes.
//      *
//      * @return the properties of a specific test data request and response pair
//      */
//     Optional<Properties> getProperties();
// 
//     /**
//      * Sets the specified properties.
//      *
//      * @param properties the properties to set
//      */
//     void setProperties(Optional<Properties> properties);
// 
//     /**
//      * Returns the test data response.
//      *
//      * @return the test data response
//      */
//     String getResponse();
// 
//     /**
//      * Sets the specified response.
//      *
//      * @param response the response to set
//      */
//     void setResponse(String response);
// 
//     /**
//      * Returns the matching request path.
//      *
//      * @return the matching request path
//      */
//     Path getMatchingRequest();
// 
//     /**
//      * Sets the specified path.
//      *
//      * @param path the path to set
//      */
//     void setMatchingRequest(Path path);
// }


// Path: rsimulator-cxf-rt-transport/src/main/java/com/github/bjuvensjo/rsimulator/cxf/transport/RSimulatorConduit.java
import com.github.bjuvensjo.rsimulator.core.Simulator;
import com.github.bjuvensjo.rsimulator.core.SimulatorResponse;
import org.apache.cxf.Bus;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageImpl;
import org.apache.cxf.service.Service;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.transport.AbstractConduit;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.Properties;
import java.util.logging.Logger;

        }
    }

    private boolean isInbound(Message message) {
        return Boolean.TRUE.equals(message.get("org.apache.cxf.message.inbound"));
    }

    private Message createResponseMessage(Message requestMessage) throws IOException {
        Message responseMessage = new MessageImpl();
        OutputStream os = requestMessage.getContent(OutputStream.class);
        String encoding = getEncoding(requestMessage);
        String request = toString((CachedOutputStream) os, encoding);
        Optional<SimulatorResponse> response = findResponse(getPath(requestMessage), request);
        if (response.isPresent()) {
            responseMessage.setContent(InputStream.class, toInputStream(response.get().getResponse(), encoding));
            Optional<Properties> properties = response.get().getProperties();
            int responseCode = 200;
            if (properties != null && properties.isPresent() && properties.get().containsKey("responseCode")) {
                responseCode = Integer.parseInt((String) properties.get().get("responseCode"));
            }
            updateMessageExchange(requestMessage, responseMessage, responseCode);
        }
        return responseMessage;
    }

    private String getEncoding(Message message) {
        return (String) message.get("org.apache.cxf.message.Message.ENCODING");
    }

    @SuppressWarnings("unchecked")
    private Optional<SimulatorResponse> findResponse(String path, String request) {