package gov.samhsa.acs.common.cxf;
import static java.util.stream.Collectors.joining;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;
import java.util.function.Supplier;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ContentTypeRebuildingOutboundSoapInterceptor extends
AbstractSoapInterceptor {
private static final String CONTENT_TYPE = "Content-Type";
private static final String SEMICOLON = ";";
private static final String EQUAL = "=";
private static final String SPACE = " ";
private static final String EMPTY = "";
private static final String BACKSLASH = "\\";
private static final String DOUBLE_QUOTE = "\"";
private static final int IDX_KEY = 0;
private static final int IDX_VALUE = 1;
private static final String SEMICOLON_WITH_SPACE = SEMICOLON + SPACE;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public ContentTypeRebuildingOutboundSoapInterceptor() {
super(Phase.WRITE);
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
debug(() -> message.toString());
debug(() -> new StringBuilder().append(CONTENT_TYPE)
.append(" before modification: ")
.append(message.get(CONTENT_TYPE).toString()).toString());
final String contentType = (String) message.get(CONTENT_TYPE);
final List<Pair> contentTypeList = new ArrayList<>();
try (Scanner scanner = new Scanner(contentType)) {
scanner.useDelimiter(SEMICOLON);
while (scanner.hasNext()) {
final String next = scanner.next();
final String[] split = next.split(EQUAL);
contentTypeList.add(new Pair(clean(split, IDX_KEY),
split.length > IDX_VALUE ? Optional.of(clean(split,
IDX_VALUE)) : Optional.empty()));
}
}
final String correctedContentType = contentTypeList
.stream()
.map(ContentTypeRebuildingOutboundSoapInterceptor::toCorrectedContentType)
.collect(joining(SEMICOLON_WITH_SPACE));
debug(() -> new StringBuilder().append(CONTENT_TYPE)
.append(" after modification: ").append(correctedContentType)
.toString());
message.put(CONTENT_TYPE, correctedContentType);
}
private final void debug(Supplier<String> msg) {
if (this.logger.isDebugEnabled()) {
logger.debug(msg.get());
}
}
private static final String clean(String[] split, int idx) {
return split[idx].replace(DOUBLE_QUOTE, EMPTY)
.replace(BACKSLASH, EMPTY).replace(SPACE, EMPTY);
}
private static final String toCorrectedContentType(Pair entry) {
return new StringBuilder().append(entry.getKey())
.append(wrap(entry.getValue().orElse(EMPTY))).toString();
}
private static final String wrap(String value) {
return EMPTY.equals(value) ? value : new StringBuilder().append(EQUAL)
.append(DOUBLE_QUOTE).append(value).append(DOUBLE_QUOTE)
.toString();
}
private class Pair {
private final String key;
private final Optional<String> value;
public Pair(String key, Optional<String> value) {
super();
this.key = key;
this.value = value;
}
@Override
public String toString() {
return new StringBuilder().append(this.key).append("=")
.append(this.value.orElse("")).toString();
}
private String getKey() {
return key;
}
private Optional<String> getValue() {
return value;
}
}
}