[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/ServiceManager - IComponentManager.py:1.1 IPackage.py:1.1 IPackages.py:1.1 IServiceDirective.py:1.1 Package.py:1.1 Packages.py:1.1 ServiceDirective.py:1.1 IBindingAware.py:1.3 IServiceManager.py:1.4 ServiceManager.py:1.4 configure.zcml:1.5

Jim Fulton jim@zope.com
Thu, 11 Jul 2002 14:22:03 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Services/ServiceManager
In directory cvs.zope.org:/tmp/cvs-serv7355/lib/python/Zope/App/OFS/Services/ServiceManager

Modified Files:
	IBindingAware.py IServiceManager.py ServiceManager.py 
	configure.zcml 
Added Files:
	IComponentManager.py IPackage.py IPackages.py 
	IServiceDirective.py Package.py Packages.py 
	ServiceDirective.py 
Log Message:

Reimplemented service managers to be package based. Service managers
are no longer containers. They have a packages subobject (not a
packages service) that contains packages. TTW components are created
in packages. To register a component, create the appropriate component
directive objects (these should be called configuration objects).

This should be viewed as a prototype to illustrate the idea of
packages. Lots of things can change (especially UI) and many things
aren't done (e.g. visiting created directives).

In the course of this, I fixed a bunch of bugs and problems in
traversal machinery. 

I also renamed Zope.ComponentArchitecture.IServiceManager back to
IServiceService, since this interface doesn't actually specify any
management.  



=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IComponentManager.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: IComponentManager.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""
from Interface import Interface

class IComponentManager(Interface):
    

    def queryComponent(type=None, filter=None, all=0):
        """Return all components that match the given type and filter

        The objects are returned a sequence of mapping objects with keys:

        path -- The component path

        component -- The component

        all -- A flag indicating whether all component managers in
               this place should be queried, or just the local one.
        
        """
    


=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IPackage.py ===
##############################################################################
#
# 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.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: IPackage.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""

from Zope.App.OFS.Container.IContainer import IContainer 

class IPackage(IContainer):
    """Component and component configuration containers.
    """
    



=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IPackages.py ===
##############################################################################
#
# 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.
# 
##############################################################################

from Zope.App.OFS.Container.IContainer import IContainer
from Zope.App.OFS.Services.ServiceManager.IComponentManager import IComponentManager

class IPackages(IContainer, IComponentManager):
    """Packages objects contain database packages

    They support simple containment as well as package query and lookup.
    """

doc = IPackages.__doc__ + """
$Id: IPackages.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""
    


=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceDirective.py ===
##############################################################################
#
# 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.
# 
##############################################################################
"""
$Id: IServiceDirective.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""

from Interface import Interface
from Interface.Attribute import Attribute

class IServiceDirective(Interface):
    """Service Configuration Directives
    """

    service_type = Attribute("The service type id")
    component_path = Attribute("The physical path to the component")

    def getService(service_manager):
        """Return the service component named in the directive.
        """

__doc__ = IServiceDirective.__doc__ + __doc__



=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Package.py ===
##############################################################################
#
# 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.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: Package.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""
__metaclass__ = type

from Zope.App.OFS.Container.BTreeContainer import BTreeContainer

from IPackage import IPackage


class Package(BTreeContainer):
    __implements__ = IPackage

    
    


=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/Packages.py ===
##############################################################################
#
# 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.
# 
##############################################################################
"""XXX short summary goes here.

XXX longer description goes here.

$Id: Packages.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""
__metaclass__ = type


from Zope.App.OFS.Container.BTreeContainer import BTreeContainer
from Zope.ContextWrapper import ContextMethod
from Zope.Proxy.ContextWrapper import ContextWrapper
from Zope.App.Traversing import getPhysicalPathString

from IPackages import IPackages
from IPackage import IPackage

class Packages(BTreeContainer):
    __implements__ = IPackages

    def queryComponent(self, type=None, filter=None, all=0):

        local = []
        path = getPhysicalPathString(self)
        for package_name in self:
            package = ContextWrapper(self[package_name], self,
                                     name=package_name)
            for name in package:
                component = package[name]
                if type is not None and not type.isImplementedBy(component):
                    continue
                if filter is not None and not filter(component):
                    continue
                local.append({'path': "%s/%s/%s" % (path, package_name, name),
                              'component': ContextWrapper(component, package,
                                                          name=name),
                              })

        if all:
            next_service_manager = getNextServiceManager(self)
            if IComponentManager.isImplementedBy(next_service_manager):
                more = next_service_manager.queryComponent(type, filter, all)

            local += list(all)

        return local

    queryComponent = ContextMethod(queryComponent)

    def setObject(self, name, object):
        if not IPackage.isImplementedBy(object):
            raise TypeError("Can only add packages")
        return super(Packages, self).setObject(name, object)
    



=== Added File Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceDirective.py ===
##############################################################################
#
# 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.
# 
##############################################################################
"""
$Id: ServiceDirective.py,v 1.1 2002/07/11 18:21:32 jim Exp $
"""

__metaclass__ = type

from Persistence import Persistent
from Zope.Security.Checker import CheckerPublic, InterfaceChecker
from Zope.Security.Proxy import Proxy
from Zope.App.Traversing import traverse
from IServiceDirective import IServiceDirective

class ServiceDirective(Persistent):
    __doc__ = IServiceDirective.__doc__
    
    __implements__ = IServiceDirective

    def __init__(self, service_type, component_path, permission=None):
        self.service_type = service_type
        self.component_path = component_path
        if permission == 'Zope.Public':
            permission = CheckerPublic
            
        self.permission = permission

    def __repr__(self):
        return "service(%s, %s)" % (self.service_type, self.component_path)

    ############################################################
    # Implementation methods for interface
    # Zope.App.OFS.Services.ServiceManager.IServiceDirective.

    def getService(self, service_manager):
        
        service = getattr(self, '_v_service', None)
        if service is None:
            service = traverse(service_manager, self.component_path)
            if self.permission:
                if type(service) is Proxy:
                    service = removeSecurityProxy(service)

                interface = service_manager.getInterfaceFor(self.service_type)

                checker = InterfaceChecker(interface, self.permission)

                service = Proxy(service, checker)

            
            self._v_service = service


        return service

    getService.__doc__ = IServiceDirective['getService'].__doc__

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

    
__doc__ = ServiceDirective.__doc__  + __doc__

            


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IBindingAware.py 1.2 => 1.3 ===
 class IBindingAware(Interface):
     
     def bound(name):
-        """Called when an immediately-containing service manager binds this object to
-        perform the named service"""
+        """
+
+        Called when an immediately-containing service manager binds
+        this object to perform the named service.
+
+        """
     
     def unbound(name):
-        """Called when an immediately-containing service manager unbinds this object
-        from performing the named service"""
\ No newline at end of file
+        """
+
+        Called when an immediately-containing service manager unbinds
+        this object from performing the named service.
+
+        """


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceManager.py 1.3 => 1.4 ===
 
 $Id$
 """
-from Interface import Interface
-from Zope.ComponentArchitecture.IServiceManager import IServiceManager as \
-  IGlobalServiceManager
-  # XXX fix once this package is changed to LocalServiceManager
-from Zope.App.OFS.Container.IContainer import IContainer
+from Zope.ComponentArchitecture.IServiceService import IServiceService
 
-class IServiceManager(IContainer, IGlobalServiceManager):
+from IComponentManager import IComponentManager
+
+from Interface.Attribute import Attribute
+
+class IServiceManager(IServiceService, IComponentManager):
     """Service Managers act as containers for Services.
     
     If a Service Manager is asked for a service, it checks for those it
@@ -31,23 +31,53 @@
     services.
     """
 
-    def bindService(serviceName, serviceComponentName):
+    Packages = Attribute("""Package container""")
+    
+
+    def bindService(service_directive):
         """Provide a service implementation.
 
         If the named object implements IBindingAware, the wrapped object is
         notified as per that interface.
         """
 
-    def unbindService(serviceName):
+    def addService(service_directive):
+        """Add a registered service, but displace another active component
+
+        Register a service component, but don't make it active of
+        there is already a registered component providing the service.
+
+        """
+
+    def unbindService(service_directive):
         """No longer provide a service implementation.
 
         If the named object implements IBindingAware, the wrapped object is
         notified as per that interface.
         """
 
+    def disableService(service_type):
+        """Make the service type inactive in this service manager.
+
+        This doesn't unbind any services, but makes them all inactive.
+        """
+
+    def enableService(service_type, index):
+        """Make the service type inactive in this service manager.
+
+        This doesn't unbind any services, but makes them all inactive.
+        """
+
     def getBoundService(name):
         """Retrieve a bound service implementation.
 
         Get the component currently bound to the named Service in this
         ServiceService.   Does not search context.
         """
+
+    def getDirectives(service_type):
+        """Get the directives registered for a service
+        """
+
+    def getBoundServiceTypes():
+        """Get a sequence of the bound service types"""


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceManager.py 1.3 => 1.4 ===
 
 $Id$
 """
+from Persistence import Persistent
+
 from Zope.Exceptions import NotFoundError, ZopeError
 
 from Zope.ComponentArchitecture.IServiceManagerContainer \
@@ -25,6 +27,7 @@
 from Zope.ComponentArchitecture.GlobalServiceManager import InvalidService
 from Zope.ComponentArchitecture.Exceptions import ComponentLookupError
 
+from Zope.App.OFS.Container.IContainer import ISimpleReadContainer
 from Zope.App.OFS.Content.Folder.Folder import Folder
 from Zope.ContextWrapper import ContextMethod
 from Zope.Proxy.ContextWrapper import ContextWrapper
@@ -32,131 +35,239 @@
 from Zope.Proxy.ProxyIntrospection import removeAllProxies
 
 from IBindingAware import IBindingAware
+from Packages import Packages
+from Package import Package
 from IServiceManager import IServiceManager
 
+class ServiceManager(Persistent):
 
-class ServiceManager(BTreeContainer):
-
-    __implements__ = IServiceManager
+    __implements__ = IServiceManager, ISimpleReadContainer
 
     def __init__(self):
+
         self.__bindings = {}
-        super(ServiceManager, self).__init__()
+        # Bindings is of the form:
+        #
+        # {service_type -> [directives]}
+        #
+        # Where the first directive is always the active directive.
+
+        self.Packages = Packages()
+        self.Packages.setObject('default', Package())
 
 
-    def getServiceDefinitions(wrapped_self):
-        clean_self=removeAllProxies(wrapped_self)
-        """ see IServiceManager Interface """
+    def getServiceDefinitions(self):
+        "See Zope.ComponentArchitecture.IServiceService.IServiceService"
+
         # Get the services defined here and above us, if any (as held
         # in a ServiceInterfaceService, presumably)
-        sm=getNextServiceManager(wrapped_self)
+        sm = getNextServiceManager(self)
         if sm is not None:
-            serviceDefs=sm.getServiceDefinitions()
-        else: serviceDefs={}
-        # since there is no way to define an interface TTW right now,
-        # worrying about this further is pointless--it probably will be
-        # an interface service evetually though...so this would be useful then:
-
-        serviceInterfaceServ= \
-             clean_self.__bindings.get('ServiceInterfaceService')
-        if serviceInterfaceServ:
-            serviceDefs.update(dict(
-               removeAllProxies(
-                   wrapped_self[serviceInterfaceServ].items()
-                   )
-               ))
+            serviceDefs = sm.getServiceDefinitions()
+        else: serviceDefs = {}
+
         return serviceDefs
 
-    getServiceDefinitions=ContextMethod(getServiceDefinitions)
+    getServiceDefinitions = ContextMethod(getServiceDefinitions)
 
     def queryService(self, name, default=None):
+        "See Zope.ComponentArchitecture.IServiceService.IServiceService"
         try:
             return self.getService(name)
         except ComponentLookupError:
             return default
 
-    queryService=ContextMethod(queryService)
+    queryService = ContextMethod(queryService)
 
-    def getService(wrapped_self, name):
-        """ see IServiceManager Interface"""
-        clean_self=removeAllProxies(wrapped_self)
-
-        service = clean_self.__bindings.get(name)
+    def getService(self, name):
+        "See Zope.ComponentArchitecture.IServiceService.IServiceService"
+        
+        service = self.__bindings.get(name)
 
         if service:
-            return ContextWrapper(wrapped_self[service],
-                                  wrapped_self, name=service) # we want
-        # to traverse by component name, not service name
+            service = service[0] # Get the active service directive
+            if service is not None: # not disabled
+                service = service.getService(self) # get the service
+                return service
 
-        return getNextService(wrapped_self, name)
+        return getNextService(self, name)
+
+    getService = ContextMethod(getService)
 
-    getService=ContextMethod(getService)
 
     def getBoundService(self, name):
-        """ see IServiceManager Interface"""
+        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
+
+        service = self.__bindings.get(name)
+        if service:
+            service = service[0] # Get the active service directive
+            service = service.getService(self) # get the service
+            return service
+
+        return None
+
+    def getInterfaceFor(self, service_type):
+        "See Zope.ComponentArchitecture.IServiceService.IServiceService"
+        for type, interface in self.getServiceDefinitions():
+            if type == service_type:
+                return interface
+
+        raise NameError(service_type)
+
+    getInterfaceFor = ContextMethod(getInterfaceFor)
+
+    def disableService(self, service_type):
+        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
+        directives = self.__bindings.get(service_type)
+        if directives and directives[0] is not None:
+            directives.insert(0, None)            
+
+    def enableService(self, service_type, index):
+        "See Zope.App.OFS.Services.ServiceManager.IServiceManager."
+        self._disableFirstBeforeEnable(service_type)
+
+        directives = self.__bindings.get(service_type)
+        directive = directives[index]
+        del directives[index]
+        directives.insert(0, directive)
+
+
+        self._p_changed = 1
+                
+        service = directive.getService(self)
+        if IBindingAware.isImplementedBy(service):
+            service.bound(service_type)
+
+
+    def _disableFirstBeforeEnable(self, service_type):
+        # Disable the first (active) service or remove the
+        # disabled marker prior to enabling a service.
+        directives = self.__bindings.get(service_type)
+
+        if directives:
+            if directives[0] is None:
+                # remove deactivation marker
+                del directives[0]
+            elif IBindingAware.isImplementedBy(directives[0]):
+                # unbind old service, if necessary
+                old_service = directives[0].getService(self)
+                old_service.unbound(service_type)
+        
+
+    def bindService(self, directive):
+        "See "
+        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
+        service = directive.getService(self)
+        service_type = directive.service_type
+
+        interface = self.getInterfaceFor(service_type)
+        
+        if not interface.isImplementedBy(service):
+            raise InvalidService(service_type, directive, interface)
 
-        return self.__bindings.get(name)
+        self._disableFirstBeforeEnable(service_type)
 
-    def bindService(wrapped_self, serviceName, serviceComponentName):
-        """ see IServiceManager Interface"""
-        clean_self=removeAllProxies(wrapped_self)
+        bindings = self.__bindings
+        if service_type not in bindings:
+            bindings[service_type] = [directive]
+        else:
+            directives = bindings[service_type]
+            directives.insert(0, directive)
+
+        self._p_changed = 1
+                
+        if IBindingAware.isImplementedBy(service):
+            service.bound(service_type)
+
+    bindService = ContextMethod(bindService)
+
+    def addService(self, directive):
+        "See "
+        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
+        service = directive.getService(self)
+        service_type = directive.service_type
 
-        # This could raise a KeyError if we don't have this component
-        clean_serviceComponent = wrapped_self[serviceComponentName]
-        wrapped_serviceComponent=ContextWrapper(
-            clean_serviceComponent,
-            wrapped_self,
-            name=serviceComponentName)
+        interface = self.getInterfaceFor(service_type)
+        
+        if not interface.isImplementedBy(service):
+            raise InvalidService(service_type, directive, interface)
 
-        for name,interface in wrapped_self.getServiceDefinitions():
-            if name == serviceName:
-                if not interface.isImplementedBy(clean_serviceComponent):
-                    raise InvalidService(serviceName,
-                                         serviceComponentName,
-                                         interface)
-            break
+        bindings = self.__bindings
+        if service_type not in bindings:
+            bindings[service_type] = []
+        bindings[service_type].append(directive)
+
+        self._p_changed = 1
+                
+        if len(bindings) == 1 and IBindingAware.isImplementedBy(service):
+            service.bound(service_type)
 
-        # Services are added to the Manager through the Folder interface
-        # self.setObject(name, component)
+    addService = ContextMethod(addService)
+    
+    def unbindService(self, directive):
+        "See Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
+        self = removeAllProxies(self)
+        service = directive.getService(self)        
+        service_type = directive.service_type
+
+        directives = self.__bindings[service_type]
+        if directive not in directives:
+            raise KeyError(directive)
         
-        if IBindingAware.isImplementedBy(clean_serviceComponent):
-            wrapped_serviceComponent.bound(serviceName)
+        if IBindingAware.isImplementedBy(service):
+            service.unbound(service_type)
 
-        clean_self.__bindings[serviceName] = serviceComponentName
 
-        # trigger persistence
-        clean_self.__bindings = clean_self.__bindings
+        self.__bindings[service_type] = [d for d in directives
+                                         if d != directive]
 
-    bindService=ContextMethod(bindService) # needed because of call to
-    # getServiceDefinitions, as well as IBindingAware stuff
+        self._p_changed = 1
+    
+    unbindService = ContextMethod(unbindService)
 
-    def unbindService(wrapped_self, serviceName):
-        """ see IServiceManager Interface """
-        clean_self=removeAllProxies(wrapped_self)
-        serviceComponentName=clean_self.__bindings[serviceName]
-        
-        clean_serviceComponent = wrapped_self[serviceComponentName]
-        wrapped_serviceComponent=ContextWrapper(
-            clean_serviceComponent,
-            wrapped_self,
-            name=serviceComponentName)
+    def getDirectives(self, service_type):
+        "See "
+        "Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
+        return self.__bindings[service_type]
+
+    def getBoundServiceTypes(self):
+        "See Zope.App.OFS.Services.ServiceManager.IServiceManager.IServiceManager"
+        return  self.__bindings.keys()
         
-        if IBindingAware.isImplementedBy(clean_serviceComponent):
-            wrapped_serviceComponent.unbound(serviceName)
 
-        del clean_self.__bindings[serviceName]
+    ############################################################
+    # Implementation methods for interface
+    # Zope.App.OFS.Services.ServiceManager.IComponentManager.
 
-        # trigger persistence
-        clean_self.__bindings = clean_self.__bindings
-    
-    unbindService=ContextMethod(unbindService)
+    def queryComponent(self, type=None, filter=None, all=0):
+        Packages = ContextWrapper(self.Packages, self, name='Packages')
+        return Packages.queryComponent(type, filter, all)
+
+    queryComponent = ContextMethod(queryComponent)
+
+    #
+    ############################################################
+
+
+    def __getitem__(self, key):
+        "See Interface.Common.Mapping.IReadMapping"
+
+        result = self.get(key)
+        if result is None:
+            raise KeyError(key)
+
+        return result
+
+    def get(self, key, default=None):
+        "See Interface.Common.Mapping.IReadMapping"
+
+        if key == 'Packages':
+            return self.Packages
+
+        return self.queryService(key, default)
+
+    def __contains__(self, key):
+        "See Interface.Common.Mapping.IReadMapping"
 
+        return self.get(key) is not None
 
-    def __delitem__(self, name):
-        '''See interface IWriteContainer'''
-        if name in self.__bindings.values():
-            # Should we silently unbind the service?
-            # self.unbindService(name)
-            # No, let's raise an exception
-            raise ZopeError("Cannot remove a bound service. Unbind it first.")
-        BTreeContainer.__delitem__(self, name)


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/configure.zcml 1.4 => 1.5 ===
    xmlns='http://namespaces.zope.org/zope'
    xmlns:browser='http://namespaces.zope.org/browser'
 >
+
   <content class=".ServiceManager.">
     <require
-        permission="Zope.Public"
+        permission="Zope.View"
+        interface="Zope.App.OFS.Container.IContainer.ISimpleReadContainer" />
+    <require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Services.ServiceManager.IServiceManager." />
+  </content>
+
+  <content class=".Packages.">
+    <require
+        permission="Zope.View"
         interface="Zope.App.OFS.Container.IContainer.IReadContainer" />
     <require
         permission="Zope.ManageServices"
         interface="Zope.App.OFS.Container.IContainer.IWriteContainer" />
     <require
         permission="Zope.ManageServices"
-        interface="Zope.App.OFS.Services.ServiceManager.IServiceManager." />
+        interface=".IComponentManager." />
+  </content>
+
+  <content class=".Package.">
+    <require
+        permission="Zope.View"
+        interface="Zope.App.OFS.Container.IContainer.IReadContainer" />
+    <require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Container.IContainer.IWriteContainer" />
+  </content>
+
+  <content class=".ServiceDirective.">
+    <require
+        permission="Zope.ManageServices"
+        interface=".IServiceDirective." />
   </content>
+
+
 
   <include package="Zope.App.OFS.Services.ServiceManager.Views" />