[Zope3-checkins] SVN: Zope3/branches/srichter-twisted-integration/ Correct way of integrating Twisted into Zope 3 thanks to Itamar's help.

Stephan Richter srichter at cosmos.phy.tufts.edu
Mon Apr 18 19:09:52 EDT 2005


Log message for revision 30033:
  Correct  way of integrating Twisted into Zope 3 thanks to Itamar's help.
  
  We now have:
  
  - a HTTP and HTTPS server over WSGI.
  
  - Twisted's async loop.
  
  - Adjusted server type code.
  
  - Thread management.
  
  Outstanding issues:
  
  - zope.app.recorder heavily depended on zope.server, so it has to be 
    completely restructured.
  
  - The FTP server is not working yet, since it has to be rewritten 
    (a Twisted folk task)
  
  - Logging has to be reimplemented. (I am pretty much done; just needs test 
    and a slightly priprietary extension to WSGI that the twisted.web2 
    author and I already agreed upon. WSGI is not the holy grail it seems at 
    first!) 
  
  - Client (SSL) certificate validation via an interface.
  
  - Graceful TTW shutdown.
  
  

Changed:
  U   Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt
  U   Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml
  A   Zope3/branches/srichter-twisted-integration/server.pem
  A   Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py
  A   Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py
  D   Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py
  A   Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_docs.py
  U   Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py
  D   Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py
  D   Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py
  D   Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py
  U   Zope3/branches/srichter-twisted-integration/zope.conf.in

-=-
Modified: Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt
===================================================================
--- Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/doc/TWISTED-TODO.txt	2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,18 +1,12 @@
 ToDo List for Twisted Integration
 =================================
 
-* Implement graceful shutdown, including KeyboardInterrupt.
-
-* Set the thread count. Itamar suggested having our own thread pool.
-
-* Use configuration information to create servers.
-
-* Use old server-type utility code to generate servers.
-
-* Have information being displayed on the screen upon server start.
-
 * Display username in logs. In general, we need to do logging based on the info
   from zope.conf.
 
+  - Push logging to Zope App Server.
+
 * We need to get an FTP server working. FTP is a long-supported protocol and
-  we cannot have a Zope 3 version without it.
\ No newline at end of file
+  we cannot have a Zope 3 version without it.
+
+* SSL HTTP support. Client certificate validation.

Modified: Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml
===================================================================
--- Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/package-includes/zope.app.recorder-configure.zcml	2005-04-18 23:09:52 UTC (rev 30033)
@@ -1 +1,3 @@
-<include package="zope.app.recorder" />
+<!-- XXX: This code relies on ZServer, which is not more! -->
+<!-- include package="zope.app.recorder" / -->
+<configure />

Added: Zope3/branches/srichter-twisted-integration/server.pem
===================================================================
--- Zope3/branches/srichter-twisted-integration/server.pem	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/server.pem	2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAm+gAwIBAgIBATANBgkqhkiG9w0BAQQFADB7MQswCQYDVQQGEwJTRzER
+MA8GA1UEChMITTJDcnlwdG8xFDASBgNVBAsTC00yQ3J5cHRvIENBMSQwIgYDVQQD
+ExtNMkNyeXB0byBDZXJ0aWZpY2F0ZSBNYXN0ZXIxHTAbBgkqhkiG9w0BCQEWDm5n
+cHNAcG9zdDEuY29tMB4XDTAwMDkxMDA5NTEzMFoXDTAyMDkxMDA5NTEzMFowUzEL
+MAkGA1UEBhMCU0cxETAPBgNVBAoTCE0yQ3J5cHRvMRIwEAYDVQQDEwlsb2NhbGhv
+c3QxHTAbBgkqhkiG9w0BCQEWDm5ncHNAcG9zdDEuY29tMFwwDQYJKoZIhvcNAQEB
+BQADSwAwSAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
+5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAaOCAQQwggEAMAkGA1UdEwQC
+MAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl
+MB0GA1UdDgQWBBTPhIKSvnsmYsBVNWjj0m3M2z0qVTCBpQYDVR0jBIGdMIGagBT7
+hyNp65w6kxXlxb8pUU/+7Sg4AaF/pH0wezELMAkGA1UEBhMCU0cxETAPBgNVBAoT
+CE0yQ3J5cHRvMRQwEgYDVQQLEwtNMkNyeXB0byBDQTEkMCIGA1UEAxMbTTJDcnlw
+dG8gQ2VydGlmaWNhdGUgTWFzdGVyMR0wGwYJKoZIhvcNAQkBFg5uZ3BzQHBvc3Qx
+LmNvbYIBADANBgkqhkiG9w0BAQQFAAOBgQA7/CqT6PoHycTdhEStWNZde7M/2Yc6
+BoJuVwnW8YxGO8Sn6UJ4FeffZNcYZddSDKosw8LtPOeWoK3JINjAk5jiPQ2cww++
+7QGG/g5NDjxFZNDJP1dGiLAxPW6JXwov4v0FmdzfLOZ01jDcgQQZqEpYlgpuI5JE
+WUQ9Ho4EzbYCOQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAKy+e3dulvXzV7zoTZWc5TzgApr8DmeQHTYC8ydfzH7EECe4R1Xh
+5kwIzOuuFfn178FBiS84gngaNcrFi0Z5fAkCAwEAAQJBAIqm/bz4NA1H++Vx5Ewx
+OcKp3w19QSaZAwlGRtsUxrP7436QjnREM3Bm8ygU11BjkPVmtrKm6AayQfCHqJoT
+ZIECIQDW0BoMoL0HOYM/mrTLhaykYAVqgIeJsPjvkEhTFXWBuQIhAM3deFAvWNu4
+nklUQ37XsCT2c9tmNt1LAT+slG2JOTTRAiAuXDtC/m3NYVwyHfFm+zKHRzHkClk2
+HjubeEgjpj32AQIhAJqMGTaZVOwevTXvvHwNEH+vRWsAYU/gbx+OQB+7VOcBAiEA
+oolb6NMg/R3enNPvS1O4UU1H8wpaF77L4yiSWlE0p4w=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBDTCBuAIBADBTMQswCQYDVQQGEwJTRzERMA8GA1UEChMITTJDcnlwdG8xEjAQ
+BgNVBAMTCWxvY2FsaG9zdDEdMBsGCSqGSIb3DQEJARYObmdwc0Bwb3N0MS5jb20w
+XDANBgkqhkiG9w0BAQEFAANLADBIAkEArL57d26W9fNXvOhNlZzlPOACmvwOZ5Ad
+NgLzJ1/MfsQQJ7hHVeHmTAjM664V+fXvwUGJLziCeBo1ysWLRnl8CQIDAQABoAAw
+DQYJKoZIhvcNAQEEBQADQQA7uqbrNTjVWpF6By5ZNPvhZ4YdFgkeXFVWi5ao/TaP
+Vq4BG021fJ9nlHRtr4rotpgHDX1rr+iWeHKsx4+5DRSy
+-----END CERTIFICATE REQUEST-----

