CgiPlusAppServer.py :  » Web-Frameworks » Webware » Webware-1.0.2 » WebKit » Adapters » CGIPlus » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Webware 
Webware » Webware 1.0.2 » WebKit » Adapters » CGIPlus » CgiPlusAppServer.py
#!/usr/bin/env python
"""CGIPlusAppServer

This WebKit app server is a WASD CGIplus server that accepts requests, hands
them off to the Application and sends the request back over the connection.

The fact that the app server stays resident is what makes it so much quicker
than traditional CGI programming. Everything gets cached.

CGIPlusAppServer takes the following command line arguments:

start: start the AppServer (default argument)
stop: stop the currently running Apperver
ClassName.SettingName=value: change configuration settings

When started, the app server records its pid in appserver.pid.

"""

import threading, Queue, select, socket, errno, traceback
from marshal import dumps,loads
from threading import Lock,Thread,Event

from Common import *
import AppServer as AppServerModule
from AutoReloadingAppServer import AutoReloadingAppServer
from MiscUtils.Funcs import timestamp
from WebUtils import Funcs


debug = False

server = None


class CgiPlusAppServer(AppServer):

  ## Init ##

  def __init__(self, path=None):
    AppServer.__init__(self, path)
    self._requestID = 1
    self.recordPID()
    self._wasd_running = None

    # temporaire
    from WebKit import Profiler
    Profiler.startTime = time.time()
    self.readyForRequests()

  def addInputHandler(self, handlerClass):
    self._handler = handlerClass

  def isPersistent(self):
    return False

  def recordPID(self):
    """Currently do nothing."""
    return

  def initiateShutdown(self):
    self._wasd_running = False
    AppServer.initiateShutdown(self)

  def mainloop(self, timeout=1):
    import wasd
    wasd.init()
    stderr_ini = sys.stderr
    sys.stderr = StringIO()
    self._wasd_running = True
    environ_ini = os.environ
    while 1:
      if not self._running or not self._wasd_running:
        return
      # init environment cgi variables
      os.environ = environ_ini.copy()
      wasd.init_environ()
      print >>sys.__stdout__, "Script-Control: X-stream-mode"
      self._requestID += 1
      self._app._sessions.cleanStaleSessions()
      self.handler = handler = self._handler(self)
      handler.activate(self._requestID)
      handler.handleRequest()
      self.restartIfNecessary()
      self.handler = None
      sys.__stdout__.flush()
      if not self._running or not self._wasd_running:
        return
      # when we want to exit don't send the eof, so
      # WASD don't try to send the next request to the server
      wasd.cgi_eof()
      sys.stderr.close()
      # block until next request
      wasd.cgi_info("")
      sys.stderr = StringIO()

  def shutDown(self):
    self._running = 0
    print "CgiPlusAppServer: Shutting Down"
    AppServer.shutDown(self)


class Handler:

  def __init__(self, server):
    self._server = server

  def activate(self, requestID):
    """Activates the handler for processing the request.

    Number is the number of the request, mostly used to identify
    verbose output. Each request should be given a unique,
    incremental number.

    """
    self._requestID = requestID

  def close(self):
    pass

  def handleRequest(self):
    pass

  def receiveDict(self):
    """Utility function to receive a marshalled dictionary."""
    pass


from WebKit.ASStreamOut import ASStreamOut
class CPASStreamOut(ASStreamOut):
  """Response stream for CgiPLusAppServer.

  The `CPASASStreamOut` class streams to a given file, so that when `flush`
  is called and the buffer is ready to be written, it sends the data from the
  buffer out on the file. This is the response stream used for requests
  generated by CgiPlusAppServer.

  CP stands for CgiPlusAppServer

  """

  def __init__(self, file):
    ASStreamOut.__init__(self)
    self._file = file

  def flush(self):
    result = ASStreamOut.flush(self)
    if result: # a true return value means we can send
      reslen = len(self._buffer)
      self._file.write(self._buffer)
      self._file.flush()
      sent = reslen
      self.pop(sent)


# Set to False in DebugAppServer so Python debuggers can trap exceptions
doesRunHandleExceptions = True

class RestartAppServerError(Exception):
  """Raised by DebugAppServer when needed."""
  pass


def run(workDir=None):
  global server
  from WebKit.CgiPlusServer import CgiPlusAppServerHandler
  runAgain = True
  while runAgain: # looping in support of RestartAppServerError
    try:
      try:
        runAgain = False
        server = None
        server = CgiPlusAppServer(workDir)
        server.addInputHandler(CgiPlusAppServerHandler)
        try:
          server.mainloop()
        except KeyboardInterrupt, e:
          server.shutDown()
      except RestartAppServerError:
        print
        print "Restarting app server:"
        sys.stdout.flush()
        runAgain = True
      except Exception, e:
        if not doesRunHandleExceptions:
          raise
        if not isinstance(e, SystemExit):
          import traceback
          traceback.print_exc(file=sys.stderr)
        print
        print "Exiting AppServer"
        if server:
          if server._running:
            server.initiateShutdown()
        # if we're here as a result of exit() being called,
        # exit with that return code.
        if isinstance(e,SystemExit):
          sys.exit(e)
    finally:
      AppServerModule.globalAppServer = None
  sys.exit()


def shutDown(arg1, arg2):
  global server
  print "Shutdown Called", asclocaltime()
  if server:
    server.initiateShutdown()
  else:
    print 'WARNING: No server reference to shutdown.'

import signal
signal.signal(signal.SIGINT, shutDown)
signal.signal(signal.SIGTERM, shutDown)

usage = re.search('\n.* arguments:\n\n(.*\n)*?\n', __doc__).group(0)

import re
settingRE = re.compile(r'^--([a-zA-Z][a-zA-Z0-9]*\.[a-zA-Z][a-zA-Z0-9]*)=')
from MiscUtils import Configurable

def main(args):
  function = run
  workDir = None
  sys.stdout = StringIO()
  for i in args[:]:
    if settingRE.match(i):
      match = settingRE.match(i)
      name = match.group(1)
      value = i[match.end():]
      Configurable.addCommandLineSetting(name, value)
    elif i == "stop":
      function = AppServerModule.stop
    elif i == "start":
      pass
    elif i[:8] == "workdir=":
      workDir = i[8:]
    else:
      print usage

  function(workDir=workDir)

main([])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.