Author: chrisz
Date: Wed Aug 23 16:19:35 2006
New Revision: 5641
Added:
Webware/trunk/WebKit/Adapters/CGIPlus/ (props changed)
Webware/trunk/WebKit/Adapters/CGIPlus/CGIPlusLaunchWebKit.py (contents, props changed)
Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusAppServer.py (contents, props changed)
Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusMakeAppWorkDir.py (contents, props changed)
Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusServer.py (contents, props changed)
Webware/trunk/WebKit/Adapters/CGIPlus/README (contents, props changed)
Log:
Added files provided by Jean-François Piéronne (jfp@...) for running Webware on OpenVMS in a WASD CGIPlus environment.
Added: Webware/trunk/WebKit/Adapters/CGIPlus/CGIPlusLaunchWebKit.py
==============================================================================
--- (empty file)
+++ Webware/trunk/WebKit/Adapters/CGIPlus/CGIPlusLaunchWebKit.py Wed Aug 23 16:19:35 2006
@@ -0,0 +1,34 @@
+#!/$1$DKA200/TOOLS/python/vms/bin/python.exe.1
+
+import os, sys
+
+webwarePath = '/webware092_root'
+appWorkPath = '/webware092_root'
+
+
+def main(args):
+ global webwarePath, appWorkPath
+ newArgs = []
+ for arg in args:
+ if arg.startswith('--webware-path='):
+ webwarePath = arg[15:]
+ elif arg.startswith('--working-path='):
+ appWorkPath = arg[15:]
+ else:
+ newArgs.append(arg)
+ args = newArgs
+ # ensure Webware is on sys.path
+ sys.path.insert(0, webwarePath)
+
+ # import the master launcher
+ import WebKit.Launch
+
+ if len(args) < 2:
+ WebKit.Launch.usage()
+
+ # Go!
+ WebKit.Launch.launchWebKit(args[1], appWorkPath, args[2:])
+
+
+if __name__=='__main__':
+ main(sys.argv)
Added: Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusAppServer.py
==============================================================================
--- (empty file)
+++ Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusAppServer.py Wed Aug 23 16:19:35 2006
@@ -0,0 +1,335 @@
+#!/usr/bin/env python
+"""
+AppServer
+
+The 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.
+
+"""
+
+from Common import *
+import AppServer as AppServerModule
+from AutoReloadingAppServer import AutoReloadingAppServer as AppServer
+from MiscUtils.Funcs import timestamp
+from marshal import dumps, loads
+import os, sys
+from threading import Lock, Thread, Event
+import threading
+import Queue
+import select
+import socket
+import threading
+import time
+import errno
+import traceback
+from WebUtils import Funcs
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+debug = 0
+
+DefaultConfig = {
+ 'MaxServerThreads': 1,
+ 'MinServerThreads': 1,
+ 'StartServerThreads': 1,
+}
+
+# Need to know this value for communications
+# Note that this limits the size of the dictionary we receive from the AppServer to 2,147,483,647 bytes
+intLength = len(dumps(int(1)))
+
+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 0
+
+ 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
+ self._shuttingdown=1 #jsl-is this used anywhere?
+ 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
+
+
+class MonitorHandler(Handler):
+
+ protcolName = 'monitor'
+
+ def handleRequest(self):
+ verbose = self.server._verbose
+ startTime = time.time()
+ if verbose:
+ print 'BEGIN REQUEST'
+ print time.asctime(time.localtime(startTime))
+ conn = self._sock
+ if verbose:
+ print 'receiving request from', conn
+ BUFSIZE = 8*1024
+ dict = self.receiveDict()
+ if dict['format'] == "STATUS":
+ conn.send(str(self.server._reqCount))
+ if dict['format'] == 'QUIT':
+ conn.send("OK")
+ conn.close()
+ self.server.shutDown()
+
+
+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)
+
+
+class AdapterHandler(Handler):
+
+ protocolName = 'address'
+
+ def handleRequest(self):
+ verbose = self._server._verbose
+ self._startTime = time.time()
+ if verbose:
+ print '%5i %s ' % (self._requestID, timestamp()['pretty']),
+
+ data = []
+ dict = self.receiveDict()
+ if dict and verbose and dict.has_key('environ'):
+ requestURI = Funcs.requestURI(dict['environ'])
+ print requestURI
+ else:
+ requestURI = None
+
+ dict['input'] = self.makeInput()
+ streamOut = TASASStreamOut(self._sock)
+ transaction = self._server._app.dispatchRawRequest(dict, streamOut)
+ streamOut.close()
+
+ try:
+ self._sock.shutdown(1)
+ self._sock.close()
+ except:
+ pass
+
+ if self._server._verbose:
+ duration = '%0.2f secs' % (time.time() - self._startTime)
+ duration = string.ljust(duration, 19)
+ print '%5i %s %s' % (self._requestID, duration, requestURI)
+ print
+
+ transaction._application=None
+ transaction.die()
+ del transaction
+
+ def makeInput(self):
+ return self._sock.makefile("rb",8012)
+
+
+# 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", time.asctime(time.localtime(time.time()))
+ 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 = """
+The AppServer is the main process of WebKit. It handles requests for
+servlets from webservers. ThreadedAppServer takes the following
+command line arguments: stop: Stop the currently running Apperver.
+daemon: run as a daemon If AppServer is called with no arguments, it
+will start the AppServer and record the pid of the process in
+appserverpid.txt
+"""
+
+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
+ daemon = 0
+ 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":
+ import AppServer
+ function=AppServer.stop
+ elif i == "daemon":
+ daemon=1
+ elif i == "start":
+ pass
+ elif i[:8] == "workdir=":
+ workDir = i[8:]
+ else:
+ print usage
+
+ function(workDir=workDir)
+
+main([])
Added: Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusMakeAppWorkDir.py
==============================================================================
--- (empty file)
+++ Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusMakeAppWorkDir.py Wed Aug 23 16:19:35 2006
@@ -0,0 +1,465 @@
+#!/usr/bin/env python
+
+"""MakeAppWorkDir.py
+
+INTRODUCTION
+
+This utility builds a directory tree that can be used as the current
+working directory of an instance of the WebKit application server
+in a WASD CGIPlus environment.
+
+USAGE
+
+MakeAppWorkDir.py [Options] WorkDir
+
+Options:
+ -c, --context-name=... The name for the preinstalled context.
+ By default, it will be "MyContext".
+ -d, --context-dir=... The directory where the context will be located,
+ so you can place it outside of the WorkDir.
+ -l, --library=... Other dirs to be included in the search path.
+ You may specify this option multiple times.
+ -i, --cvsignore This will add .cvsignore files to the WorkDir.
+ -u, --user=... The name or uid of the user to own the WorkDir.
+ This option is supported under Unix only.
+ -g, --group=... The name or gid of the group to own the WorkDir.
+ This option is supported under Unix only.
+
+WorkDir:
+ The target working directory to be created.
+"""
+
+# FUTURE
+# * Add options to immediately import the new directory tree into a
+# CVS or SVN repository. In the case of a CVS repository, the
+# .cvsignore files should be created automatically, and in case
+# of SVN, the corresponding svn propset commands should be issued.
+# * MakeAppWorkDir.py should set the admin password like install.py does.
+# At the same time, install.py should be able to do a "app-less" install,
+# from which the admin can create appdirs using MakeAppWorkDir.py.
+# The idea here is that the results of install.py should only be "shared"
+# resources, and "per-app" resources (like the admin password) should be
+# deferred (or, at least, deferrable) to MakeAppWorkDir.py.
+# CREDITS
+# * Contributed to Webware for Python by Robin Dunn
+# * Improved by Christoph Zwerschke
+
+import sys, os, stat, re, glob, shutil
+
+
+class MakeAppWorkDir:
+ """Make a new application runtime directory for Webware.
+
+ This class breaks down the steps needed to create a new runtime
+ directory for webware. That includes all the needed
+ subdirectories, default configuration files, and startup scripts.
+ Each step can be overridden in a derived class if needed.
+ """
+
+ def __init__(self, webwareDir, workDir, verbose=1, osType=None,
+ contextName='MyContext', contextDir='', libraryDirs=None,
+ cvsIgnore=0, uid=None, gid=None):
+ """Initializer for MakeAppWorkDir.
+
+ Pass in at least the Webware directory and the target working
+ directory. If you pass None for contextName then the default
+ context will be the the WebKit/Examples directory as usual.
+
+ """
+ self._webwareDir = webwareDir
+ self._webKitDir = os.path.join(webwareDir, 'WebKit')
+ self._workDir = os.path.abspath(workDir)
+ self._verbose = verbose
+ if osType is None:
+ osType = os.name
+ self._contextName = contextName
+ self._contextDir = contextDir
+ if libraryDirs is None:
+ libraryDirs = []
+ self._libraryDirs = libraryDirs
+ self._osType = osType
+ self._cvsIgnore = cvsIgnore
+ self._uid = uid
+ self._gid = gid
+
+ def buildWorkDir(self):
+ """These are all the steps needed to make a new runtime directory.
+
+ You can override the steps taken here with your own methods.
+
+ """
+ self.msg("Making a new WebKit runtime directory...")
+ self.msg()
+ self.makeDirectories()
+ self.copyConfigFiles()
+ self.copyOtherFiles()
+ self.makeLauncherScripts()
+ if self._contextName is not None:
+ self.makeDefaultContext()
+ if self._cvsIgnore:
+ self.addCvsIgnore()
+ self.changeOwner()
+ self.printCompleted()
+
+ def makeDirectories(self):
+ """Create all the needed directories if they don't already exist."""
+ self.msg("Creating the directory tree...")
+ standardDirs = (
+ '', 'Configs')
+ for dir in standardDirs:
+ dir = os.path.join(self._workDir, dir)
+ if os.path.exists(dir):
+ self.msg("\tWarning: %s already exists." % dir)
+ else:
+ os.mkdir(dir)
+ self.msg("\t%s" % dir)
+ for dir in self._libraryDirs:
+ dir = os.path.join(self._workDir, dir)
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+ open(os.path.join(dir, '__init__.py'), 'w').write('#\n')
+ self.msg("\t%s created." % dir)
+ self.msg()
+
+ def copyConfigFiles(self):
+ """Make a copy of the config files in the Configs directory."""
+ self.msg("Copying config files...")
+ configs = glob.glob(os.path.join(self._webKitDir,
+ "Configs", "*.config"))
+ for name in configs:
+ newname = os.path.join(self._workDir, "Configs",
+ os.path.basename(name))
+ self.msg("\t%s" % newname)
+ shutil.copyfile(name, newname)
+ mode = os.stat(newname)[stat.ST_MODE]
+ # remove public read/write/exec perms
+ os.chmod(newname, mode & 0770)
+ self.msg()
+
+ def copyOtherFiles(self):
+ """Make a copy of any other necessary files in the new work dir."""
+ self.msg("Copying other files...")
+ otherFiles = ('404Text.txt',)
+ for name in otherFiles:
+ if name == 'AppServer':
+ if self._osType == 'nt':
+ name += '.bat'
+ chmod = 1
+ elif name == 'webkit':
+ if self._osType != 'posix':
+ continue
+ chmod = 1
+ else:
+ chmod = 0
+ newname = os.path.join(self._workDir, os.path.basename(name))
+ if not os.path.exists(newname):
+ oldname = os.path.join(self._webKitDir, name)
+ if os.path.exists(oldname):
+ self.msg("\t%s" % newname)
+ shutil.copyfile(oldname, newname)
+ if chmod:
+ os.chmod(newname, 0755)
+ else:
+ self.msg("\tWarning: Cannot find %r." % oldname)
+ self.msg()
+
+ def makeLauncherScripts(self):
+ """Create the launcher scripts and copy the CGI adapter script."""
+ self.msg("Creating the launcher scripts...")
+ workDir = self._workDir
+ webwareDir = self._webwareDir
+ webKitDir = self._webKitDir
+ libraryDirs = self._libraryDirs
+ uid, gid = self._uid, self._gid
+ if uid is None:
+ user = None
+ else:
+ import pwd
+ user = pwd.getpwuid(uid)[0]
+ if gid is None:
+ group = None
+ else:
+ import grp
+ group = grp.getgrgid(gid)[0]
+ executable = sys.executable
+ for name in launcherScripts:
+ if name.endswith('Service.py') and self._osType != 'nt':
+ continue
+ newname = os.path.join(workDir, name)
+ if not os.path.exists(newname):
+ oldname = os.path.join(webKitDir, name)
+ if os.path.exists(oldname):
+ self.msg("\t%s" % newname)
+ script = launcherScripts[name] % locals()
+ open(newname, "w").write(script)
+ os.chmod(newname, 0755)
+ else:
+ self.msg("\tWarning: Cannot find %r." % oldname)
+ self.msg()
+
+ def makeDefaultContext(self):
+ """Make a very simple context for the newbie user to play with."""
+ self.msg("Creating default context...")
+ contextDir = os.path.join(
+ self._workDir,
+ self._contextDir or self._contextName)
+ if contextDir.startswith(self._workDir):
+ configDir = contextDir[len(self._workDir):]
+ configDir = configDir.lstrip(os.sep)
+ if os.altsep:
+ configDir = configDir.lstrip(os.altsep)
+ else:
+ configDir = contextDir
+ if not os.path.exists(contextDir):
+ os.makedirs(contextDir)
+ for name in exampleContext:
+ filename = os.path.join(contextDir, name)
+ if not os.path.exists(filename):
+ self.msg("\t%s" % filename)
+ open(filename, "w").write(exampleContext[name])
+ self.msg("Updating config for default context...")
+ filename = os.path.join(self._workDir, "Configs",
+ 'Application.config')
+ self.msg("\t%s" % filename)
+ content = open(filename).readlines()
+ output = open(filename, 'w')
+ foundContext = 0
+ configDir = "WebKitPath + '/%s'" % (self._contextName,)
+ for line in content:
+ if line.startswith("Contexts['default'] = "):
+ output.write("Contexts[%r] = %s\n"
+ % (self._contextName, configDir))
+ output.write("Contexts['default'] = %r\n"
+ % self._contextName)
+ foundContext += 1
+ else:
+ output.write(line)
+ if not foundContext:
+ self.msg("\tWarning: Default context could not be set.")
+ self.msg()
+
+ def addCvsIgnore(self):
+ self.msg("Creating .cvsignore files...")
+ files = {
+ '.': '*.pyc\n*.pyo\n'
+ 'address.*\nhttpd.*\nappserverpid.*\nprofile.pstats',
+ 'Cache': '[a-zA-Z0-9]*',
+ 'ErrorMsgs': '[a-zA-Z0-9]*',
+ 'Logs': '[a-zA-Z0-9]*',
+ 'Sessions': '[a-zA-Z0-9]*',
+ self._contextName: '*.pyc\n*.pyo' }
+ for dir, contents in files.items():
+ filename = os.path.join(self._workDir,
+ dir, '.cvsignore')
+ f = open(filename, 'w')
+ f.write(contents)
+ f.close()
+ self.msg()
+
+ def changeOwner(self):
+ if self._uid is None and self._gid is None:
+ return
+ self.msg("Changing the ownership...")
+ uid = self._uid
+ if uid is None:
+ uid =os.getuid()
+ gid = self._gid
+ if gid is None:
+ gid = os.getgid()
+ try:
+ os.chown(self._workDir, uid, gid)
+ except:
+ self.msg("\tWarning: The ownership could not be changed.")
+ else:
+ for (dir, dirs, files) in os.walk(self._workDir):
+ for file in dirs + files:
+ path = os.path.join(dir, file)
+ os.chown(path, uid, gid)
+ self.msg()
+
+ def printCompleted(self):
+ run = os.path.abspath(os.path.join(self._workDir, 'AppServer'))
+ print """
+Congratulations, you've just created a runtime working directory for Webware.
+
+Don't forget to set a correct security profile on this created directory tree.
+The accounts which will execute the application need READ access to this
+directory tree.
+
+
+To finish you must create a CGIPlus script like the following
+$ @WEBWARE092_ROOT:[VMS]CGIPlusLaunchWebKit -
+ dev1:[users_directory] -
+ dev2:[app_directory.MyAPP]
+
+where
+ dev1:[users_directory] is the directory which holds the directory
+ created using the procedure WEBWARE092_ROOT:[VMS]add_webware_user.com
+ dev2:[app_directory.MyAPP] is the directory created by this procedure
+
+
+You will also need to add some rules to your HTTPD$MAP.CONF file
+set /myapp/* map=once cache=noscript auth=once
+set /myapp/* script=as=WEBWARE_USER
+set /myapp/* SCRIPT=SYNTAX=UNIX
+set /myapp/* throttle=1/1,,,20,,00:05:00
+script+ /myapp/* /cgi-bin/myapp.com*
+
+
+if cgi-bin:[000000]myapp.com is the script previously mentioned.
+
+Have fun!
+"""
+
+ def msg(self, text=None):
+ if self._verbose:
+ if text:
+ print text
+ else:
+ print
+
+launcherScripts = { # launcher scripts with adjusted parameters
+
+} # end of launcher scripts
+
+exampleContext = { # files copied to example context
+
+# This is used to create a very simple sample context for the new
+# work dir to give the newbie something easy to play with.
+
+'__init__.py': r"""
+def contextInitialize(appServer, path):
+ # You could put initialization code here to be executed
+ # when the context is loaded into WebKit.
+ pass
+""",
+
+'Main.py': r"""
+from WebKit.Page import Page
+
+class Main(Page):
+
+ def title(self):
+ return 'My Sample Context'
+
+ def writeContent(self):
+ self.writeln('<h1>Welcome to Webware for Python!</h1>')
+ self.writeln('''
+ <p>This is a sample context generated for you and has purposly been kept
+ very simple to give you something to play with to get yourself started.
+ The code that implements this page is located in <b>%s</b>.</p>
+ ''' % self.request().serverSidePath())
+ self.writeln('''
+ <p>There are more examples and documentation in the Webware distribution,
+ which you can get to from here:</p>
+ <ul>
+ ''')
+ adapterName = self.request().adapterName()
+ contextName = self.request().contextName()
+ ctxs = self.application().contexts().keys()
+ ctxs.sort()
+ for ctx in ctxs:
+ if ctx in ('default', contextName) or ctx.find('/') >= 0:
+ continue
+ self.writeln('<li><a href="%s/%s/">%s</a></li>'
+ % (adapterName, ctx, ctx))
+ self.writeln('</ul>')
+"""
+
+} # end of example context files
+
+def usage():
+ """Print the docstring and exit with error."""
+ print __doc__
+ sys.exit(2)
+
+def main(args=None):
+ """Evaluate the command line arguments and call MakeAppWorkDir."""
+ if args is None:
+ args = sys.argv[1:]
+ contextName = contextDir = cvsIgnore = user = group = None
+ libraryDirs = []
+ # Get all options:
+ from getopt import getopt, GetoptError
+ try:
+ opts, args = getopt(args, 'c:d:l:iu:g:', [
+ 'context-name=', 'context-dir=', 'library=',
+ 'cvsignore', 'user=', 'group='])
+ except GetoptError, error:
+ print str(error)
+ usage()
+ for opt, arg in opts:
+ if opt in ('-c', '--context-name'):
+ contextName = arg
+ elif opt in ('-d', '--context-dir'):
+ contextDir = arg
+ elif opt in ('-l', '--library'):
+ libraryDirs.append(arg)
+ elif opt in ('-i', '--cvsignore'):
+ cvsIgnore = 1
+ elif opt in ('-u', '--user'):
+ user = arg
+ elif opt in ('-g', '--group'):
+ group = arg
+ # Get the name of the target directory:
+ try:
+ workDir = args.pop(0)
+ workDir = os.path.join(workDir, 'WebKit')
+ except IndexError:
+ usage()
+ if args:# too many parameters
+ usage()
+ if os.path.exists(workDir):
+ print "The target directory already exists!"
+ sys.exit(1)
+ if not contextName:
+ if contextDir:
+ contextName = os.path.basename(contextDir)
+ else:
+ contextName = 'MyContext'
+ # Figure out the group id:
+ gid = group
+ if gid is not None:
+ try:
+ gid = int(gid)
+ except ValueError:
+ try:
+ import grp
+ entry = grp.getgrnam(gid)
+ except KeyError:
+ print 'Error: Group %r does not exist.' % gid
+ sys.exit(2)
+ except ImportError:
+ print 'Error: Group names are not supported.'
+ sys.exit(2)
+ gid = entry[2]
+ # Figure out the user id:
+ uid = user
+ if uid is not None:
+ try:
+ uid = int(uid)
+ except ValueError:
+ try:
+ import pwd
+ entry = pwd.getpwnam(uid)
+ except KeyError:
+ print 'Error: User %r does not exist.' % uid
+ sys.exit(2)
+ except ImportError:
+ print 'Error: User names are not supported.'
+ sys.exit(2)
+ if not gid:
+ gid = entry[3]
+ uid = entry[2]
+ # This assumes that this script is still located in Webware/bin:
+ scriptName = sys.argv and sys.argv[0]
+ if not scriptName or scriptName == '-c':
+ scriptName = 'MakeAppWorkDir.py'
+ binDir = os.path.dirname(os.path.abspath(scriptName))
+ webwareDir = os.path.abspath(os.path.join(binDir, os.pardir))
+ mawd = MakeAppWorkDir(webwareDir, workDir, 1, None,
+ contextName, contextDir, libraryDirs, cvsIgnore, uid, gid)
+ mawd.buildWorkDir() # go!
+
+if __name__ == '__main__':
+ main()
Added: Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusServer.py
==============================================================================
--- (empty file)
+++ Webware/trunk/WebKit/Adapters/CGIPlus/CgiPlusServer.py Wed Aug 23 16:19:35 2006
@@ -0,0 +1,112 @@
+import sys
+import os
+import mimetools
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+from WebKit.CgiPlusAppServer import Handler, CPASStreamOut
+import time
+
+
+class CgiPlusHandler:
+ """Handles incoming requests. Recreated with every request.
+ Abstract base class.
+ """
+ def __init__(self, env, rfile, wfile):
+ self.env = env
+ self.rfile = rfile
+ self.wfile = wfile
+ self._discardOutput = False
+ def handleRequest(self):
+ """
+ Actually performs the request, creating the environment and
+ calling self.doTransaction(env, myInput) to perform the
+ response.
+ """
+ myInput = ''
+ self._discardOutput = False
+ if self.env.has_key('CONTENT_LENGTH'):
+ length = int(self.env['CONTENT_LENGTH'])
+ if length > 0:
+ myInput = myInput + self.rfile.read(length)
+ self.doTransaction(self.env, myInput)
+
+ def processResponse(self, data):
+ """Takes a string (like what a CGI script would print) and
+ sends the actual HTTP response (response code, headers, body)."""
+ if self._discardOutput:
+ return
+ self.wfile.write(data)
+ self.wfile.flush()
+
+ def doLocation(self, headers):
+ """If there's a Location header and no Status header,
+ we need to add a Status header ourselves."""
+ if headers.has_key('Location'):
+ if not headers.has_key('Status'):
+ headers['Status'] = '301 Moved Temporarily'
+
+ def sendStatus(self, headers):
+ if not headers.has_key('Status'):
+ status = "200 OK"
+ else:
+ status = headers['Status']
+ del headers['Status']
+ pos = status.find(' ')
+ if pos == -1:
+ code = int(status)
+ message = ''
+ else:
+ code = int(status[:pos])
+ message = status[pos:].strip()
+ self.wfile.write("Status: %d %s\n" % (code, message))
+
+ def sendHeaders(self, headers):
+ for header, value in headers.items():
+ self.send_header(header, value)
+ self.end_headers()
+
+ def send_header(self, keyword, value):
+ """Send a MIME header."""
+ self.wfile.write("%s: %s\n" % (keyword, value))
+
+ def sendBody(self, bodyFile):
+ self.wfile.write(bodyFile.read())
+ bodyFile.close()
+ self.wfile.flush()
+
+ def end_headers(self):
+ """Send the blank line ending the MIME headers."""
+ self.wfile.write("\n")
+ self.wfile.flush()
+
+
+class CgiPlusAppServerHandler(Handler, CgiPlusHandler):
+ """Adapters CgiPlusHandler to fit with CgiPlusAppServer's
+ model of an adapter."""
+
+ protocolName = 'CgiPlus'
+
+ def handleRequest(self):
+ CgiPlusHandler.__init__(self, os.environ, os.sys.stdin, os.sys.__stdout__)
+ CgiPlusHandler.handleRequest(self)
+
+ def doTransaction(self, env, myInput):
+ streamOut = CPASStreamOut(os.sys.__stdout__)
+ requestDict = {
+ 'format': 'CGI',
+ 'time': time.time(),
+ 'environ': env,
+ 'input': StringIO(myInput),
+ 'requestID': self._requestID,
+ }
+ self.dispatchRawRequest(requestDict, streamOut)
+ self.processResponse(streamOut._buffer)
+
+ def dispatchRawRequest(self, requestDict, streamOut):
+ transaction = self._server._app.dispatchRawRequest(requestDict, streamOut)
+ streamOut.close()
+ transaction._application=None
+ transaction.die()
+ del transaction
Added: Webware/trunk/WebKit/Adapters/CGIPlus/README
==============================================================================
--- (empty file)
+++ Webware/trunk/WebKit/Adapters/CGIPlus/README Wed Aug 23 16:19:35 2006
@@ -0,0 +1,10 @@
+This directory contains some modifications and additions
+provided by Jean-Frans Pinne (jfp@...)
+for running Webware on OpenVMS in a WASD CGIPlus environment
+(multi processes, multi accounts).
+
+For more information see:
+
+ * http://pi-net.dyndns.org
+ * http://vmspython.dyndns.org
+ * http://wasd.vsm.com.au
\ No newline at end of file
|