Added: Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt	2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,159 @@
+=================================
+Zope 3 Application Server Support
+=================================
+
+This package is responsible for initializing and starting the servers that
+will provide access to the Zope 3 application. This package is heavily
+twisted-depedent, though some pieces can be reused to bring up the Zope 3
+application server in other environemnts.
+
+
+Server Types
+------------
+
+Zope 3 needs to support many server types -- HTTP, FTP, HTTP with postmortem
+debugging, etc.  All of them are registered as ``IServerType`` utilities in
+ZCML. This allows developers to easily develop and register new servers for
+Zope 3.
+
+``ServerType`` is an implementation of ``IServerType`` that is specific to the
+standard Twisted servers..  The constructor of ``ServerType`` takes three
+arguments: the factory that will create a Twisted ``IServerFactory`` object
+and the default port and IP to which to bind the server.
+
+The ``factory`` argument should be a callable expecting one argument, the ZODB
+instance. It is up to the factory, to implement the necessary glue between the
+server and the application:
+
+  >>> class TwistedServerFactoryStub(object):
+  ...     def doStart(self): pass
+
+  >>> def factory(db):
+  ...     print 'ZODB: %s' %db
+  ...     return TwistedServerFactoryStub()
+
+For the other two constructor arguments of ``ServerType``, the ``defaultPort``
+argument specifies the default TCP port number for the server. The
+``defaultIP`` argument specifies the network interface for listening on.  You
+can specify the network interface IP address, or an empty string if you want
+to listen on all interfaces.
+
+We are now ready to instantiate the server type:
+
+  >>> from zope.app.server.server import ServerType
+  >>> st = ServerType(factory, defaultPort=8080)
+
+and let's make sure it really implements the promised interface:
+
+  >>> from zope.interface.verify import verifyObject
+  >>> from zope.app.server.interfaces import IServerType
+  >>> verifyObject(IServerType, st)
+  True
+
+A server type is then registered as a named utility.  These utilities are used
+while interpreting ``<server>`` sections of `zope.conf` to create instances of
+servers listening on a specific port.
+
+When you create an instance of a server using the ``create()`` method of the
+server type, you need to tell it an identifying name and a the ZODB database
+object. The IP address, port and backlog count can be optionally passed to the
+method. 
+
+  >>> db = 'my database'
+  >>> server = st.create('Example-HTTP', db, port=8080)
+  ZODB: my database
+  >>> server #doctest:+ELLIPSIS
+  <zope.app.server.server.ZopeTCPServer instance at ...>
+
+As you can see the server type creates a Zope-specific TCP server, which is
+simply a standard ``twisted.internet.TCPServer`` that creates a log entry upon
+startup.
+
+  >>> server.startService()
+  >>> print log.getvalue()
+  -- Example-HTTP Server started.
+     Hostname: localhost
+     Port: 8080
+
+You can, of course, create multiple instances of the same server type, and
+bind them to different ports.
+
+  >>> server2 = st.create('Example-HTTP-2', db, port=8081)
+  ZODB: my database
+
+  >>> server2.startService()
+  >>> print log.getvalue()
+  -- Example-HTTP Server started.
+     Hostname: localhost
+     Port: 8080
+  -- Example-HTTP-2 Server started.
+     Hostname: localhost
+     Port: 8081
+
+A special type of server type is the SSL server type; it requires some
+additional information (private key path, certificate path, and TLS flag) to
+start up the server. The setup will only work, if OpenSSL is installed:
+
+  # >>> from zope.app.server.server import SSLServerType
+  # >>> ssl_st = SSLServerType(factory, defaultPort=8443)
+  # 
+  # >>> ssl_server = ssl_st.create('Example-HTTPS', db,
+  # ...                            'server.pem', 'server.pem')
+  # ZODB: my database
+  # >>> ssl_server #doctest:+ELLIPSIS
+  # <zope.app.server.server.ZopeSSLServer instance at ...>
+
+
+Server Factories
+----------------
+
+Now, of course we do not hardwire the setup of actual servers in
+Python. Instead, we are using ZConfig to setup the servers. Unfortunately that
+means that we need yet another abstraction layer to setup the
+servers. ZConfig-based configuration code creates so called ``ServerFactory``
+and ``SSLServerFactory`` objects that then use the server types to create the
+servers.
+
+  >>> from zope.interface import implements
+  >>> from zope.app.server.interfaces import IServerType
+  >>> class MyServerType:
+  ...     implements(IServerType)
+  ...     def create(self, name, db,
+  ...                port='unknown', ip='', backlog=50):
+  ...         if not ip:
+  ...             ip = '*' # listen on all interfaces
+  ...         return ('%s server on %s:%d, registered with %s, backlog %d'
+  ...                 % (name, ip, port, db, backlog))
+
+  >>> from zope.app.testing import ztapi
+  >>> ztapi.provideUtility(IServerType, MyServerType(), name='HTTP')
+  >>> ztapi.provideUtility(IServerType, MyServerType(), name='FTP')
+
+``ServerFactory`` is used to hook into ZConfig and create instances of servers
+specified in `zope.conf`.  It gets a `section` argument that contains settings
+specified in a ZConfig ``<server>`` section.
+
+    >>> class ServerSectionStub:
+    ...     type = 'HTTP'
+    ...     address = ('', 8080)
+    ...     backlog = 30
+    >>> my_section = ServerSectionStub()
+
+    >>> from zope.app.server.server import ServerFactory
+    >>> sf = ServerFactory(my_section)
+
+The server factory object knows how to create a server, given a ZODB database
+object.
+
+    >>> db = 'my db'
+    >>> print sf.create(db)
+    HTTP server on *:8080, registered with my db, backlog 30
+
+The settings should actually work with FTP as well. 
+
+    >>> my_section.type = 'FTP'
+    >>> my_section.address = ('127.0.0.1', 8021)
+    >>> sf = ServerFactory(my_section)
+    >>> print sf.create(db)
+    FTP server on 127.0.0.1:8021, registered with my db, backlog 30
+


