"""
$URL: svn+ssh://svn.mems-exchange.org/repos/trunk/quixote/server/mod_python_handler.py $
$Id: mod_python_handler.py 25893 2005-01-19 14:26:25Z dbinger $

This needs testing.

mod_python configuration
------------------------

mod_python is an Apache module for embedding a Python interpreter into
the Apache server.  To use mod_python as the interface layer between
Apache and Quixote, add something like this to your httpd.conf::

    LoadModule python_module /usr/lib/apache/1.3/mod_python.so
    <LocationMatch "^/qdemo(/|$)">
        SetHandler python-program
        PythonHandler quixote.server.mod_python_handler
        PythonOption quixote-publisher-factory quixote.demo.create_publisher
        PythonInterpreter quixote.demo
        PythonDebug On
    </LocationMatch>

This will attach URLs starting with ``/qdemo`` to the Quixote demo.
When you use mod_python, there's no need for rewrite rules (because of
the pattern in the ``LocationMatch`` directive), and no need for a
driver script.  

mod_python support was contributed to Quixote (1) by Erno Kuusela
<erno@iki.fi> and the Quixote 2 port comes from Clint.
"""

import sys
from mod_python import apache
from quixote import enable_ptl
from quixote.publish import Publisher
from quixote.config import Config
from quixote.util import import_object

class ErrorLog:
    def __init__(self, publisher):
        self.publisher = publisher

    def write(self, msg):
        self.publisher.log(msg)

    def close(self):
        pass

class ModPythonPublisher(Publisher):
    def __init__(self, package, **kwargs):
        Publisher.__init__(self, package, **kwargs)
        # may be overwritten
        self.logger.error_log = self.__error_log = ErrorLog(self)
        self.__apache_request = None

    def log(self, msg):
        if self.logger.error_log is self.__error_log:
            try:
                self.__apache_request.log_error(msg)
            except AttributeError:
                apache.log_error(msg)
        else:
            Publisher.log(self, msg)

    def publish_modpython(self, req):
        """publish_modpython() -> None

        Entry point from mod_python.
        """
        self.__apache_request = req
        try:
            self.publish(apache.CGIStdin(req),
                         apache.CGIStdout(req),
                         sys.stderr,
                         apache.build_cgi_env(req))

            return apache.OK
        finally:
            self.__apache_request = None

name2publisher = {}

def run(publisher, req):
    from quixote.http_request import HTTPRequest
    request = HTTPRequest(apache.CGIStdin(req), apache.build_cgi_env(req))
    response = publisher.process_request(request)
    try:
        response.write(apache.CGIStdout(req))
    except IOError, err:
        publisher.log("IOError while  sending response ignored: %s" % err)
    return apache.OK

def handler(req):
    opts = req.get_options()
    try:
        factory = opts['quixote-publisher-factory']
    except KeyError:
        apache.log_error('quixote-publisher-factory setting required')
        return apache.HTTP_INTERNAL_SERVER_ERROR
    pub = name2publisher.get(factory)
    if pub is None:
        factory_fcn = import_object(factory)
        pub = factory_fcn()
        name2publisher[factory] = pub
    return run(pub, req)

