import java.io.*;
import java.util.Enumeration;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.http.*;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.dom.DocumentImpl;
import org.apache.xalan.xpath.xdom.XercesLiaison;
import org.apache.xalan.xslt.*;
//--------

/* 
 * Linus Sphinx's Write Xml Servlet - attempts to modify xml file with contents of request parameters
 * Copyright Linus Sphinx 1999 (c) all rights reserved
 */

public class wxml extends HttpServlet
{ 
public String XDocRoot; // location of doc root in initArgs from zone.properties
public String XDocDir; // directory added to XDocRoot where XDocName is
public String XMap; // .map dir to be added to xdocroot
public String XDad; // name of another file to touch upon successful edit of xdoc
public String XAct; // delete node if equal "del"
public String XDocName; // name on xml file to work on in XDocRoot
public String XItem; // sub item to edit
public String XPTag;   // tag to match on
public String XData; // contents matching above tag ie: <XPTag>XData<XPTag> matches it's time to build a form
public String Title = "Linus' Xml Wizard"; // title of html pages


    public void doGet( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        writeXml( request, response );
    }

    public void doPost( HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
        writeXml( request, response );
    }

    public void writeXml (HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        Document doc;
        int level = 0;
        String title = "Write XML Servlet";
        String myArgs = "xdoc xitem xptag xdata xstyle xdad xact xdir xmap";
	ServletContext context = this.getServletContext();
        Enumeration e = request.getParameterNames();
        PrintWriter out = response.getWriter();

        response.setContentType("text/html");
        XMap = request.getParameter( "xmap" );
        XDocDir = request.getParameter( "xdir" );
        XDocRoot = context.getInitParameter( "docroot" );
        if ( XDocDir != null )
        {
            XDocRoot = XDocRoot + XDocDir + "/";
        }
        if ( XMap != null && !XMap.equals( "addamap" ))
        {
            if ( XDocDir != null )
                XDocRoot = XDocRoot + XDocDir + "/" + XMap + ".map/";
            else
                XDocRoot = XDocRoot + XMap + ".map/";
        }

        XDocName = request.getParameter( "xdoc" );
        XItem = request.getParameter( "xitem" );
        XPTag = request.getParameter( "xptag" );
        XData = request.getParameter( "xdata" );
        XDad = request.getParameter( "xdad" );
        XAct = request.getParameter( "xact" );

		if ( XDocName == null )
		{
			selectXDoc( request, out );
			return;
		}

        out.println("<HTML><HEAD><TITLE>");
        out.println(title);
        out.println("</TITLE></HEAD><BODY bgcolor=\"#FFFFFF\">");
        out.println("<H4>" + title + "</H4>");
        out.println("<br />Filename: " + XDocName );
/*
            out.println("<p /><a href=\"/emonster/index.xml\">Home</a>");
            out.println("</BODY></HTML>");
            out.close();
		return;
*/
        // open and parse doc
        try 
		{
            DOMParser parser = new DOMParser();
            parser.parse(XDocRoot + XDocName + ".xml" );
            doc = parser.getDocument();
            doc.getDocumentElement().normalize();

        // get a node list of xitems
            org.w3c.dom.NodeList nodeList = doc.getElementsByTagName( XItem );

        // find which one is to be altered
            int x = findMyNode( nodeList );
			if (!( XAct != null && XAct.compareTo((String)"del")== 0 ))
			{
				if ( x < 0 ) // add
           	 	{
                	x = 0;
                	org.w3c.dom.Node refNode = nodeList.item(x);
					org.w3c.dom.Node newNode = doc.createElement( XItem );
   		            org.w3c.dom.Node dadNode = doc.getDocumentElement();
   		            dadNode.insertBefore( newNode, refNode );
                	out.println( "<br />Adding #" + x );
            	}
            	else // update
                out.println("<br />Updating #" + x);
            	org.w3c.dom.Node target = nodeList.item(x);
            	while( e.hasMoreElements())
            	{
                	String s = (String)e.nextElement();
                	if ( myArgs.indexOf( s ) < 0 ) // it's not one of ours
                	{
                    	String v = (String)request.getParameter( s );
                    	updateXItem( doc, target, s, v, out );
                	}
            	} 
			}    
           	else if ( x >= 0 ) // deleting
			{
				out.println( "<br />Deleting #" + x );
            	org.w3c.dom.Node target = nodeList.item(x);
   		        org.w3c.dom.Node dadNode = doc.getDocumentElement();
				dadNode.removeChild( target );
			}

            // write out our tree
            FileWriter xFile = new FileWriter( XDocRoot + XDocName + ".xml", false);
            PrintWriter newFile = new PrintWriter(xFile);
            printTree( doc.getDocumentElement(), newFile, level );
            newFile.close();
            if (XDad != null)
            {
            	out.println("<br />Touching " + XDad );
                RandomAccessFile xd = new RandomAccessFile( XDocRoot + XDad, "rw");
                int z = xd.read();
                xd.seek(0L);
                xd.write(z);
                xd.close();
            }
            Date now = new Date();
            out.println("<br />at " + now.toString());
            out.println("<p /><a href=\"/emonster/index.xml\">Home</a>");
            out.println("</BODY></HTML>");
            out.close();

        } catch (SAXParseException spe) {
           // Error generated by the parser
           out.println ("\n** Parsing error" + ", line " + spe.getLineNumber () + ", uri " + spe.getSystemId ());
           out.println("   " + spe.getMessage() );

           // Use the contained exception, if any
           Exception  x = spe;
           if (spe.getException() != null)
               x = spe.getException();
           x.printStackTrace();
           return;

        } catch (SAXException sxe) {
           // Error generated by this application
           // (or a parser-initialization error)
           Exception  x = sxe;
           if (sxe.getException() != null)
               x = sxe.getException();
           x.printStackTrace();
           return;

        } catch (IOException ioe) {
           // I/O error
           ioe.printStackTrace();
           return;
        }
    } // eo writeXml

// ------------------
// update a node by creating new one from doc named str filled with val printed to out
// swap if we can find it or add if not
// ------------------
    void updateXItem( Document doc, org.w3c.dom.Node node, String str, String val, PrintWriter out )
    {
        boolean found = false;
        org.w3c.dom.Element newnode = null;
        org.w3c.dom.Element newdata = null;
        out.println("<br />" + str + " = " + val );
        org.w3c.dom.NodeList kids = node.getChildNodes();
        for (int i=0; i < kids.getLength(); i++ ) // for each child of our xitem
        {
            org.w3c.dom.Node kid = kids.item(i);
            int type = kid.getNodeType();
            String name = kid.getNodeName(); 
            if ( type == 1 && str.equals( name )) // match param so make new one, attach param value and switch
            {
                 found = true;
                 newnode = doc.createElement( str );
                 newnode.appendChild( doc.createTextNode( val ));
                 node.replaceChild( newnode, kid );
            }
        }
        if ( !found )
        {
            newnode = doc.createElement( str );
            newnode.appendChild( doc.createTextNode( val ));
            node.appendChild( newnode );
        }
    } // eo updateXItem

// ------------------
// find a node whose name equals xitem and content equals xptag
// ------------------
    int findMyNode( org.w3c.dom.NodeList nodeListi ) throws java.io.IOException,
                                                            java.net.MalformedURLException,
                                                            org.xml.sax.SAXException
    {
        int type;
        int x;
        String name;
        String val;
        org.w3c.dom.Node nodei;
        org.w3c.dom.Node nodej;

        for (int i=0; i < nodeListi.getLength(); i++ ) // for every xitem we are looking for
        {
            nodei = nodeListi.item(i);
            type = nodei.getNodeType();
            name = nodei.getNodeName();
            if ( type == 1 && name.equals( XItem ) && nodei.hasChildNodes() ) // check it's children
            {
                org.w3c.dom.NodeList childTagNodes = nodei.getChildNodes();
                for (int j=0; j<childTagNodes.getLength(); j++)
                {
                    nodej = childTagNodes.item(j);
                    type = nodej.getNodeType();
                    name = nodej.getNodeName();
                    if ( type == 1 && name.equals( XPTag ) && nodej.hasChildNodes() ) // it's our key
                    {
                        org.w3c.dom.NodeList childnodes = nodej.getChildNodes(); // check it's data
                        for (int k=0; k<childnodes.getLength(); k++)
                        {
                            org.w3c.dom.Node childnode = childnodes.item(k);
                            type = childnode.getNodeType();
                            name = childnode.getNodeName();
                            val = childnode.getNodeValue().trim();
                            if ( type == 3 && name.equals( "#text" ) && val.equals( XData )) // nodej is it
                            {
                                return( i ); // success
                            }
                        }
                    }
                }
            }
        }
        // not found
        return( -1 );
    } // eo editForm

// ------------------
// print a tree in xml code by calling printBranches on every type 1 node
// ------------------
    void printTree( org.w3c.dom.Node rootNode, PrintWriter Out, int level )
    {
        int type = rootNode.getNodeType();
        String name = rootNode.getNodeName();
        Out.println("<?xml version=\"1.0\"?>"); 
        if ( type == 1 )
            Out.println("<" + name + ">"); 
        printBranches( rootNode, Out, level );
        if ( type == 1 )
            Out.println("</" + name + ">"); 
    }

// ------------------
// print a branch in xml code
// ------------------
    void printBranches( org.w3c.dom.Node rootNode, PrintWriter Out, int level )
    {
        int j;

        org.w3c.dom.NodeList nodes = rootNode.getChildNodes();
        for (int i=0; i<nodes.getLength(); i++) {
            org.w3c.dom.Node node = nodes.item(i);
            int type = node.getNodeType();
            if ( type == 1 )
            {
                Out.print("<" + node.getNodeName() + ">"); 
            }
            if ( type == 3 )
            {
                String s = node.getNodeValue();
                if ( s.trim().compareTo( "" ) != 0 )
                {
                    Out.print( s ); 
                }
            }
            if ( node.hasChildNodes() )
            {
               printBranches( node, Out, level + 1 );
            } 
            if ( type == 1 )
            {
                Out.println("</" + node.getNodeName() + ">"); 
            }
        }
    } // eo printTree

// ------------------
// create the top of a form
// ------------------
    void topOfForm( PrintWriter Out )
    {
        Out.println("<html><head><title>");
        Out.println( Title );
        Out.println("</title></head><body bgcolor=\"#FFFFFF\"><center><table border=\"0\" cellspacing=\"8\" cellpadding=\"8\">");
        Out.println("<tr><td><table border=\"1\" width=\"100%\"><tr><th align=\"center\">" + XItem + " Edit Wizard</th></tr></table></td></tr>");
		Out.println("<tr><td align=\"left\"><form  method=\"Post\" action=\"/emonster/wxml\">");
    } // eo topOfForm

// ------------------
//  end of a form
// ------------------
    void endOfForm( PrintWriter Out )
    {
        Out.println("</form>");
        Out.println("</td></tr></table></center></body></html>");
    } // eo endOfForm

// ------------------
// xdoc param is empty present a form to fill it
// ------------------
    void selectXDoc( HttpServletRequest request, PrintWriter Out )
    {
        File xmlPath = new File( XDocRoot );
        ExtensionFilter xf = new ExtensionFilter( "xml" );
        String[] xmlDirs = xmlPath.list( xf );
        Enumeration e = request.getParameterNames();

        topOfForm( Out );
        Out.println( "Select a " + XItem + " to edit: </td></tr>" );
        Out.println( "<tr><td align=\"left\"><select name=\"xdoc\" size=\"9\">" );
        for ( int i = 0; i < xmlDirs.length; i++ )
        {
            Out.println("<option />" + xmlDirs[ i ].substring( 0, xmlDirs[ i ].length() - 4 ));
        }
        Out.println( "</select></td></tr>" );
        Out.println("<tr><td><table border=\"1\" width=\"100%\"><tr><th align-\"center\"><input type=\"submit\" value=\"Next &gt;&gt;\" /></th></tr></table></td></tr>");
		while( e.hasMoreElements())
		{
			String s = (String)e.nextElement();
			String v = (String)request.getParameter( s );
        	Out.println("<tr><td><input type=\"hidden\" name=\"" + s + "\" value=\"" + v + "\" /></td></tr>");
		}
        endOfForm( Out );
    }

// ------------------
// ------------------
//-------------- 
// eo wxml
//--------------
}