Property changes on: Zope3/branches/srichter-twisted-integration/src/zope/app/server/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/configure.zcml	2005-04-18 23:09:52 UTC (rev 30033)
@@ -7,25 +7,27 @@
   <utility
       name="HTTP"
       component=".http.http"
-      provides=".servertype.IServerType"
+      provides=".interfaces.IServerType"
       />
 
   <utility
-      name="PostmortemDebuggingHTTP"
-      component=".http.pmhttp"
-      provides=".servertype.IServerType"
+      name="HTTPS"
+      component=".http.https"
+      provides=".interfaces.IServerType"
       />
 
   <utility
-      name="WSGI-HTTP"
-      component=".wsgi.http"
-      provides=".servertype.IServerType"
+      name="PostmortemDebuggingHTTP"
+      component=".http.pmhttp"
+      provides=".interfaces.IServerType"
       />
 
+<!--
   <utility
       name="FTP"
       component=".ftp.server"
-      provides=".servertype.IServerType"
+      provides=".interfaces.IServerType"
       />
+-->
 
 </configure>

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/ftp.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -55,3 +55,201 @@
     FTPRequestFactory,
     CommonFTPActivityLogger,
     8021, True)
+
+
+
+import posixpath
+
+from cStringIO import StringIO
+
+from zope.server.interfaces.ftp import IFileSystem
+from zope.server.interfaces.ftp import IFileSystemAccess
+
+from zope.server.ftp.server import FTPServer
+from zope.publisher.publish import publish
+
+from zope.interface import implements
+
+class FileSystem(object):
+    """Generic Publisher FileSystem implementation."""
+
+    implements(IFileSystem)
+
+    def __init__ (self, credentials, request_factory):
+        self.credentials = credentials
+        self.request_factory = request_factory
+
+    def type(self, path):
+        if path == '/':
+            return 'd'
+
+        return self._execute(path, 'type')
+
+    def names(self, path, filter=None):
+        return self._execute(path, 'names', split=False, filter=filter)
+
+    def ls(self, path, filter=None):
+        return self._execute(path, 'ls', split=False, filter=filter)
+
+    def readfile(self, path, outstream, start=0, end=None):
+        return self._execute(path, 'readfile', 
+                             outstream=outstream, start=start, end=end)
+
+    def lsinfo(self, path):
+        return self._execute(path, 'lsinfo')
+
+    def mtime(self, path):
+        return self._execute(path, 'mtime')
+
+    def size(self, path):
+        return self._execute(path, 'size')
+
+    def mkdir(self, path):
+        return self._execute(path, 'mkdir')
+
+    def remove(self, path):
+        return self._execute(path, 'remove')
+
+    def rmdir(self, path):
+        return self._execute(path, 'rmdir')
+
+    def rename(self, old, new):
+        'See IWriteFileSystem'
+        old = self._translate(old)
+        new = self._translate(new)
+        path0, old = posixpath.split(old)
+        path1, new = posixpath.split(new)
+        assert path0 == path1
+        return self._execute(path0, 'rename', split=False, old=old, new=new)
+
+    def writefile(self, path, instream, start=None, end=None, append=False):
+        'See IWriteFileSystem'
+        return self._execute(
+            path, 'writefile',
+            instream=instream, start=start, end=end, append=append)
+
+    def writable(self, path):
+        'See IWriteFileSystem'
+        return self._execute(path, 'writable')
+
+    def _execute(self, path, command, split=True, **kw):
+        env = {}
+        env.update(kw)
+        env['command'] = command
+
+        path = self._translate(path)
+
+        if split:
+            env['path'], env['name'] = posixpath.split(path)
+        else:
+            env['path'] = path
+            
+        env['credentials'] = self.credentials
+        # NoOutput avoids creating a black hole.
+        request = self.request_factory(StringIO(''), NoOutput(), env)
+
+        # Note that publish() calls close() on request, which deletes the
+        # response from the request, so that we need to keep track of it.
+        response = request.response
+        publish(request)
+        return response.getResult()
+
+    def _translate (self, path):
+        # Normalize
+        path = posixpath.normpath(path)
+        if path.startswith('..'):
+            # Someone is trying to get lower than the permitted root.
+            # We just ignore it.
+            path = '/'
+        return path
+
+
+class NoOutput(object):
+    """An output stream lookalike that warns you if you try to
+    dump anything into it."""
+
+    def write(self, data):
+        raise RuntimeError, "Not a writable stream"
+
+    def flush(self):
+        pass
+
+    close = flush
+
+
+from twisted.protocols import ftp
+from twisted.internet import threads
+
+class ZopeFTPShell(object):
+    """ """
+    implements(ftp.IFTPShell)
+
+    def __init__(self, db, username, password):
+        self._dir = '/'
+        self.publication = FTPPublication(db)
+        self.credentials = (username, password)
+
+    def mapCPathToSPath(self, path):
+        return path
+
+    def pwd(self):
+        return self._dir
+
+    def cwd(self, path):
+        self._dir = posixpath.join(self._dir, path)
+
+    def cdup(self):
+        self.cwd('..')
+
+    def size(self, path):
+        return threads.deferredToThread(self._execute, path, 'size')
+
+    def mkd(self, path):
+        return threads.deferredToThread(self._execute, path, 'mkdir')
+
+    def rmd(self, path):
+        return threads.deferredToThread(self._execute, path, 'rmdir')
+
+    def dele(self, path):
+        return threads.deferredToThread(self._execute, path, 'remove')
+
+    def list(self, path):
+        return threads.deferredToThread(self._execute, path, 'ls')
+
+    def nlst(self, path):
+        pass
+
+    def retr(self, path):
+        pass
+
+    def stor(self, params):
+        pass
+
+    def mdtm(self, path):
+        pass
+
+    def _execute(self, path, command, split=True, **kw):
+        '''This is running in a thread!'''
+        path = posixpath.join(self._dir, path)
+
+        env = {}
+        env.update(kw)
+        env['command'] = command
+
+        path = self._translate(path)
+
+        if split:
+            env['path'], env['name'] = posixpath.split(path)
+        else:
+            env['path'] = path
+            
+        env['credentials'] = self.credentials
+        # NoOutput avoids creating a black hole.
+        request = FTPRequest(StringIO(''), output_steam, env)
+        request.setPublication(self.publication)
+
+        # Note that publish() calls close() on request, which deletes the
+        # response from the request, so that we need to keep track of it.
+        response = request.response
+        publish(request)
+        return response.getResult()

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/http.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -15,19 +15,31 @@
 
 $Id$
 """
+import twisted.web2.wsgi
+import twisted.web2.server
 
-from zope.app.publication.httpfactory import HTTPPublicationRequestFactory
-from zope.app.server.servertype import ServerType
-from zope.server.http.commonaccesslogger import CommonAccessLogger
-from zope.server.http.publisherhttpserver import PMDBHTTPServer
-from zope.server.http.publisherhttpserver import PublisherHTTPServer
+from zope.app.server.server import ServerType, SSLServerType
+from zope.app import wsgi
 
-http = ServerType(PublisherHTTPServer,
-                  HTTPPublicationRequestFactory,
-                  CommonAccessLogger,
-                  8080, True)
 
-pmhttp = ServerType(PMDBHTTPServer,
-                    HTTPPublicationRequestFactory,
-                    CommonAccessLogger,
-                    8013, True)
+def createHTTPFactory(db):
+    resource = twisted.web2.wsgi.WSGIResource(
+        wsgi.WSGIPublisherApplication(db))
+    
+    return twisted.web2.server.Site(resource)
+
+
+http = ServerType(createHTTPFactory, 8080)
+
+https = SSLServerType(createHTTPFactory, 8443)
+
+
+def createHTTPFactory(db):
+    resource = twisted.web2.wsgi.WSGIResource(
+        wsgi.PMDBWSGIPublisherApplication(db))
+    
+    return twisted.web2.server.Site(resource)
+
+pmhttp = ServerType(createHTTPFactory, 8080)
+
+

Added: Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,45 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Server Setup Interfaces
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+from zope.interface import Interface
+
+class IServerType(Interface):
+    """Server Type utility.
+
+    A utility that the can create a server instance.
+
+    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(name, db, ip=None, port=None, backlog=50):
+        """Create the server knowing the port, IP address and the ZODB.
+
+        Returns the new server.
+        """
+
+class ISSLServerType(IServerType):
+    """SSL Server Type utility"""
+    
+    def create(name, db, privateKeyPath, certificatePath, tls=False,
+               ip=None, port=None, backlog=50):
+        """Create an SSL server instance.
+
+        This differs only in respect to that it needs the private key path,
+        certificate key path and TLS flag to instantiate the server.
+        """


