package pdfgenerator.tools.servlet;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;

import org.apache.fop.apps.*;
import pdfgenerator.messaging.*;




import java.net.URL;
/**
 * Example servlet to generate a PDF from a servlet.
 * Servlet param is:
 * <ul>
 *   <li>fo: the path to a formatting object file to render
 * </ul>
 *
 * Example URL : http://servername/servlet/PDFGeneratorServletFromString?xml=/home/example/hello.xml&xsl=/home/example/hello.xsl
 *         URL : http://servername/servlet/PDFGeneratorServletFromString?fo=/home/example/hello.fo
 *
 */

public class PDFGeneratorServletFromString extends HttpServlet
{
    File xmlfile, xsltfile;
    String debug=new String("");
    public static final String XML_REQUEST_PARAM = "xml";
    public static final String XSL_REQUEST_PARAM = "xsl";
    public static final String FO_REQUEST_PARAM = "fo";
    //boolean errorDump;


    public void doGet(HttpServletRequest request,
		      HttpServletResponse response)
	throws ServletException
    {
	try {
	    if (request.getParameter(XML_REQUEST_PARAM) != null && XSL_REQUEST_PARAM != null) {
                xmlfile = new File(request.getParameter(XML_REQUEST_PARAM));
                xsltfile = new File(request.getParameter(XSL_REQUEST_PARAM));
                if (!xmlfile.exists()) {
                    MessageHandler.errorln("ERROR: xml file " +
                                       xmlfile.getAbsolutePath() + " not found ");
                    System.exit(1);
                }
                if (!xsltfile.exists()) {
                    MessageHandler.errorln("ERROR: xsl file " +
                                       xsltfile.getAbsolutePath() + " not found ");
                    System.exit(1);
                }
                render(response);
            }else if (request.getParameter(FO_REQUEST_PARAM) != null){
                File fofile=new File(request.getParameter(FO_REQUEST_PARAM));
                if (!fofile.exists()) {
                    MessageHandler.errorln("ERROR: fo file " +
                         fofile.getAbsolutePath() + " not found ");
                    System.exit(1);
                }
                String path = new String(request.getParameter(FO_REQUEST_PARAM));
                renderFO(new InputSource(path), response);


           }else {
		PrintWriter out = response.getWriter();
		out.println("<html><head><title>Error</title></head>\n"+
			    "<body><h1>PDFGeneratorServlet Error</h1><h3>No 'xml' or 'xslt'"+
			    "request param given.</body></html>");
	    }

	}
	catch (Exception ex) {
	    throw new ServletException(ex);
	}
    }

    /**
     * renders an XML inputsource into a PDF file which is rendered
     * directly to the response object's OutputStream
     */
    public void render(HttpServletResponse response) throws ServletException
    {
	try {
	    ByteArrayOutputStream out = new ByteArrayOutputStream();
	    response.setContentType("application/pdf");
	    this.runToOut(out);

	    byte[] content = out.toByteArray();
	    response.setContentLength(content.length);
	    response.getOutputStream().write(content);
            response.getOutputStream().flush();

	}
	catch (Exception ex) {
	    throw new ServletException(ex);
	}

    }


    /**
     * renders an FO inputsource into a PDF file which is rendered
     * directly to the response object's OutputStream
     */
    public void renderFO(InputSource foFile, HttpServletResponse response)
	throws ServletException
    {
	try {
	    ByteArrayOutputStream out = new ByteArrayOutputStream();

	    response.setContentType("application/pdf");

	    Driver driver = new Driver(foFile, out);
	    driver.run();

	    byte[] content = out.toByteArray();
	    response.setContentLength(content.length);
	    response.getOutputStream().write(content);
	    response.getOutputStream().flush();

	}
	catch (Exception ex) {
	    throw new ServletException(ex);
	}

    }

    public InputHandler getInputHandler (File xmlfile, File xsltfile ) {
       return  new XSLTInputHandler(xmlfile, xsltfile);
    }


    private void setParserFeatures (XMLReader parser,boolean errorDump) {
        try {
            parser.setFeature("http://xml.org/sax/features/namespace-prefixes",true);
        } catch (SAXException e) {
            MessageHandler.errorln("Error in setting up parser feature namespace-prefixes");
            MessageHandler.errorln("You need a parser which supports SAX version 2");
            if (errorDump) {
                e.printStackTrace();
            }
            System.exit(1);
        }
    }

    public InputSource getInputSource(File xmlfile, File xsltfile){
      InputHandler inputHandler = this.getInputHandler(xmlfile, xsltfile);
      return inputHandler.getInputSource();
   }

    public void runToOut(ByteArrayOutputStream out) {
        String version = Version.getVersion();
        MessageHandler.logln(version);
        InputHandler inputHandler = this.getInputHandler(this.xmlfile, this.xsltfile);
        XMLReader parser = inputHandler.getParser();
        setParserFeatures(parser,true);
        Driver driver = new Driver();
        driver.setErrorDump(true);


        try {
            driver.setRenderer(1); //render PDF
            InputSource inputSource = inputHandler.getInputSource();
            driver.buildFOTree(parser, inputSource);
            driver.setOutputStream(out);
            driver.format();
            driver.render();
        } catch (Exception e) {
            MessageHandler.errorln("FATAL ERROR: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
    }


}
