[Zope3-checkins] CVS: Zope3/src/zope/app/startup - __init__.py:1.2 bootstrap.py:1.2 configure.zcml:1.2 initzodb.py:1.2 meta.zcml:1.2 metaconfigure.py:1.2 requestfactory.py:1.2 requestfactoryregistry.py:1.2 servertype.py:1.2 servertyperegistry.py:1.2 simpleregistry.py:1.2 sitedefinition.py:1.2 startup.py:1.2

Jim Fulton jim@zope.com
Wed, 25 Dec 2002 09:13:57 -0500


Update of /cvs-repository/Zope3/src/zope/app/startup
In directory cvs.zope.org:/tmp/cvs-serv15352/src/zope/app/startup

Added Files:
	__init__.py bootstrap.py configure.zcml initzodb.py meta.zcml 
	metaconfigure.py requestfactory.py requestfactoryregistry.py 
	servertype.py servertyperegistry.py simpleregistry.py 
	sitedefinition.py startup.py 
Log Message:
Grand renaming:

- Renamed most files (especially python modules) to lower case.

- Moved views and interfaces into separate hierarchies within each
  project, where each top-level directory under the zope package
  is a separate project.

- Moved everything to src from lib/python.

  lib/python will eventually go away. I need access to the cvs
  repository to make this happen, however.

There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.



=== Zope3/src/zope/app/startup/__init__.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/__init__.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,2 @@
+#
+# This file is necessary to make this directory a package.


=== Zope3/src/zope/app/startup/bootstrap.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/bootstrap.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,98 @@
+##############################################################################
+#
+# Copyright (c) 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.
+#
+##############################################################################
+"""Bootstrap code.
+
+This module contains code to bootstrap a Zope3 instance.  For example
+it makes sure a root folder exists and creates and configures some
+essential services.
+
+$Id$
+"""
+from transaction import get_transaction
+
+from zope.app.traversing import traverse, traverseName
+from zope.app.publication.zopepublication import ZopePublication
+from zope.app.content.folder import RootFolder
+from zope.app.services.service import ServiceManager
+from zope.app.services.service import \
+     ServiceConfiguration
+from zope.app.services.hub import ObjectHub
+from zope.app.services.event import \
+     LocalEventService
+from zope.app.services.errorr import \
+     ErrorReportingService
+
+
+def bootstrapInstance(db):
+    """Bootstrap a Zope3 instance given a database object.
+
+    This first checks if the root folder exists.  If it exists, nothing
+    is changed.  If no root folder exists, one is added, and several
+    essential services are added and configured.
+    """
+    connection = db.open()
+    root = connection.root()
+    root_folder = root.get(ZopePublication.root_name, None)
+
+    if root_folder is None:
+        # Bootstrap code
+
+        root_folder = RootFolder()
+        addEssentialServices(root_folder)
+        root[ZopePublication.root_name] = root_folder
+
+        get_transaction().commit()
+
+    connection.close()
+
+
+def addEssentialServices(root_folder):
+    """Add essential services.
+
+    XXX This ought to be configurable.  For now, hardcode some
+    services we know we all need.
+    """
+    service_manager = ServiceManager()
+    root_folder.setServiceManager(service_manager)
+    addService(root_folder, 'Events', LocalEventService)
+    addService(root_folder, 'ObjectHub', ObjectHub)
+    addService(root_folder, 'ErrorReportingService', ErrorReportingService,
+               copy_to_zlog=True)
+
+
+def addService(root_folder, service_type, service_factory,
+               initial_status='Active', **kw):
+    """Add and configure a service to the root folder.
+
+    The service is added to the default package and activated.
+    This assumes the root folder already has a service manager,
+    and that we add at most one service of each type.
+    """
+    # The code here is complicated by the fact that the registry
+    # calls at the end require a fully context-wrapped
+    # configuration; hence all the traverse[Name]() calls.
+    package_name = ('', '++etc++Services', 'Packages', 'default')
+    package = traverse(root_folder, package_name)
+    name = service_type + '-1'
+    service = service_factory()
+    package.setObject(name, service)
+    configuration_manager = traverseName(package, 'configure')
+    configuration =  ServiceConfiguration(service_type,
+                                          package_name + (name,))
+    key = configuration_manager.setObject(None, configuration)
+    configuration = traverseName(configuration_manager, key)
+    configuration.status = initial_status
+    # Set additional attributes on the service
+    for k, v in kw.iteritems():
+        setattr(service, k, v)