Property changes on: Zope3/branches/srichter-twisted-integration/src/zope/app/server/interfaces.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/main.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -24,14 +24,14 @@
 
 import twisted.web2.wsgi
 import twisted.web2.server
-import twisted.application.service
-import twisted.application.strports
+from twisted.application import service
 from twisted.internet import reactor
 
+from zope.event import notify
+
 import zope.app.appsetup
 import zope.app.appsetup.interfaces
 from zope.app import wsgi
-from zope.event import notify
 
 CONFIG_FILENAME = "zope.conf"
 
@@ -50,18 +50,29 @@
         return None
 
 
+class ZopeService(service.MultiService):
+
+    def startService(self):
+        notify(zope.app.appsetup.interfaces.ProcessStarting())
+        service.MultiService.startService(self)
+
+    # can override stopService or similar to implement shutdown event later.
+
+
 def main(args=None):
     # Record start times (real time and CPU time)
     t0 = time.time()
     c0 = time.clock()
 
-    setup(load_options(args))
+    service = setup(load_options(args))
+    service.startService()
+    reactor.addSystemEventTrigger('before', 'shutdown', service.stopService)
 
     t1 = time.time()
     c1 = time.clock()
     logging.info("Startup time: %.3f sec real, %.3f sec CPU", t1-t0, c1-c0)
 
