package org.mockserver.mock;
import com.google.common.annotations.VisibleForTesting;
import org.mockserver.client.serialization.Base64Converter;
import org.mockserver.client.serialization.ExpectationSerializer;
import org.mockserver.matchers.HttpRequestMatcher;
import org.mockserver.matchers.MatcherBuilder;
import org.mockserver.matchers.TimeToLive;
import org.mockserver.matchers.Times;
import org.mockserver.model.Action;
import org.mockserver.model.HttpRequest;
import org.mockserver.model.ObjectWithReflectiveEqualsHashCodeToString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author jamesdbloom
*/
public class MockServerMatcher extends ObjectWithReflectiveEqualsHashCodeToString {
protected final List<Expectation> expectations = Collections.synchronizedList(new ArrayList<Expectation>());
private Logger requestLogger = LoggerFactory.getLogger("REQUEST");
public Expectation when(HttpRequest httpRequest) {
return when(httpRequest, Times.unlimited(), TimeToLive.unlimited());
}
public Expectation when(final HttpRequest httpRequest, Times times, TimeToLive timeToLive) {
Expectation expectation;
if (times.isUnlimited()) {
Collection<Expectation> existingExpectationsWithMatchingRequest = new ArrayList<Expectation>();
for (Expectation potentialExpectation : new ArrayList<Expectation>(this.expectations)) {
if (potentialExpectation.contains(httpRequest)) {
existingExpectationsWithMatchingRequest.add(potentialExpectation);
}
}
if (!existingExpectationsWithMatchingRequest.isEmpty()) {
for (Expectation existingExpectation : existingExpectationsWithMatchingRequest) {
existingExpectation.setNotUnlimitedResponses();
}
expectation = new Expectation(httpRequest, times, timeToLive);
} else {
expectation = new Expectation(httpRequest, Times.unlimited(), timeToLive);
}
} else {
expectation = new Expectation(httpRequest, times, timeToLive);
}
this.expectations.add(expectation);
return expectation;
}
public Action retrieveAction(HttpRequest httpRequest) {
for (Expectation expectation : new ArrayList<Expectation>(this.expectations)) {
if (expectation.matches(httpRequest)) {
expectation.decrementRemainingMatches();
if (!expectation.hasRemainingMatches()) {
if (this.expectations.contains(expectation)) {
this.expectations.remove(expectation);
}
}
return expectation.getAction();
} else if (!expectation.isStillAlive()) {
if (this.expectations.contains(expectation)) {
this.expectations.remove(expectation);
}
}
}
return null;
}
public void clear(HttpRequest httpRequest) {
if (httpRequest != null) {
HttpRequestMatcher httpRequestMatcher = new MatcherBuilder().transformsToMatcher(httpRequest);
for (Expectation expectation : new ArrayList<Expectation>(this.expectations)) {
if (httpRequestMatcher.matches(expectation.getHttpRequest(), true)) {
if (this.expectations.contains(expectation)) {
this.expectations.remove(expectation);
}
}
}
} else {
reset();
}
}
public void reset() {
this.expectations.clear();
}
public void dumpToLog(HttpRequest httpRequest) {
ExpectationSerializer expectationSerializer = new ExpectationSerializer();
if (httpRequest != null) {
for (Expectation expectation : new ArrayList<Expectation>(this.expectations)) {
if (expectation.matches(httpRequest)) {
requestLogger.warn(cleanBase64Response(expectationSerializer.serialize(expectation)));
}
}
} else {
for (Expectation expectation : new ArrayList<Expectation>(this.expectations)) {
requestLogger.warn(cleanBase64Response(expectationSerializer.serialize(expectation)));
}
}
}
@VisibleForTesting
String cleanBase64Response(String serializedExpectation) {
Pattern base64ResponseBodyPattern = Pattern.compile("[\\s\\S]*\\\"httpResponse\\\"\\s*\\:\\s*\\{[\\s\\S]*\\\"body\\\"\\s*\\:\\s*\\\"(([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==))\\\"[\\s\\S]*");
Matcher matcher = base64ResponseBodyPattern.matcher(serializedExpectation);
if (matcher.find()) {
return serializedExpectation.replace(matcher.group(1), new String(Base64Converter.base64StringToBytes(matcher.group(1))));
} else {
return serializedExpectation;
}
}
public Expectation[] retrieveExpectations(HttpRequest httpRequest) {
List<Expectation> expectations = new ArrayList<Expectation>();
if (httpRequest != null) {
for (Expectation expectation : new ArrayList<Expectation>(this.expectations)) {
if (expectation.matches(httpRequest)) {
expectations.add(expectation);
}
}
} else {
expectations.addAll(this.expectations);
}
return expectations.toArray(new Expectation[expectations.size()]);
}
}