#!/usr/bin/python

import sys
import traceback
import time
import BaseHTTPServer

# http://effbot.org/zone/element-index.htm
import elementtree.ElementTree 

import RelaxNGCheck

# The database is only in memory :-)
domains = {}

class NoContentLength(Exception):
    pass

def domain_info(domain):
    holder = domains[domain]["holder"]
    created = domains[domain]["created"]
    creator = domains[domain]["creator"]
    return """
                     <domain>
                          <holder>%s</holder>
                          <created>%s</created>
                          <creator>%s</creator>
                     </domain>\n\r""" % (holder, created, creator)

class RESTHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):

    def __init__(self, request, client_address, server):
        self.checker_request = RelaxNGCheck.Check("file:schema-request.rnc")
        self.checker_reply = RelaxNGCheck.Check("file:schema-reply.rnc")
        BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, request,
                                                       client_address, server)
        
    def do_GET(self):
        domain = self.path[1:]
        if domains.has_key(domain):
            self.send_response(200)
            self.end_headers()
            self.wfile.write(domain_info(domain))
        else:
            self.send_response(404) # Not found
            self.end_headers()
                
    def do_DELETE(self):
        domain = self.path[1:]
        if domains.has_key(domain):
            self.send_response(204)
            self.end_headers()
            del domains[domain]
        else:
            self.send_response(404)
            self.end_headers()
                
    def do_PUT(self):
        try:
            domain = self.path[1:]
            if domains.has_key(domain):
                self.send_response(200) # RFC 2616 says so
                self.end_headers()
                self.wfile.write(domain_info(domain))
            else:
                if not self.headers.has_key('content-length'):
                    raise NoContentLength
                body = self.rfile.read(int(self.headers['content-length']))
                self.checker_request.check(body)
                xml_request = elementtree.ElementTree.fromstring(body)
                self.send_response(201)
                self.end_headers()
                domains[domain] = {}
                domains[domain]["holder"] = xml_request.find("holder").text
                domains[domain]["creator"] = str(self.client_address[0])
                domains[domain]["created"] = time.strftime("%Y-%m-%dT%H:%M:%S",
                                                           time.gmtime())
                self.wfile.write(domain_info(domain))
        except:
             self.send_response(500)
             self.end_headers()
             (exc_type, exc_value, exc_trace) = sys.exc_info()
             error = "Internal server error: " + \
                   str(exc_type) + ": " + str(exc_value)
             self.wfile.write("%s\n" % error)
             long_error = error +  " (" + str(traceback.format_tb(exc_trace)) + ")"
             self.log_error(long_error)

                 
def run(server_class=BaseHTTPServer.HTTPServer,
        handler_class=RESTHTTPRequestHandler):
    server_address = ('', 8080)
    httpd = server_class(server_address, handler_class)
    httpd.serve_forever()

if __name__ == '__main__':
    run()
    
