/*
 * Copyright (C) 2004 TiongHiang Lee
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not,  write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Email: thlee@onemindsoft.org
 */

package org.onemind.jxp.servlet;

import java.io.*;
import java.util.*;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.*;
import org.apache.commons.fileupload.DiskFileUpload;
import org.onemind.commons.java.util.*;
import org.onemind.jxp.*;
import org.xml.sax.SAXException;
/**
 * TODO comment
 * @author TiongHiang Lee (thlee@onemindsoft.org)
 * 
 */
public class JxpServlet extends HttpServlet
{

    /** the logger **/
    private static final Logger _logger = Logger.getLogger(JxpServlet.class.getName());

    /** jxp configuration * */
    private Properties _config;

    /** the processor **/
    private JxpProcessor _processor;
    
    /** the configuration file **/
    private String _configFile;
    
    /** the upload **/
    private DiskFileUpload _uploadRepository;

    /**
     * {@inheritDoc}
     */
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        doPost(req, resp);
    }

    /**
     * Return the config
     * @return the config
     */
    private Properties getConfig()
    {
        return _config;
    }

    /**
     * Get the processor
     * @param req the request
     * @return the processor
     * @throws Exception
     */
    private JxpProcessor getProcessor(HttpServletRequest req) throws Exception
    {
        if (_processor == null)
        {
            synchronized (this)
            {                
                if (_processor != null)
                {                    
                    return _processor;
                }
                if (StringUtils.isNullOrEmpty(_configFile))
                {
                    _processor = new JxpProcessor(new JxpContext(new FilePageSource(req.getRealPath("/"))));
                } else 
                {
                    _processor = JxpFactory.getProcessor(_configFile);
                }
                
            }
        }
        return _processor;
    }

    /**
     * {@inheritDoc}
     */
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        Map env = ServletUtils.getServletEnvironment(getServletConfig());
        env.putAll(ServletUtils.getRequestEnvironment(req));
        env.putAll(ServletUtils.getExtraRequestEnvironment(req));        
        Map form = new HashMap();
        
        String uri = req.getRequestURI();
        if (uri.endsWith("JxpServlet"))
        {
            dumpDebugInfo(req, resp, env);
        } else
        {
            resp.setContentType("text/html");
            resp.setStatus(200, "OK");
            Writer writer = resp.getWriter();
            env.put("form", form);
            env.put("req", req);
            env.put("resp", resp);
            String uripath = StringUtils.substringBeforeLast(uri, "/");
            if (uripath == null)
            {
                uripath = "/";
            }
            env.put("uripath", uripath);
            try
            {
                form.putAll(ServletUtils.getRequestParameters(req, _uploadRepository));
                JxpProcessor processor = getProcessor(req);
                processor.process(uri, writer, env);
            } catch (JxpPageNotFoundException pnfe)
            {
                _logger.info("Error processing uri" + uripath + ": " + pnfe.getMessage());
                writer.write(pnfe.getMessage());
            } catch (JxpPageSourceException jpse)
            {
                _logger.info("Error processing uri" + uripath + ": " + jpse.getMessage());
                writer.write(jpse.getMessage());
            } catch (Exception e)
            {
                _logger.info("Error processing uri" + uripath);
                e.printStackTrace(new PrintWriter(writer));
            } finally
            {
                writer.flush();
            }
        }
    }

    /**
     * Output the debugging information
     * @param req the request
     * @param resp the resoibse
     * @param env the environment
     * @throws IOException io exceptions
     */
    private void dumpDebugInfo(HttpServletRequest req, HttpServletResponse resp, Map env) throws IOException
    {
        resp.setContentType("text/html");
        resp.setStatus(200, "OK");
        PrintWriter output = resp.getWriter();
        output.write("<html><body><pre>");
        MapUtils.dump(env, output);
        output.write("</pre></body></html>");
        output.flush();
        output.close();
        return;
    }

    /**
     * {@inheritDoc}
     */
    public void init(ServletConfig config) throws ServletException
    {
        super.init(config);
        LogUtils.initLoggingFromClassPath();
        _configFile = config.getInitParameter("config");
        // create a new file upload handler
        _uploadRepository = new DiskFileUpload();
        //     Set upload parameters
        _uploadRepository.setRepositoryPath(System.getProperty("java.io.tmpdir"));
        _uploadRepository.setSizeThreshold(1000000); //file > 1 meg write to disk
        _uploadRepository.setSizeMax(-1); //no maximum size
        
    }
}