=== Zope3/src/zope/app/startup/configure.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/configure.zcml	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,55 @@
+<zopeConfigure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:startup="http://namespaces.zope.org/startup">
+
+
+  <startup:registerRequestFactory name="BrowserRequestFactory"
+    publication = 
+    "zope.app.publication.browser.BrowserPublication"
+    request = "zope.publisher.browser.BrowserRequest" 
+  />
+
+
+  <startup:registerRequestFactory name="XMLRPCRequestFactory" 
+    publication = 
+    "zope.app.publication.xmlrpc.XMLRPCPublication"
+    request = "zope.publisher.xmlrpc.XMLRPCRequest" 
+  />
+
+
+  <startup:registerRequestFactory name="VFSRequestFactory"
+    publication = 
+    "zope.app.publication.vfs.VFSPublication"
+    request = "zope.publisher.vfs.VFSRequest" 
+  />
+
+
+  <startup:registerServerType 
+    name = "Browser"
+    factory = "zope.server.http.publisherhttpserver.PublisherHTTPServer"
+    requestFactory="BrowserRequestFactory"
+    logFactory = "zope.server.http.commonhitlogger.CommonHitLogger"
+    defaultPort="8080"
+    defaultVerbose="true" />
+
+
+  <startup:registerServerType 
+    name = "XML-RPC"
+    factory = "zope.server.http.publisherhttpserver.PublisherHTTPServer"
+    requestFactory="XMLRPCRequestFactory"
+    logFactory = "zope.server.http.commonhitlogger.CommonHitLogger"
+    defaultPort="8081"
+    defaultVerbose="true" />
+
+
+  <startup:registerServerType 
+    name = "FTP"
+    factory = "zope.server.ftp.publisherftpserver.PublisherFTPServer"
+    requestFactory="VFSRequestFactory"
+    logFactory = 
+    "zope.server.ftp.commonftpactivitylogger.CommonFTPActivityLogger"
+    defaultPort="8021"
+    defaultVerbose="true" />
+
+
+</zopeConfigure>


=== Zope3/src/zope/app/startup/initzodb.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/initzodb.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################


=== Zope3/src/zope/app/startup/meta.zcml 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/meta.zcml	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,33 @@
+<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
+
+  <directives namespace="http://namespaces.zope.org/startup">
+
+    <directive name="defineSite"
+               attributes="name threads"
+               handler="zope.app.startup.metaconfigure.defineSite">
+
+      <subdirective name="useFileStorage"
+                    attributes="file" />
+
+      <subdirective name="useMappingStorage" />
+
+      <subdirective name="useLog" attributes="file level" />
+
+      <subdirective name="addServer"
+                    attributes="type port verbose logClass" />
+
+    </directive>
+
+    <directive name="registerRequestFactory"
+               attributes="name publication request"
+               handler="zope.app.startup.metaconfigure.registerRequestFactory"
+               />
+
+    <directive name="registerServerType"
+               attributes="name publication request"
+               handler="zope.app.startup.metaconfigure.registerServerType"
+               />
+
+  </directives>
+
+</zopeConfigure>


