/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package de.christofreichardt.jaxws.securitypriceservice;

import de.christofreichardt.diagnosis.AbstractTracer;
import de.christofreichardt.diagnosis.Traceable;
import de.christofreichardt.diagnosis.TracerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import javax.xml.crypto.Data;
import javax.xml.crypto.OctetStreamData;
import javax.xml.crypto.URIDereferencer;
import javax.xml.crypto.URIReference;
import javax.xml.crypto.URIReferenceException;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dom.DOMURIReference;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 *
 * @author Christof Reichardt
 */
public class SoapBodyDereferencer implements URIDereferencer, Traceable {
  private final XMLSerializer xmlSerializer = new XMLSerializer();

  @Override
  public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {
    AbstractTracer tracer = getCurrentTracer();
    tracer.entry("Data", this, "dereference(URIReference uriReference, XMLCryptoContext context)");
    
    try {
      if (!(uriReference instanceof DOMURIReference))
        throw new IllegalArgumentException("Need a DOMURIReference.");
      
      DOMURIReference domURIReference = (DOMURIReference) uriReference;
      Element documentElement = domURIReference.getHere().getOwnerDocument().getDocumentElement();
      NodeList elements = documentElement.getElementsByTagNameNS("http://schemas.xmlsoap.org/soap/envelope/", "Body");
      
      if (elements.getLength() != 1)
        throw new URIReferenceException("Need a Soap body.");
      
      Node soapBody = elements.item(0);
      ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
      this.xmlSerializer.serialize(soapBody, outputStream);
      ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
      
      return new OctetStreamData(inputStream);
    }
    finally {
      tracer.wayout();
    }
  }

  @Override
  public AbstractTracer getCurrentTracer() {
    return TracerFactory.getInstance().getCurrentPoolTracer();
  }

}