-    run()
+    reactor.run()
     sys.exit(0)
 
 
@@ -75,14 +86,6 @@
     return db
 
 
-def run():
-    try:
-        reactor.run()
-    except KeyboardInterrupt:
-        # Exit without spewing an exception.
-        pass
-
-
 def load_options(args=None):
     if args is None:
         args = sys.argv[1:]
@@ -108,18 +111,13 @@
 
     notify(zope.app.appsetup.interfaces.DatabaseOpened(db))
 
-    # Simple setup of a WSGI-based Twisted HTTP server
-    resource = twisted.web2.wsgi.WSGIResource(
-        wsgi.WSGIPublisherApplication(db))
+    # Set number of threads
+    reactor.suggestThreadPoolSize(options.threads)
 
-    reactor.listenTCP(8080, twisted.web2.server.Site(resource))
+    rootService = ZopeService()
 
-    #task_dispatcher = ThreadedTaskDispatcher()
-    #task_dispatcher.setThreadCount(options.threads)
-    #
-    #for server in options.servers:
-    #    server.create(task_dispatcher, db)
+    for server in options.servers + options.sslservers:
+        service = server.create(db)
+        service.setServiceParent(rootService)
 
-    notify(zope.app.appsetup.interfaces.ProcessStarting())
-
-    return db
+    return rootService

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/schema.xml	2005-04-18 23:09:52 UTC (rev 30033)
@@ -16,9 +16,18 @@
   <sectiontype name="server" datatype="zope.app.server.server.ServerFactory">
     <key name="type" required="yes" />
     <key name="address" datatype="inet-address" />
-    <key name="verbose" datatype="boolean" />
+    <key name="backlog" datatype="integer" default="50" />
   </sectiontype>
 
+  <sectiontype name="sslserver" 
+               extends="server"
+               datatype="zope.app.server.server.SSLServerFactory">
+    <key name="privatekeypath" datatype="existing-file" required="yes" />
+    <key name="certificatepath" datatype="existing-file" required="yes" />
+    <key name="tls" datatype="boolean" default="false" />
+  </sectiontype>
+
+
   <section type="ZODB.database" name="*" required="yes"
            attribute="database">
     <description>
@@ -40,6 +49,7 @@
   </section>
 
   <multisection type="server" name="*" attribute="servers" />
+  <multisection type="sslserver" name="*" attribute="sslservers" />
 
   <key name="site-definition" default="site.zcml">
     <description>

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/server.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -17,12 +17,107 @@
 
 $Id$
 """
+import logging
+
+from zope.interface import implements
 from zope.app import zapi
-from zope.app.server.servertype import IServerType
+from zope.app.server.interfaces import IServerType, ISSLServerType
 
+from twisted.application import internet
+from twisted.internet import reactor, interfaces
+
+class SSLNotSupported(Exception):
+    ''' '''
+
+def logStartUp(service):
+    logging.info('-- %s Server started.\n'
+                 '\tHostname: %s\n\tPort: %d' % (
+            service.name,
+            service.kwargs['interface'] or 'localhost',
+            service.args[0]
+            ))
+    
+
+class ZopeTCPServer(internet.TCPServer):
+
+    def __init__(self, name, *args, **kwargs):
+        internet.TCPServer.__init__(self, *args, **kwargs)        
+        self.name = name
+
+    def startService(self):
+        internet.TCPServer.startService(self)
+        logStartUp(self)
+
+class ZopeSSLServer(internet.SSLServer):
+
+    def __init__(self, name, *args, **kwargs):
+        internet.SSLServer.__init__(self, *args, **kwargs)        
+        self.name = name
+
+    def startService(self):
+        internet.SSLServer.startService(self)
+        logStartUp(self)
+        
+
+class ServerType(object):
+
+    implements(IServerType)
+
+    def __init__(self, factory, defaultPort, defaultIP=''):
+        self._factory = factory
+        self._defaultPort = defaultPort
+        self._defaultIP = defaultIP
+
+    def create(self, name, db, ip=None, port=None, backlog=50):
+        'See IServerType'
+        if port is None:
+            port = self._defaultPort
+
+        if ip is None:
+            ip = self._defaultIP
+
+        # Given a database, create a twisted.internet.interfaces.IServerFactory
+        factory = self._factory(db)
+        return ZopeTCPServer(name, port, factory, interface=ip, backlog=backlog)
+
+
+class SSLServerType(ServerType):
+
+    implements(IServerType)
+
+    def create(self, name, db, privateKeyPath, certificatePath, tls=False,
+               ip=None, port=None, backlog=50):
+        'See IServerType'
+        if port is None:
+            port = self._defaultPort
+
+        if ip is None:
+            ip = self._defaultIP
+
+        if not interfaces.IReactorSSL.providedBy(reactor):
+            raise SSLNotSupported
+
+        from twisted.internet import ssl
+        from OpenSSL import SSL
+        if tls:
+            method = SSL.TLSv1_METHOD
+        else:
+            method = SSL.SSLv23_METHOD
+
+        contextFactory = ssl.DefaultOpenSSLContextFactory(
+            privateKeyPath, certificatePath, method)
+
+        # Given a database, create a twisted.internet.interfaces.IServerFactory
+        factory = self._factory(db)
+        return ZopeSSLServer(name, port, factory, contextFactory,
+                             interface=ip, backlog=backlog)
+
+
 class ServerFactory(object):
     """Factory for server objects.
 
