package com.github.bjuvensjo.rsimulator.core.handler.regexp; import com.google.inject.Inject; import com.github.bjuvensjo.rsimulator.core.Handler; import com.github.bjuvensjo.rsimulator.core.SimulatorResponse; import com.github.bjuvensjo.rsimulator.core.SimulatorResponseImpl; import com.github.bjuvensjo.rsimulator.core.util.FileUtils; import com.github.bjuvensjo.rsimulator.core.util.Props; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; import static com.github.bjuvensjo.rsimulator.core.config.Constants.REQUEST; import static com.github.bjuvensjo.rsimulator.core.config.Constants.RESPONSE; /** * AbstractHandler implements what is common for regular expression handlers. * * @author Magnus Bjuvensjö * @see Handler */ public abstract class AbstractHandler implements Handler { private static final String PROPERTIES_PATTERN = REQUEST + ".*"; private Logger log = LoggerFactory.getLogger(AbstractHandler.class); @Inject private FileUtils fileUtils; @Inject private Props props; public Optional<SimulatorResponse> findMatch(String rootPath, String rootRelativePath, String request) { String path = rootPath.concat(rootRelativePath); log.debug("path: {}", path); Optional<SimulatorResponse> result = fileUtils.findRequests(Paths.get(path), getExtension()) .stream() .map(candidatePath -> { SimulatorResponse simulatorResponse = null; String candidateRequest = fileUtils.read(candidatePath); Matcher matcher = getMatcher(request, candidateRequest); if (matcher.matches()) { String response = getResponse(candidatePath, matcher); Optional<Properties> properties = getProperties(candidatePath); simulatorResponse = new SimulatorResponseImpl(response, properties, candidatePath); } return Optional.ofNullable(simulatorResponse); }) .filter(simulatorResponse -> simulatorResponse.isPresent()) .findFirst() .get(); return result; } /** * Returns the supported file extension. * * @return the supported file extension */ protected abstract String getExtension(); /** * Returns the specified request formatted for matching. * * @param request the request * @return the specified request formatted for matching */ protected abstract String format(String request); /** * Returns the specified request escaped for matching. * * @param request the request * @param isCandidate the isCandidate * @return the specified request escaped for matching */ protected abstract String escape(String request, boolean isCandidate); private Matcher getMatcher(String request, String candidate) { String formattedRequest = format(request); String formattedCandidate = format(candidate); String escapedRequest = escape(formattedRequest, false); String escapedCandidate = escape(formattedCandidate, true); Pattern p = Pattern.compile(escapedCandidate); return p.matcher(escapedRequest); } private String getResponse(Path candidatePath, Matcher matcher) { String name = candidatePath.getFileName().toString().replaceFirst(REQUEST, RESPONSE); Path responsePath = candidatePath.resolveSibling(name); String response = fileUtils.read(responsePath); for (int j = 1; j <= matcher.groupCount(); j++) { response = response.replaceAll("[$]+[{]+" + j + "[}]+", matcher.group(j)); } log.debug("Response: [{}, {}]", response, responsePath); return response; } private Optional<Properties> getProperties(Path candidatePath) { String name = candidatePath.getFileName().toString().replaceFirst(PROPERTIES_PATTERN, ".properties"); Path propertiesPath = candidatePath.resolveSibling(name); Optional<Properties> properties = props.getProperties(propertiesPath); log.debug("Properties: [{}, {}]", properties, propertiesPath); return properties; } }