
import java.util.Hashtable;

import oasis.names.tc.dss._1_0.core.wsdl.SOAPport;
import oasis.names.tc.dss._1_0.core.wsdl.digitalSignatureServiceClient;

import org.apache.xmlbeans.XmlAnyURI;
import org.apache.xmlbeans.XmlBase64Binary;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.w3.x2000.x09.xmldsig.KeyInfoType;
import org.w3.x2000.x09.xmldsig.X509DataType;

import x0CoreSchema.oasisNamesTcDss1.DocumentType;
import x0CoreSchema.oasisNamesTcDss1.InlineXMLType;
import x0CoreSchema.oasisNamesTcDss1.SignRequestDocument;
import x0CoreSchema.oasisNamesTcDss1.SignResponseDocument;
import x0CoreSchema.oasisNamesTcDss1.InputDocumentsDocument.InputDocuments;
import x0CoreSchema.oasisNamesTcDss1.KeySelectorDocument.KeySelector;
import x0CoreSchema.oasisNamesTcDss1.OptionalInputsDocument.OptionalInputs;
import x0CoreSchema.oasisNamesTcDss1.SignRequestDocument.SignRequest;


public class CreacioSignatura {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {

		// Configuració local
		Utils.setProxyConfiguration();
		
		// Dades de prova

		// Certificat amb que es generarà la signatura o timestamp
		// si ataquem a PSIS, nomes podrem signar utilitzant certificats que PSIS tingui
		// enmmagatzemats amb la clau privada!
		
		byte[] certificate = Utils.readBase64File("certificats/certificate.dat");
		
		
		// Document en B64 a signar
		//byte[] doc = Utils.readBase64File("");

		// XML a signar
		String xml = Utils.readXmlFile("data/create-sig.xml");

		// Tipus de signatura disponibles
		// Signatura CAdES: 					http://uri.etsi.org/01733/v1.6.3#
		// Signatura CMS: 						urn:ietf:rfc:3852
		// Signatura XMLDsig: 					urn:ietf:rfc:3275
		// Signatura XAdES: 					http://uri.etsi.org/01903/1.2.2#
		String type = "urn:ietf:rfc:3275";

		// Inicialització del client
		digitalSignatureServiceClient proxy = new digitalSignatureServiceClient();
		SOAPport port = proxy.getdssPortSoap("http://psis.catcert.net/psis/catcert/dss");

		// Composició del missatge

		// Definició dels namespaces correctes
		Hashtable prefixes = new Hashtable();
		prefixes.put("urn:oasis:names:tc:dss:1.0:core:schema","dss");
		prefixes.put("http://www.w3.org/2000/09/xmldsig#","ds");

		XmlOptions options= new XmlOptions();	
		options.setSaveSuggestedPrefixes(prefixes);

		// Creació del missatge DSS
		SignRequestDocument requestDocument = SignRequestDocument.Factory.newInstance(options);

		SignRequest request = requestDocument.addNewSignRequest();
		request.setProfile("urn:oasis:names:tc:dss:1.0:profiles:XSS");

		// Creació de l'element amb el document a signar (en format XML)
		DocumentType document = DocumentType.Factory.newInstance();

		InlineXMLType inline = document.addNewInlineXML();
		inline.set(XmlObject.Factory.parse(xml));
		
		InputDocuments inpDocuments = InputDocuments.Factory.newInstance();
		inpDocuments.setDocumentArray(new DocumentType[] { document });

		request.setInputDocuments(inpDocuments);

		// Creació de l'element amb el document a signar (en format base64)
		// InputDocuments inpDocuments = request.addNewInputDocuments();

		// Base64Data b64data = Base64Data.Factory.newInstance();
		// b64data.setByteArrayValue(doc);

		// DocumentType document = inpDocuments.addNewDocument();
		// document.setBase64Data(b64data);

		// Creació de l'element amb els paràmetres opcionals necessaris per
		// consultar
		OptionalInputs optional = request.addNewOptionalInputs();

		KeySelector selector = optional.addNewKeySelector();

		KeyInfoType key = selector.addNewKeyInfo();

		X509DataType x509data = key.addNewX509Data();

		XmlBase64Binary b64certificate = x509data.addNewX509Certificate();
		b64certificate.setByteArrayValue(certificate);

		XmlAnyURI any = optional.addNewSignatureType();
		any.setStringValue(type);

		// Visualització de la petició
		System.out.println(requestDocument.xmlText(options));

		// Execució del servei
		SignResponseDocument responseDocument = port.sign(requestDocument);

		// visualització de la resposta
		System.out.println(responseDocument.xmlText(options));

	}

}
