[Zope3-checkins] CVS: Zope3/src/zope/server/linereceiver - __init__.py:1.1.2.1 linecommandparser.py:1.1.2.1 lineserverchannel.py:1.1.2.1 linetask.py:1.1.2.1

Jim Fulton jim@zope.com
Mon, 23 Dec 2002 14:33:24 -0500


Update of /cvs-repository/Zope3/src/zope/server/linereceiver
In directory cvs.zope.org:/tmp/cvs-serv19908/zope/server/linereceiver

Added Files:
      Tag: NameGeddon-branch
	__init__.py linecommandparser.py lineserverchannel.py 
	linetask.py 
Log Message:
Initial renaming before debugging

=== Added File Zope3/src/zope/server/linereceiver/__init__.py ===
#
# This file is necessary to make this directory a package.


=== Added File Zope3/src/zope/server/linereceiver/linecommandparser.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: linecommandparser.py,v 1.1.2.1 2002/12/23 19:33:23 jim Exp $
"""

from zope.server.interfaces.interfaces import IStreamConsumer


class LineCommandParser:
    """Line Command parser. Arguments are left alone for now."""

    __implements__ = IStreamConsumer

    # See Zope.Server.IStreamConsumer.IStreamConsumer
    completed = 0
    inbuf = ''
    cmd = ''
    args = ''
    empty = 0

    max_line_length = 1024  # Not a hard limit


    def __init__(self, adj):
        """
        adj is an Adjustments object.
        """
        self.adj = adj


    ############################################################
    # Implementation methods for interface
    # Zope.Server.IStreamConsumer

    def received(self, data):
        'See Zope.Server.IStreamConsumer.IStreamConsumer'
        if self.completed:
            return 0  # Can't consume any more.
        pos = data.find('\n')
        datalen = len(data)
        if pos < 0:
            self.inbuf = self.inbuf + data
            if len(self.inbuf) > self.max_line_length:
                # Don't accept any more.
                self.completed = 1
            return datalen
        else:
            # Line finished.
            s = data[:pos + 1]
            self.inbuf = self.inbuf + s
            self.completed = 1
            line = self.inbuf.strip()
            self.parseLine(line)
            return len(s)

    #
    ############################################################


    def parseLine(self, line):
        parts = line.split(' ', 1)
        if len(parts) == 2:
            self.cmd, self.args = parts
        else:
            self.cmd = parts[0]


=== Added File Zope3/src/zope/server/linereceiver/lineserverchannel.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: lineserverchannel.py,v 1.1.2.1 2002/12/23 19:33:23 jim Exp $
"""

import os
import sys

from zope.server.serverchannelbase import ServerChannelBase
from zope.server.linereceiver.linecommandparser import LineCommandParser
from zope.server.linereceiver.linetask import LineTask


DEBUG = os.environ.get('ZOPE_SERVER_DEBUG')


class LineServerChannel(ServerChannelBase):
    """The Line Server Channel represents a connection to a particular
       client. We can therefore store information here."""

    __implements__ = ServerChannelBase.__implements__

    # Wrapper class that is used to execute a command in a different thread
    task_class = LineTask

    # Class that is being initialized to parse the input
    parser_class = LineCommandParser

    # List of commands that are always available
    special_commands = ('cmd_quit')

    # Commands that are run in a separate thread
    thread_commands = ()

    # Define the authentication status of the channel. Note that only the
    # "special commands" can be executed without having authenticated.
    authenticated = 0

    # Define the reply code for non-authenticated responses
    not_auth_reply = 'LOGIN_REQUIRED'

    # Define the reply code for an unrecognized command
    unknown_reply = 'CMD_UNKNOWN'

    # Define the error message that occurs, when the reply code was not found.
    reply_error = '500 Unknown Reply Code: %s.'

    # Define the status messages
    status_messages = {
        'CMD_UNKNOWN'      : "500 '%s': command not understood.",
        'INTERNAL_ERROR'   : "500 Internal error: %s",
        'LOGIN_REQUIRED'   : '530 Please log in with USER and PASS',
        }


    def process_request(self, command):
        """Processes a command.

        Some commands use an alternate thread.
        """
        assert isinstance(command, LineCommandParser)
        cmd = command.cmd
        method = 'cmd_' + cmd.lower()
        if ( not self.authenticated and method not in self.special_commands):
            # The user is not logged in, therefore don't allow anything
            self.reply(self.not_auth_reply)

        elif method in self.thread_commands:
            # Process in another thread.
            return self.task_class(self, command, method)

        elif hasattr(self, method):
            try:
                getattr(self, method)(command.args)
            except:
                self.exception()
        else:
            self.reply(self.unknown_reply, cmd.upper())
        return None


    def reply(self, code, args=(), flush=1):
        """ """
        try:
            msg = self.status_messages[code] %args
        except:
            msg = self.reply_error %code

        self.write('%s\r\n' %msg)

        if flush:
            self.flush(0)

        # XXX: Some logging should go on here.


    def exception(self):
        if DEBUG:
            import traceback
            traceback.print_exc()
        t, v = sys.exc_info()[:2]
        try:
            info = '%s: %s' % (getattr(t, '__name__', t), v)
        except:
            info = str(t)
        self.reply('INTERNAL_ERROR', info)
        self.handle_error()


=== Added File Zope3/src/zope/server/linereceiver/linetask.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: linetask.py,v 1.1.2.1 2002/12/23 19:33:23 jim Exp $
"""

import socket
import time
from zope.server.interfaces.interfaces import ITask


class LineTask:
    """This is a generic task that can be used with command line
       protocols to handle commands in a separate thread.
    """

    __implements__ = ITask


    def __init__(self, channel, command, m_name):
        self.channel = channel
        self.m_name = m_name
        self.args = command.args

        self.close_on_finish = 0


    ############################################################
    # Implementation methods for interface
    # Zope.Server.ITask

    def service(self):
        """Called to execute the task.
        """
        try:
            try:
                self.start()
                getattr(self.channel, self.m_name)(self.args)
                self.finish()
            except socket.error:
                self.close_on_finish = 1
                if self.channel.adj.log_socket_errors:
                    raise
            except:
                self.channel.exception()
        finally:
            self.channel.end_task(self.close_on_finish)


    def cancel(self):
        'See Zope.Server.ITask.ITask'
        self.channel.close_when_done()


    def defer(self):
        'See Zope.Server.ITask.ITask'
        pass

    #
    ############################################################

    def start(self):
        now = time.time()
        self.start_time = now


    def finish(self):
        hit_log = self.channel.server.hit_log
        if hit_log is not None:
            hit_log.log(self)