package j3t.wsfolder.doc;

/*v
 * Author: John
 * Created: 01 April 2005 07:32:44
 * Modified: 01 April 2005 07:32:44
 */


/*
To create your own custom template, create a copy of the Custom 
script in Tools/Eventhandlers/Java file/Templates and then modify 
it to create your own template.
*/
import java.io.*;
import java.io.IOException;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.w3c.dom.DocumentFragment;
import org.xml.sax.*;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;

class StringEncMain
{
	
	public static void main (String args[])
	{
		try
		{
			StringEncrypter strEnc = new StringEncrypter("DESede");
			String encElement1= "arg1";
			
			//get file to doc
			Document doc= parseXmlFile("message.xml", false);
			System.out.println("****DOC*******");
			
			//get password element from original file and encrypt
			String passwordValue = getElementTextNodeValue (doc,"wsse:Password",0);
			passwordValue = strEnc.encrypt(passwordValue);
			System.out.println("*****PASSWORD******");
			System.out.println(passwordValue);
			
			//get arg1 element from original file and encrypt
			String argvalue = getElementTextNodeValue (doc,encElement1,0);
			argvalue = strEnc.encrypt(argvalue);			
			System.out.println("*****arg1******");
			System.out.println(argvalue);
			
			
			//create documentFragment for password cipher
			Document docp = makeCipherFragment("EncryptionTemplate.xml","Id","wsse:Password");
			//create documentFragment for arg1
			Document docf = makeCipherFragment("EncryptionTemplate.xml","Id",encElement1);

			//replace elements Value with encoded value
			replaceElementsTextNodevalue(docp,"CipherValue",passwordValue,0);
			
			//replace elements Value with encoded value
			replaceElementsTextNodevalue(docf,"CipherValue",argvalue,0);
			
			// get node 
			Node argnode = getNode (doc, encElement1, 0);
			System.out.println("*********** " + argnode.getLocalName());

			// replace node with arg1 documentFragment
			Node replaced = replaceNode(doc, docf,argnode);
			
			// get node 
			Node pnode = getNode (doc, "wsse:Password", 0);
			System.out.println("*********** " + pnode.getLocalName());

			// replace node with arg1 documentFragment
			Node replacedp = replaceNode(doc, docp,pnode);						
			
			// Print doc to screen
			printDocument(doc);
			
			// Output doc
			doc2file(doc, "encryptedmessage.xml");
			
			
		}catch (Exception e) {}		
	}
	
	
	// Get Node from Document.
	public static Node getNode (Document doc, String tagName, int itemPosition)
	{
		NodeList nodelist = doc.getElementsByTagName(tagName);
		// get node value and encrypt
		Node node = nodelist.item(itemPosition).getFirstChild();
		return node;
	}
	
	
	//create a cipher element from a Template (wsse) setting attribute (ID) elements value
	public static Document makeCipherFragment(String filename, String attributeID, String value)
	{
		// Create a Cipher fragment
		Document doc= parseXmlFile(filename, false);
		Element element= doc.getDocumentElement();
		//set ID attribute to Encrypted element tagname
		element.setAttribute(attributeID,value);
		return doc;
	}
	
	
	
	// returns String value of Elements child
	public static String getElementTextNodeValue (Document doc, String tagName, int childPostion)
	{
		// replace wsse:username with encrypted text
		NodeList nodelist = doc.getElementsByTagName(tagName);
		//get the next node TEXT and set value to encrypted node
		Node node = nodelist.item(childPostion).getFirstChild();
		return node.getNodeValue();
	}
	
	
	
	// replace Elements child text node with a value
	public static void replaceElementsTextNodevalue(Document doc,String tagname, String value, int childposition)
	{
		// replace CipherValue with encrypted text
		NodeList nodelist= doc.getElementsByTagName(tagname);
		//get the next node TEXT and set value to encrypted node
		Node node = nodelist.item(childposition).getFirstChild();
		node.setNodeValue(value);
	}
	
	
	// Dump it! to file
	//http://forum.java.sun.com/thread.jspa?threadID=599716&messageID=3244438
	static void doc2file(Document doc, String filename) throws Exception {
		try {
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StringWriter sw=new StringWriter();
			StreamResult result = new StreamResult(sw);
			transformer.transform(source, result);
			String xmlString=sw.toString();
			PrintWriter pw = new PrintWriter(
				new FileWriter(filename));
			pw.write(xmlString.toString());
			pw.close();
		} 
		catch (Exception e) {
			System.err.println(e.toString());
		}//catch
	}
	
	
	public static Node replaceNode(Document replacedDocument, Document replacingDocument, Node replacedNode){
		
		//Create a documentFragment of the replacingDocument
		DocumentFragment docFrag = replacingDocument.createDocumentFragment();
		Element rootElement = replacingDocument.getDocumentElement();
		docFrag.appendChild(rootElement);    
		
		
		//Import docFrag under the ownership of replacedDocument
		Node replacingNode = ((replacedDocument).importNode(docFrag, true)); 
		
		
		//In order to replace the node need to retrieve replacedNode's parent
		Node replaceNodeParent = replacedNode.getParentNode();
		replaceNodeParent.replaceChild(replacingNode, replacedNode);
		return replacedDocument;
	}
	
	// Prints Dom to Screen
	// throws IOException
	public static void printDocument(Document doc) throws IOException {
		OutputFormat of = new OutputFormat(doc);
		of.setPreserveSpace(true);
		XMLSerializer xs = new XMLSerializer(System.out, of);
		xs.serialize(doc);
		System.out.println();
	}//printDocument
	
	
	
	// Parses an XML file and returns a DOM document.
	// If validating is true, the contents is validated against the DTD
	// specified in the file.
	public static Document parseXmlFile(String filename, boolean validating) {
		try {
			// Create a builder factory
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			factory.setValidating(validating);
			
			// Create the builder and parse the file
			Document doc = factory.newDocumentBuilder().parse(new File(filename));
			return doc;
		} catch (SAXException e) {
			// A parsing error occurred; the xml input is not valid
		} catch (ParserConfigurationException e) {
		} catch (IOException e) {
		}
		return null;
	}//end
	
	
	// Parses a string containing XML and returns a DocumentFragment
	// containing the nodes of the parsed XML.
	public static DocumentFragment parseXml(Document doc, String fragment) {
		// Wrap the fragment in an arbitrary element
		fragment = "<fragment>"+fragment+"</fragment>";
		try {
			// Create a DOM builder and parse the fragment
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			Document d = factory.newDocumentBuilder().parse(new InputSource(new StringReader(fragment)));
			
			// Import the nodes of the new document into doc so that they
			// will be compatible with doc
			Node node = doc.importNode(d.getDocumentElement(), true);
			
			// Create the document fragment node to hold the new nodes
			DocumentFragment docfrag = doc.createDocumentFragment();
			
			// Move the nodes into the fragment
			while (node.hasChildNodes()) {
				docfrag.appendChild(node.removeChild(node.getFirstChild()));
			}
			
			// Return the fragment
			return docfrag;
		} catch (SAXException e) {
			// A parsing error occurred; the xml input is not valid
		} catch (ParserConfigurationException e) {
		} catch (IOException e) {
		}
		return null;
	}//end
	
}