[Zope-Checkins] CVS: Zope3/lib/python/Zope/StartUp - __init__.py:1.1.2.1 initZODB.py:1.1.2.1 metaConfigure.py:1.1.2.1 startup-meta.zcml:1.1.2.1 startup.py:1.1.2.1

Stephan Richter srichter@cbu.edu
Fri, 29 Mar 2002 14:44:21 -0500


Update of /cvs-repository/Zope3/lib/python/Zope/StartUp
In directory cvs.zope.org:/tmp/cvs-serv18519/lib/python/Zope/StartUp

Added Files:
      Tag: Zope-3x-branch
	__init__.py initZODB.py metaConfigure.py startup-meta.zcml 
	startup.py 
Log Message:
This is a first tackle of creating a Zope startup configuration file. It is 
not very flexible at the moment, simply because I do not know what is ahead
of us. However, I think it is better than what we had before.

Features:

- Specify the types of servers you want to start
- Decide which type of ZODB storage to use
- Decide where the logs should be written to.


Planned (if agreed with by the community):

- Make a server type registry, where developers can register new servers, 
  so that the site admin has only to select them and is not challenged with
  implementation details.

- Make a second registry for ZODB storage type for the same reasons as 
  above.

- Split the startup configuration into two sections:
  1. The programmer directives, that do all the low level stuff and provide
     the services for the higher level settings.
  2. The Site Admin directives, which then use the objects, which were 
     provided by the programmers



=== Added File Zope3/lib/python/Zope/StartUp/__init__.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""

$Id: __init__.py,v 1.1.2.1 2002/03/29 19:44:19 srichter Exp $
"""



=== Added File Zope3/lib/python/Zope/StartUp/initZODB.py ===


=== Added File Zope3/lib/python/Zope/StartUp/metaConfigure.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
# 
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
# 
##############################################################################
"""
This module handles the :startup directives. 

