package com.subgraph.vega.http.conditions;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import com.subgraph.vega.api.http.conditions.ConditionType;
import com.subgraph.vega.api.http.conditions.IHttpBooleanCondition;
import com.subgraph.vega.api.http.conditions.IHttpConditionSet;
import com.subgraph.vega.api.http.conditions.TransactionDirection;
import com.subgraph.vega.internal.http.conditions.ConditionTypeDomainName;
import com.subgraph.vega.internal.http.conditions.ConditionTypeRequestHeader;
import com.subgraph.vega.internal.http.conditions.ConditionTypeRequestMethod;
import com.subgraph.vega.internal.http.conditions.ConditionTypeResponseHeader;
import com.subgraph.vega.internal.http.conditions.ConditionTypeResponseStatus;
public class HttpConditionSet implements IHttpConditionSet {
private final ArrayList<IHttpBooleanCondition> conditionList = new ArrayList<IHttpBooleanCondition>();
@Override
public IHttpBooleanCondition createCondition(ConditionType conditionType, Enum<?> comparisonType, String pattern, boolean isEnabled) {
IHttpBooleanCondition condition = null;
switch (conditionType) {
case DOMAIN_NAME:
condition = new ConditionTypeDomainName(comparisonType, pattern, isEnabled);
break;
case REQUEST_METHOD:
condition = new ConditionTypeRequestMethod(comparisonType, pattern, isEnabled);
break;
case REQUEST_HEADER:
condition = new ConditionTypeRequestHeader(comparisonType, pattern, isEnabled);
break;
case RESPONSE_HEADER:
condition = new ConditionTypeResponseHeader(comparisonType, pattern, isEnabled);
break;
case RESPONSE_STATUS:
condition = new ConditionTypeResponseStatus(comparisonType, pattern, isEnabled);
break;
default:
throw new IllegalArgumentException("Unknown condition type " + conditionType);
}
conditionList.add(condition);
return condition;
}
@Override
public void removeCondition(IHttpBooleanCondition condition) {
conditionList.remove(condition);
}
@Override
public int getBreakpontIdxOf(IHttpBooleanCondition condition) {
return conditionList.indexOf(condition);
}
@Override
public int getConditionCnt() {
return conditionList.size();
}
@Override
public IHttpBooleanCondition[] getConditions() {
return conditionList.toArray(new IHttpBooleanCondition[conditionList.size()]);
}
private String escapeString(String s) {
final StringBuilder builder = new StringBuilder();
final StringCharacterIterator iter = new StringCharacterIterator(s);
for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
if (c == '@' || c == '!' || c == '\\') {
builder.append('\\');
}
builder.append(c);
}
return builder.toString();
}
private String unescapeString(String s) {
final StringBuilder builder = new StringBuilder();
final StringCharacterIterator iter = new StringCharacterIterator(s);
for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next()) {
if (c == '\\') {
c = iter.next();
if (c == CharacterIterator.DONE) {
throw new IllegalArgumentException("Invalid quoted character");
}
}
builder.append(c);
}
return builder.toString();
}
@Override
public String serialize() {
final StringBuilder builder = new StringBuilder();
for (int idx = 0; idx < conditionList.size(); idx++) {
if (idx > 0) {
builder.append("!!");
}
IHttpBooleanCondition condition = conditionList.get(idx);
builder.append(escapeString(condition.getType().name()));
builder.append("@@");
builder.append(escapeString(condition.getComparisonType().name()));
builder.append("@@");
builder.append(escapeString(condition.getPattern()));
}
return builder.toString();
}
@Override
public void unserialize(String str) {
conditionList.clear();
if (str != "") {
final String[] conditions = str.split("!!");
for (int idx = 0; idx < conditions.length; idx++) {
final String[] fields = conditions[idx].split("@@");
if (fields.length != 3) {
conditionList.clear();
throw new IllegalArgumentException("Bad preferences string");
}
ConditionType conditionType = ConditionType.valueOf(unescapeString(fields[0]));
Enum<?> comparisonType = Enum.valueOf((Class) conditionType.getComparisonTypeClass(), unescapeString(fields[1]));
String pattern = fields[2];
createCondition(conditionType, comparisonType, pattern, true);
}
}
}
@Override
public boolean test(HttpRequest request, HttpResponse response) {
for (IHttpBooleanCondition condition: conditionList) {
if (condition.getIsEnabled() == true) {
if ((condition.getType().getMask() & TransactionDirection.DIRECTION_REQUEST.getMask()) != 0) {
return condition.test(request);
} else {
return condition.test(response);
}
}
}
return false;
}
}