=== Zope3/src/zope/app/startup/metaconfigure.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/metaconfigure.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# 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$
+"""
+
+from zope.app.startup.sitedefinition import SiteDefinition
+from zope.configuration.action import Action
+from zope.app.startup import requestfactoryregistry
+from zope.app.startup import servertyperegistry
+from zope.app.startup.requestfactory import RequestFactory
+from zope.app.startup.servertype import ServerType
+
+defineSite = SiteDefinition
+
+
+def registerRequestFactory(_context, name, publication, request):
+    publication = _context.resolve(publication)
+    request = _context.resolve(request)
+    request_factory = RequestFactory(publication, request)
+
+    return [
+        Action(
+            discriminator = name,
+            callable = requestfactoryregistry.registerRequestFactory,
+            args = (name, request_factory,),
+            )
+        ]
+
+
+def registerServerType(_context, name, factory, requestFactory, logFactory,
+                       defaultPort, defaultVerbose):
+    factory = _context.resolve(factory)
+    logFactory = _context.resolve(logFactory)
+
+    if defaultVerbose.lower() == 'true':
+        defaultVerbose = True
+    else:
+        defaultVerbose = False
+
+    defaultPort = int(defaultPort)
+
+    server_type = ServerType(name, factory, requestFactory, logFactory,
+                             defaultPort, defaultVerbose)
+
+    return [
+        Action(
+            discriminator = name,
+            callable = servertyperegistry.registerServerType,
+            args = (name, server_type),
+            )
+        ]


=== Zope3/src/zope/app/startup/requestfactory.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/requestfactory.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,65 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""ctory.py,v 1.1.2.2 2002/04/02 02:20:40 srichter Exp $
+"""
+
+from zope.interface import Interface
+import copy
+
+
+class IRequestFactory(Interface):
+    """This is a pure read-only interface, since the values are set through
+       a ZCML directive and we shouldn't be able to change them.
+    """
+
+    def realize(db):
+        """Realize the factory by initalizing the publication.
+
+           The method returns the realized object.
+        """
+
+
+    def __call__(input_stream, output_steam, env):
+        """Call the Request Factory"""
+
+
+
+
+
+class RequestFactory:
+    """This class will generically create RequestFactories. This way I do
+       not have to create a method for each Server Type there is.
+    """
+
+    __implements__ =  IRequestFactory
+
+    def __init__(self, publication, request):
+        """Initialize Request Factory"""
+        self._pubFactory = publication
+        self._publication = None
+        self._request = request
+
+
+    def realize(self, db):
+        'See IRequestFactory'
+        realized = copy.copy(self)
+        realized._publication = realized._pubFactory(db)
+        return realized
+
+
+    def __call__(self, input_stream, output_steam, env):
+        'See IRequestFactory'
+        request = self._request(input_stream, output_steam, env)
+        request.setPublication(self._publication)
+        return request


=== Zope3/src/zope/app/startup/requestfactoryregistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/requestfactoryregistry.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# 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$
+"""
+from zope.app.interfaces.startup.simpleregistry import ISimpleRegistry
+from zope.app.startup.simpleregistry import SimpleRegistry
+from zope.app.startup.requestfactory import IRequestFactory
+
+
+class IRequestFactoryRegistry(ISimpleRegistry):
+    """
+    The RequestFactory Registry manages a list of all the fields
+    available in Zope. A registry is useful at this point, since
+    fields can be initialized and registered by many places.
+
+    Note that it does not matter whether we have classes or instances as
+    fields. If the fields are instances, they must implement
+    IInstanceFactory.
+    """
+
+
+class RequestFactoryRegistry(SimpleRegistry):
+    __implements__ =  (IRequestFactoryRegistry,)
+
+
+RequestFactoryRegistry = RequestFactoryRegistry(IRequestFactory)
+registerRequestFactory = RequestFactoryRegistry.register
+getRequestFactory = RequestFactoryRegistry.get


=== Zope3/src/zope/app/startup/servertype.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/servertype.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""e.py,v 1.1.2.2 2002/04/02 02:20:40 srichter Exp $
+"""
+
+from zope.interface import Interface
+from zope.app.startup.requestfactoryregistry import getRequestFactory
+
+
+class IServerType(Interface):
+    """This is a pure read-only interface, since the values are set through
+       a ZCML directive and we shouldn't be able to change them.
+    """
+
+    def create(task_dispatcher, db, port=None, verbose=None):
+        """Create the server knowing the port, task dispatcher and the ZODB.
+        """
+
+
+class ServerType:
+
+    __implements__ =  IServerType
+
+
+    def __init__(self, name, factory, requestFactory, logFactory,
+                 defaultPort, defaultVerbose):
+        """ """
+        self._name = name
+        self._factory = factory
+        self._requestFactory = requestFactory
+        self._logFactory = logFactory
+        self._defaultPort = defaultPort
+        self._defaultVerbose = defaultVerbose
+
+
+    def create(self, task_dispatcher, db, port=None, verbose=None):
+        'See IServerType'
+
+        request_factory = getRequestFactory(self._requestFactory)
+        request_factory = request_factory.realize(db)
+
+        if port is None:
+            port = self._defaultPort
+
+        if verbose is None:
+            verbose = self._defaultVerbose
+
+        apply(self._factory,
+              (request_factory, self._name, '', port),
+              {'task_dispatcher': task_dispatcher,
+               'verbose': verbose,
+               'hit_log': self._logFactory()})


