package org.cagrid.dorian.service.wsrf;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor;
import org.apache.commons.io.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/*
* http://cxf.apache.org/docs/interceptors.html
* http://www.mastertheboss.com/jboss-web-services/apache-cxf-interceptors
*/
public abstract class AbstractSamlCanonicalizerInterceptor extends AbstractPhaseInterceptor<Message> {
public AbstractSamlCanonicalizerInterceptor(String phase) {
super(phase);
}
private static final Logger LOG = LoggerFactory.getLogger(AbstractSamlCanonicalizerInterceptor.class);
protected String changeOutboundMessage(String currentEnvelope) {
return canonicalize(currentEnvelope);
}
protected String changeInboundMessage(String currentEnvelope) {
return canonicalize(currentEnvelope);
}
protected String canonicalize(String string) {
Canonicalizer c;
try {
c = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
return new String(c.canonicalize(string.getBytes()));
} catch (InvalidCanonicalizerException e) {
LOG.warn("Skipping canonicalization due to invalid canonicalizer:"
+ Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS, e);
} catch (CanonicalizationException e) {
LOG.warn("Skipping canonicalization due to canonicalization exception:" + e.getMessage(), e);
} catch (ParserConfigurationException e) {
LOG.warn("Skipping canonicalization due to parser exception:" + e.getMessage(), e);
} catch (IOException e) {
LOG.warn("Skipping canonicalization due to IO exception:" + e.getMessage(), e);
} catch (SAXException e) {
LOG.warn("Skipping canonicalization due to Sax exception:" + e.getMessage(), e);
}
return null;
}
protected abstract boolean doesOutboundMessageApply(Message message);
protected abstract boolean doesInboundMessageApply(Message message);
public void handleMessage(Message message) {
boolean isOutbound = false;
isOutbound = message == message.getExchange().getOutMessage()
|| message == message.getExchange().getOutFaultMessage();
if (isOutbound && doesOutboundMessageApply(message)) {
OutputStream os = message.getContent(OutputStream.class);
CachedStream cs = new CachedStream();
message.setContent(OutputStream.class, cs);
message.getInterceptorChain().doIntercept(message);
try {
cs.flush();
IOUtils.closeQuietly(cs);
CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class);
String currentEnvelopeMessage = IOUtils.toString(csnew.getInputStream(), "UTF-8");
csnew.flush();
IOUtils.closeQuietly(csnew);
if (LOG.isDebugEnabled()) {
LOG.debug("Outbound message: " + currentEnvelopeMessage);
}
String res = changeOutboundMessage(currentEnvelopeMessage);
if (res != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Outbound message has been changed: " + res);
}
}
res = res != null ? res : currentEnvelopeMessage;
InputStream replaceInStream = IOUtils.toInputStream(res, "UTF-8");
IOUtils.copy(replaceInStream, os);
replaceInStream.close();
IOUtils.closeQuietly(replaceInStream);
os.flush();
message.setContent(OutputStream.class, os);
IOUtils.closeQuietly(os);
} catch (IOException ioe) {
LOG.warn("Unable to perform change.", ioe);
throw new RuntimeException(ioe);
}
} else if (doesInboundMessageApply(message)) {
try {
InputStream is = message.getContent(InputStream.class);
String currentEnvelopeMessage = IOUtils.toString(is, "UTF-8");
IOUtils.closeQuietly(is);
if (LOG.isDebugEnabled()) {
LOG.debug("Inbound message: " + currentEnvelopeMessage);
}
String res = changeInboundMessage(currentEnvelopeMessage);
if (res != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Inbound message has been changed: " + res);
}
}
res = res != null ? res : currentEnvelopeMessage;
is = IOUtils.toInputStream(res, "UTF-8");
message.setContent(InputStream.class, is);
IOUtils.closeQuietly(is);
} catch (IOException ioe) {
LOG.warn("Unable to perform change.", ioe);
throw new RuntimeException(ioe);
}
}
}
public void handleFault(Message message) {
}
private class CachedStream extends CachedOutputStream {
public CachedStream() {
super();
}
protected void doFlush() throws IOException {
currentStream.flush();
}
protected void doClose() throws IOException {
}
protected void onWrite() throws IOException {
}
}
}