$Id: metaConfigure.py,v 1.1.2.1 2002/03/29 19:44:19 srichter Exp $
"""

import sys

# Import Configuration-related classes
from Zope.Configuration.Action import Action
from Zope.Configuration.ConfigurationDirectiveInterfaces \
     import INonEmptyDirective

# Import Undo-related classes 
from Zope.ComponentArchitecture import provideUtility
from Zope.App.Undo.ZODBUndoManager import ZODBUndoManager
from Zope.App.Undo.IUndoManager import IUndoManager

# Import Server-related
from Zope.Publisher.Browser.BrowserRequest import BrowserRequest
from Zope.App.ZopePublication.Browser.Publication import BrowserPublication

from Zope.Publisher.XMLRPC.XMLRPCRequest import XMLRPCRequest
from Zope.App.ZopePublication.XMLRPC.Publication import XMLRPCPublication


from Zope.App.Security.SimpleSecurityPolicies \
     import PermissiveSecurityPolicy
from Zope.App.Security.SecurityManager import setSecurityPolicy
from Zope.App.OFS.Folder.RootFolder import RootFolder
import asyncore, zLOG
from Zope.Server import ZLogIntegration
from Zope.Server.PublisherServers import PublisherHTTPServer
from Zope.Server.TaskThreads import ThreadedTaskDispatcher
from Zope.Server.HTTPServer import CommonHitLogger
from Zope.App.ZopePublication.ZopePublication import ZopePublication

import asyncore, zLOG

from ZODB.FileStorage import FileStorage
from ZODB import DB


DEFAULT_STORAGE = 'ZODB.FileStorage.'
DEFAULT_STORAGE_FILE = 'Data.fs'
DEFAULT_LOG_FILE = 'STDERR'
DEFAULT_LOG_CLASS = 'Zope.Server.HTTPServer.CommonHitLogger'
DEFAULT_SERVER_VERBOSE = 'true'


class SiteDefinition:

    __class_implements__ = INonEmptyDirective    

    # I wish we could specify this through the ZCML script, but I think
    # that would be too low level. 
    _server_types = {'Browser': (PublisherHTTPServer, BrowserPublication,
                                 BrowserRequest),
                     'XML-RPC': (PublisherHTTPServer, XMLRPCPublication,
                                 XMLRPCRequest),
                     'SOAP': None,
                     'FTP': None}

    # Some special file names for log files
    _special_log_files = {'STDERR': sys.stderr,
                          'STDOUT': sys.stdout}

    
    def __init__(self, _context, name="default", threads=4):
        """Initilize is called, when the defineSite directive is invoked.
        """
        self._name = name
        self._threads = int(threads)

        self._zodb = None
        self.useLog(_context)
        self._servers = {}

        self._started = 0


    def useStorage(self, _context, factory=DEFAULT_STORAGE,
                   file=DEFAULT_STORAGE_FILE):
        """Lets you specify the ZODB to use."""
        storage = _context.resolve(factory)
        self._zodb = DB(storage(file))
        return []
    

    def useLog(self, _context, file=DEFAULT_LOG_FILE):
        """Lets you specify the log file to use"""

        if file in self._special_log_files.keys():
            file = self._special_log_files[file]
        else:
            file = open(file, 'w')

        zLOG._set_log_dest(file)
        return []


    def addServer(self, _context, type='Browser', port='8081',
                  logClass=DEFAULT_LOG_CLASS, verbose='true'):
        """Add a new server for this site."""

        if verbose.lower() == 'true':
            verbose = 1
        else:
            verbose = 0

        logClass = _context.resolve(logClass)

        server_info = self._server_types.get(type, None)

        if type is not None:
            self._servers[type] = {'server': server_info[0],
                                    'publication': server_info[1],
                                    'request': server_info[2],
                                    'port': int(port),
                                    'logClass': logClass,
                                    'verbose': verbose}

            return [ Action(discriminator = 'Start Servers',
                           callable = self.start,
                           args = (),
                           ) ]
        else:
            sys.stderr.out('Warning: Server of Type %s does not exist. ' +
                           'Directive neglected.') 
            return []


    def start(self):
        """Now start all the servers"""

        sys.stderr.write('\nStarting Site: %s\n\n' %self._name)

        if not self._started:
            sys.setcheckinterval(120)

            # setup undo fnctionality
            provideUtility(IUndoManager, ZODBUndoManager(self._zodb))

            # Setup the task dispatcher
            td = ThreadedTaskDispatcher()
            td.setThreadCount(self._threads)

            # setup the storage, if not already done
            if self._zodb is None:
                self.useStorage(_context)

            # check whether a root was already specified for this ZODB; if
            # not create one.
            self._initDB()

            # Start the servers
            for type, server_info in self._servers.items():
                request_factory = RequestFactory(
                    server_info['publication'](self._zodb),
                    server_info['request'])
                apply(server_info['server'],
                      (request_factory, type, '', server_info['port']),
                      {'task_dispatcher': td,
                       'verbose': server_info['verbose'],
                       'hit_log': server_info['logClass']()})

            self._started = 1
        

    def _initDB(self):
        """Initialize the ZODB"""

        connection = self._zodb.open()
        root = connection.root()
        app = root.get(ZopePublication.root_name, None)

        if app is None:

            from Zope.App.OFS.Folder.RootFolder import RootFolder
            from Transaction import get_transaction
        
            app = RootFolder()
            root[ZopePublication.root_name] = app

            get_transaction().commit()

        connection.close()


    def __call__(self):
        "Handle empty/simple declaration."
        return []
    

defineSite = SiteDefinition


class RequestFactory:
    """This class will generically create RequestFactories. This way I do
       not have to create a method for each Server Type there is.
    """

    def __init__(self, publication, request):
        """Initialize Request Factory"""
        self._publication = publication
        self._request = request


    def __call__(self, input_stream, output_steam, env):
        """Call the Request Factory"""
        request = self._request(input_stream, output_steam, env)
        request.setPublication(self._publication)
        return request


=== Added File Zope3/lib/python/Zope/StartUp/startup-meta.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/zope'>

  <directives namespace="http://namespaces.zope.org/startup">

    <directive name="defineSite"
               attributes="name, threads"
               handler="Zope.StartUp.metaConfigure.defineSite">

      <subdirective name="useStorage"
                    attributes="factory, file" />

      <subdirective name="useLog" attributes="file" />

      <subdirective name="addServer"
                    attributes="type, port, verbose, logClass" />

    </directive>

  </directives>

</zopeConfigure>


=== Added File Zope3/lib/python/Zope/StartUp/startup.py ===