=== Zope3/src/zope/app/startup/servertyperegistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/servertyperegistry.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,41 @@
+##############################################################################
+#
+# 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$
+"""
+from zope.app.interfaces.startup.simpleregistry import ISimpleRegistry
+from zope.app.startup.servertype import IServerType
+from zope.app.startup.simpleregistry import SimpleRegistry
+
+
+class IServerTypeRegistry(ISimpleRegistry):
+    """
+    The ServerType Registry manages a list of all the fields
+    available in Zope. A registry is useful at this point, since
+    fields can be initialized and registered by many places.
+
+    Note that it does not matter whether we have classes or instances as
+    fields. If the fields are instances, they must implement
+    IInstanceFactory.
+    """
+
+
+class ServerTypeRegistry(SimpleRegistry):
+    """Registry for the various Server types"""
+    __implements__ =  (IServerTypeRegistry,)
+
+
+ServerTypeRegistry = ServerTypeRegistry(IServerType)
+registerServerType = ServerTypeRegistry.register
+getServerType = ServerTypeRegistry.get


=== Zope3/src/zope/app/startup/simpleregistry.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:56 2002
+++ Zope3/src/zope/app/startup/simpleregistry.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,96 @@
+##############################################################################
+#
+# 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$
+"""
+from zope.configuration.name import resolve
+from zope.app.interfaces.startup.simpleregistry import ISimpleRegistry
+from types import StringTypes, ListType, TupleType
+ListTypes = (TupleType, ListType)
+
+
+class ZopeDuplicateRegistryEntryError(Exception):
+    """
+    This Error is raised when the user tries to add an object with
+    a name that already exists in the registry. Therefore,
+    overwriting is not allowed.
+    """
+
+    def __init__(self, name):
+        """Initializes Error"""
+        self.name = name
+
+    def __str__(self):
+        """Returns string representation of Error"""
+        return "The name '%s' is already defined in this registry." \
+               %self.name
+
+
+class ZopeIllegalInterfaceError(Exception):
+    """This Error is thrown, when the passed object does not implement
+    the specified interface."""
+
+    def __init__(self, name, interface):
+        """Initalize Error"""
+        self.name = name
+        self.interface = interface
+
+    def __str__(self):
+        """Returns string representation of Error"""
+        return ( "The object with name " + self.name + " does not implement "
+                 "the interface " + self.interface.__name__ + "." )
+
+
+
+class SimpleRegistry:
+    """ """
+
+    __implements__ =  (ISimpleRegistry,)
+
+
+    def __init__(self, interface):
+        """Initialize registry"""
+        self.objects = {}
+        self.interface = interface
+
+
+    def register(self, name, object):
+        '''See ISimpleRegistry'''
+
+        if name in self.objects.keys():
+            raise ZopeDuplicateRegistryEntryError(name)
+
+        # XXX Find the right Interface tools to do that; unfortunately,
+        #     I have not found them
+        # Check whether the object implements the right interface.
+        # Note, that we do *not* know whether the object is an instance
+        # or a class (or worse a Persistent class)
+        if hasattr(object, '__implements__') and \
+               ( self.interface == object.__implements__ or \
+                 ( type(object.__implements__) in ListTypes and
+                   self.interface in object.__implements__ ) ):
+            self.objects[name] = object
+
+        else:
+            raise ZopeIllegalInterfaceError(name, self.interface)
+
+        return []
+
+
+    def get(self, name):
+        '''See ISimpleRegistry'''
+        if name in self.objects.keys():
+            return self.objects[name]
+        else:
+            return None