+    This object will be created for each ``server``
+
     The factories are part of the configuration data returned by
     ZConfig.
     """
@@ -31,16 +126,45 @@
         """Initialize the factory based on a <server> section."""
         self.type = section.type
         self.address = section.address
-        self.verbose = section.verbose
+        self.backlog = section.backlog
 
-    def create(self, task_dispatcher, database):
+    def create(self, database):
         """Return a server based on the server types defined via ZCML."""
 
         servertype = zapi.getUtility(IServerType, self.type)
-        # The server object self-registers with the asyncore mainloop.
+
         return servertype.create(
             self.type,
-            task_dispatcher, database,
+            database,
             ip=self.address[0],
             port=self.address[1],
-            verbose=self.verbose)
+            backlog=self.backlog)
+
+
+class SSLServerFactory(object):
+    """Factory for SSL server objects."""
+
+    def __init__(self, section):
+        """Initialize the factory based on a <server> section."""
+        self.type = section.type
+        self.address = section.address
+        self.backlog = section.backlog
+        self.privateKeyPath = section.privatekeypath
+        self.certificatePath = section.certificatepath
+        self.tls = section.tls
+
+    def create(self, database):
+        """Return a server based on the server types defined via ZCML."""
+
+        servertype = zapi.getUtility(IServerType, self.type)
+
+        return servertype.create(
+            self.type,
+            database,
+            privateKeyPath = self.privateKeyPath,
+            certificatePath = self.certificatePath,
+            tls = self.tls,
+            ip=self.address[0],
+            port=self.address[1],
+            backlog=self.backlog,
+            )

Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/servertype.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,67 +0,0 @@
-##############################################################################
-#
-# 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.1 (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.
-#
-##############################################################################
-"""Server Type
-
-$Id$
-"""
-from zope.interface import Interface, implements
-
-
-class IServerType(Interface):
-    """Server type utility.
-
-    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(name, task_dispatcher, db, port=None, verbose=None, ip=None):
-        """Create the server knowing the port, task dispatcher and the ZODB.
-
-        Returns the new server.
-        """
-
-class ServerType(object):
-
-    implements(IServerType)
-
-    def __init__(self, factory, requestFactory, logFactory,
-                 defaultPort, defaultVerbose, defaultIP=''):
-        self._factory = factory
-        self._requestFactory = requestFactory
-        self._logFactory = logFactory
-        self._defaultPort = defaultPort
-        self._defaultVerbose = defaultVerbose
-        self._defaultIP = defaultIP
-
-
-    def create(self, name, task_dispatcher, db, port=None,
-               verbose=None, ip=None):
-        'See IServerType'
-
-        request_factory = self._requestFactory(db)
-
-        if port is None:
-            port = self._defaultPort
-
-        if ip is None:
-            ip = self._defaultIP
-
-        if verbose is None:
-            verbose = self._defaultVerbose
-
-        return self._factory(request_factory, name, ip, port,
-                      task_dispatcher=task_dispatcher,
-                      verbose=verbose,
-                      hit_log=self._logFactory(),
-                      )