=== Zope3/src/zope/app/startup/sitedefinition.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:57 2002
+++ Zope3/src/zope/app/startup/sitedefinition.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,202 @@
+##############################################################################
+#
+# 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$
+"""
+
+import logging
+import sys
+
+# Importing zlogintegration redirects asyncore's logging to the
+# logging module
+from zope.server import zlogintegration
+
+# Import Configuration-related classes
+from zope.configuration.action import Action
+from zope.interfaces.configuration import INonEmptyDirective
+from zope.interfaces.configuration import ISubdirectiveHandler
+
+from zope.app.startup.servertyperegistry import getServerType
+
+# Import Undo-related classes
+from zope.app.content.folder import RootFolder
+from zope.app.interfaces.undo import IUndoManager
+from zope.app.publication.zopepublication import ZopePublication
+from zope.app.browser.undo import ZODBUndoManager
+from zope.component import getService
+from zope.server.taskthreads import ThreadedTaskDispatcher
+
+from zodb.code.module import PersistentModuleImporter
+
+DEFAULT_STORAGE_FILE = 'Data.fs'
+DEFAULT_LOG_FILE = 'STDERR'
+DEFAULT_LOG_LEVEL = 'INFO'
+
+
+class SiteDefinition:
+
+    __class_implements__ = INonEmptyDirective
+    __implements__ = ISubdirectiveHandler
+
+    # Some special file names for log files
+    _special_log_files = {'STDERR': sys.stderr,
+                          'STDOUT': sys.stdout}
+
+    # Mapping from log level names to numeric log levels
+    _log_levels = {
+        'CRITICAL' : logging.CRITICAL,
+        'ERROR' : logging.ERROR,
+        'WARN' : logging.WARN,
+        'INFO' : logging.INFO,
+        'DEBUG' : logging.DEBUG,
+        'NOTSET' : logging.NOTSET,
+        }
+
+
+    def __init__(self, _context, name="default", threads=4):
+        """Initialize is called when defineSite directive is invoked."""
+        self._name = name
+        self._threads = int(threads)
+
+        self._zodb = None
+        self.useLog(_context)
+        self._servers = {}
+
+        self._started = 0
+
+    def close(self):
+        if self._zodb is not None:
+            self._zodb.close()
+            self._zodb = None
+
+    def useFileStorage(self, _context, file=DEFAULT_STORAGE_FILE):
+        """Lets you specify the ZODB to use."""
+        from zodb.storage.file import DB
+        if self._zodb is not None:
+            raise RuntimeError("Database already open")
+        self._zodb = DB(file)
+        return []
+
+
+    def useMappingStorage(self, _context):
+        """Lets you specify the ZODB to use."""
+        from zodb.storage.mapping import DB
+        if self._zodb is not None:
+            raise RuntimeError("Database already open")
+        self._zodb = DB()
+        return []
+
+
+    def useLog(self, _context, file=DEFAULT_LOG_FILE, level=DEFAULT_LOG_LEVEL):
+        """Lets you specify the log file and level to use"""
+
+        # Translate the level to logging
+        loglevel = self._log_levels.get(level.upper())
+        if loglevel is None:
+            raise ValueError, "unknown log level %r" % level
+
+        # Get the root logger and set its logging level
+        root = logging.root
+        root.setLevel(loglevel)
+
+        # Remove previous handlers
+        for h in root.handlers[:]:
+            root.removeHandler(h)
+
+        # Create the new handler
+        if file in self._special_log_files.keys():
+            file = self._special_log_files[file]
+            handler = logging.StreamHandler(file)
+        else:
+            handler = logging.FileHandler(file)
+
+        # Create a standard Zope-style formatter and set it
+        formatter = logging.Formatter(
+            "------\n"
+            "%(asctime)s %(levelname)s %(name)s %(message)s",
+            datefmt="%Y-%m-%dT%H:%M:%S")
+        handler.setFormatter(formatter)
+
+        # Set the handler
+        root.addHandler(handler)
+
+        # Return empty sequence to satisfy API
+        return []
+
+
+    def addServer(self, _context, type, port=None, verbose=None):
+        """Add a new server for this site."""
+
+        if port is not None:
+            port = int(port)
+
+        if verbose is not None:
+            if verbose.lower() == 'true': verbose = 1
+            else: verbose = 0
+
+        if type is not None:
+            self._servers[type] = {'port': port,
+                                   'verbose': verbose}
+        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)
+
+        sys.setcheckinterval(120)
+
+        # setup undo fnctionality
+        getService(None,"Utilities").provideUtility(
+            IUndoManager,
+            ZODBUndoManager(self._zodb)
+            )
+
+        # Setup the task dispatcher
+        td = ThreadedTaskDispatcher()
+        td.setThreadCount(self._threads)
+
+        # 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():
+
+            server = getServerType(type)
+            server.create(td, self._zodb, server_info['port'],
+                          server_info['verbose'])
+
+    def _initDB(self):
+        """Initialize the ZODB and persistence module importer."""
+
+        from zope.app.startup import bootstrap
+        bootstrap.bootstrapInstance(self._zodb)
+
+        imp = PersistentModuleImporter()
+        imp.install()
+
+
+    def __call__(self):
+        "Handle empty/simple declaration."
+        return [ Action(discriminator = 'Start Servers',
+                        callable = self.start,
+                        args = ()),
+                 ]


=== Zope3/src/zope/app/startup/startup.py 1.1 => 1.2 ===
--- /dev/null	Wed Dec 25 09:13:57 2002
+++ Zope3/src/zope/app/startup/startup.py	Wed Dec 25 09:13:24 2002
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################