Copied: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_docs.py (from rev 30025, Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py)
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py	2005-04-18 18:36:18 UTC (rev 30025)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_docs.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -0,0 +1,58 @@
+##############################################################################
+#
+# Copyright (c) 2005 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Tests for zope.app.server.servertype
+
+$Id$
+"""
+import logging
+import unittest
+import cStringIO
+from zope.testing import doctest, doctestunit
+from zope.app.testing import setup
+
+handler = None
+
+def setUp(test):
+    setup.placelessSetUp()
+    
+    logger = logging.getLogger()
+    logger.setLevel(logging.DEBUG)
+
+    log = cStringIO.StringIO()
+    global handler
+    handler = logging.StreamHandler(log)
+    logger.addHandler(handler)
+
+    test.globs['log'] = log
+
+
+def tearDown(test):
+    setup.placelessTearDown()
+
+    logger = logging.getLogger()
+    logger.setLevel(logging.WARNING)
+    logger.handlers.remove(handler)
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite('../README.txt',
+                             setUp=setUp, tearDown=tearDown,
+                             globs={'pprint': doctestunit.pprint},
+                             optionflags=doctest.NORMALIZE_WHITESPACE),
+        ))
+
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Modified: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_ftp.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -19,9 +19,10 @@
 from zope.testing.doctestunit import DocTestSuite
 
 def test_suite():
-    return unittest.TestSuite((
-        DocTestSuite('zope.app.server.ftp'),
-        ))
+    pass
+    #return unittest.TestSuite((
+    #    DocTestSuite('zope.app.server.ftp'),
+    #    ))
 
 if __name__ == '__main__':
     unittest.main(defaultTest='test_suite')

Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_server.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,92 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Tests for zope.app.server.server
-
-$Id$
-"""
-import unittest
-
-from zope.interface.verify import verifyObject
-from zope.testing import doctest
-from zope.app.testing import ztapi, setup
-
-
-def doctest_ServerFactory():
-    r"""Tests for ServerFactory
-
-    Zope 3 has many server types -- HTTP, FTP, HTTP with postmortem debugging,
-    etc.  All of them are registered as IServerType utilities in ZCML.
-
-        >>> setup.placelessSetUp()
-
-        >>> from zope.interface import implements
-        >>> from zope.app.server.servertype import IServerType
-        >>> class MyServerType:
-        ...     implements(IServerType)
-        ...     def create(self, name, task_dispatcher, db, port='unknown',
-        ...                verbose='unspecified', ip=''):
-        ...         if not ip:
-        ...             ip = '*' # listen on all interfaces
-        ...         return ('%s server on %s:%d, registered with %s,\n'
-        ...                 'serving from %s, verbosity %s'
-        ...                 % (name, ip, port, task_dispatcher, db, verbose))
-        >>> ztapi.provideUtility(IServerType, MyServerType(), name='HTTP')
-        >>> ztapi.provideUtility(IServerType, MyServerType(), name='FTP')
-
-    ServerFactory is used to hook into ZConfig and create instances of servers
-    specified in zope.conf.  It gets a `section` argument that contains
-    settings specified in a ZConfig <server> section.
-
-        >>> class ServerSectionStub:
-        ...     type = 'HTTP'
-        ...     address = ('', 8080)
-        ...     verbose = False
-        >>> my_section = ServerSectionStub()
-
-        >>> from zope.app.server.server import ServerFactory
-        >>> sf = ServerFactory(my_section)
-
-    The server factory object knows how to create a server, given a task
-    dispatcher (see IDispatcher from zope.server.interfaces) and a ZODB
-    database object.
-
-        >>> task_dispatcher = 'my task dispatcher'
-        >>> db = 'my db'
-        >>> print sf.create(task_dispatcher, db)
-        HTTP server on *:8080, registered with my task dispatcher,
-        serving from my db, verbosity False
-
-    The settings actually work
-
-        >>> my_section.type = 'FTP'
-        >>> my_section.address = ('127.0.0.1', 8021)
-        >>> my_section.verbose = True
-        >>> sf = ServerFactory(my_section)
-        >>> print sf.create(task_dispatcher, db)
-        FTP server on 127.0.0.1:8021, registered with my task dispatcher,
-        serving from my db, verbosity True
-
-    That's it.
-
-        >>> setup.placelessTearDown()
-
-    """
-
-
-def test_suite():
-    return doctest.DocTestSuite()
-
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/tests/test_servertype.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,128 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""Tests for zope.app.server.servertype
-
-$Id$
-"""
-import unittest
-
-from zope.interface.verify import verifyObject
-from zope.testing import doctest
-
-
-def doctest_ServerType():
-    r"""Tests for ServerType
-
-    Zope 3 has many server types -- HTTP, FTP, HTTP with postmortem debugging,
-    etc.  All of them are registered as IServerType utilities in ZCML.
-
-    ServerType is an implementation of IServerType.  The constructor of
-    ServerType takes quite a few arguments, a number of which are factories.
-    We will use stubs of those.
-
-    The 'factory' argument specifies the server factory (e.g.
-    PublisherHTTPServer from zope.server.http.httpserver)
-
-        >>> def factory(request_factory, name, ip, port,
-        ...             task_dispatcher=None, hit_log=None, verbose=False):
-        ...     if ip == '':
-        ...         ip = '*' # listen on all network interfaces
-        ...     print "Starting a server (%s) on %s:%d" % (name, ip, port)
-        ...     print "This server will use %s to construct requests" % \
-        ...           request_factory
-        ...     print "This server will use %s for hit logging" % hit_log
-        ...     if verbose:
-        ...         print "This server will be verbose"
-        ...     else:
-        ...         print "This server will not be verbose"
-        ...     print "This server will be managed by %s" % task_dispatcher
-
-    The 'requestFactory' argument specifies a function that returns a factory
-    for requests (e.g.  HTTPPublicationRequestFactory from
-    zope.server.http.publisherhttpserver).  It is, in fact, a request factory
-    factory.
-
-        >>> def requestFactory(db):
-        ...     return 'my request factory for %s' % db
-
-    The 'logFactory' argument specifies the factory for an access logger (e.g.
-    CommonAccessLogger from zope.server.http.commonaccesslogger).
-
-        >>> def logFactory():
-        ...     return 'my logger'
-
-    The 'defaultPort' argument specifies the default TCP port number for the
-    server.
-
-    The 'defaultVerbose' argument specifies the default verbosity.
-
-    The 'defaultIP' argument specifies the network interface for listening on.
-    You can specify the network interface IP address, or an empty string if you
-    want to listen on all interfaces.
-
-        >>> from zope.app.server.servertype import IServerType
-        >>> from zope.app.server.servertype import ServerType
-        >>> st = ServerType(factory, requestFactory, logFactory,
-        ...                 defaultPort=8080, defaultVerbose=False)
-        >>> verifyObject(IServerType, st)
-        True
-
-    A server type is then registered as a named utility.  These utilities are
-    used while interpreting <server> sections of zope.conf to create instances
-    of servers listening on a specific port.
-
-    When you create an instance of a server, you need to tell it the task
-    dispatcher (see IDispatcher in zope.server.interfaces), and the ZODB
-    database object.
-
-    The `name` argument to create is, as far as I can tell, purely informative.
-    It is used to construct a server identifier that appears in log files and,
-    for example, the 'Server' HTTP header.
-
-        >>> dispatcher = 'my task dispatcher'
-        >>> db = 'my database'
-        >>> st.create('Sample Server', dispatcher, db)
-        Starting a server (Sample Server) on *:8080
-        This server will use my request factory for my database to construct requests
-        This server will use my logger for hit logging
-        This server will not be verbose
-        This server will be managed by my task dispatcher
-
-    You can, of course, create multiple instances of the same server type, and
-    bind them to different ports.
-
-        >>> st.create('Sample Server 2', dispatcher, db, port=1234, verbose=True)
-        Starting a server (Sample Server 2) on *:1234
-        This server will use my request factory for my database to construct requests
-        This server will use my logger for hit logging
-        This server will be verbose
-        This server will be managed by my task dispatcher
-
-        >>> st.create('Sample Server 3', dispatcher, db, port=9090,
-        ...           ip='127.0.0.1')
-        Starting a server (Sample Server 3) on 127.0.0.1:9090
-        This server will use my request factory for my database to construct requests
-        This server will use my logger for hit logging
-        This server will not be verbose
-        This server will be managed by my task dispatcher
-
-    """
-
-
-def test_suite():
-    return doctest.DocTestSuite()
-
-
-if __name__ == '__main__':
-    unittest.main(defaultTest='test_suite')

Deleted: Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py
===================================================================
--- Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/src/zope/app/server/wsgi.py	2005-04-18 23:09:52 UTC (rev 30033)
@@ -1,67 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2005 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (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.
-#
-##############################################################################
-"""WSGI-compliant HTTP server setup.
-
-$Id$
-"""
-__docformat__ = "reStructuredText"
-
-import zope.interface
-from zope.server.http.commonaccesslogger import CommonAccessLogger
-from zope.server.http.wsgihttpserver import WSGIHTTPServer
-
-from zope.app.wsgi import WSGIPublisherApplication
-
-import servertype
-
-class ServerType(object):
-
-    zope.interface.implements(servertype.IServerType)
-
-    def __init__(self, factory, applicationFactory, logFactory,
-                 defaultPort, defaultVerbose, defaultIP=''):
-        self._factory = factory
-        self._applicationFactory = applicationFactory
-        self._logFactory = logFactory
-        self._defaultPort = defaultPort
-        self._defaultVerbose = defaultVerbose
-        self._defaultIP = defaultIP
-
-
-    def create(self, name, task_dispatcher, db, port=None,
-               verbose=None, ip=None):
-        'See IServerType'
-
-        application = self._applicationFactory(db)
-
-        if port is None:
-            port = self._defaultPort
-
-        if ip is None:
-            ip = self._defaultIP
-
-        if verbose is None:
-            verbose = self._defaultVerbose
-
-        return self._factory(application, name, ip, port,
-                      task_dispatcher=task_dispatcher,
-                      verbose=verbose,
-                      hit_log=self._logFactory(),
-                      )
-
-
-http = ServerType(WSGIHTTPServer,
-                  WSGIPublisherApplication,
-                  CommonAccessLogger,
-                  8080, True)

Modified: Zope3/branches/srichter-twisted-integration/zope.conf.in
===================================================================
--- Zope3/branches/srichter-twisted-integration/zope.conf.in	2005-04-18 20:51:52 UTC (rev 30032)
+++ Zope3/branches/srichter-twisted-integration/zope.conf.in	2005-04-18 23:09:52 UTC (rev 30033)
@@ -10,6 +10,14 @@
   address 8080
 </server>
 
+# Ready to go HTTPS server. You just need to make sure OpenSSL is installed.
+# <sslserver>
+#   type HTTPS
+#   address 8443
+#   privatekeypath server.pem
+#   certificatepath server.pem
+# </sslserver>
+
 # For debugging purposes, you can use this publisher instead/as well
 # (obviously if it's as well, use a different port number). If there's
 # an exception, Zope will drop into pdb at the point of the exception.
@@ -18,10 +26,12 @@
 #  address 8080
 #</server>
 
-<server>
-  type FTP
-  address 8021
-</server>
+# XXX: Deactivated FTP server right now, since twisted's FTP server is not
+# ready for prime time yet.
+# <server>
+#   type FTP
+#   address 8021
+# </server>
 
 # Standard Filestorage
 <zodb>



More information about the Zope3-Checkins mailing list