[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/ServiceManager - IBindingAware.py:1.2 IServiceManager.py:1.2 ServiceManager.py:1.2 __init__.py:1.2 hooks.py:1.2 service-manager.zcml:1.2

Jim Fulton jim@zope.com
Mon, 10 Jun 2002 19:28:44 -0400


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

Added Files:
	IBindingAware.py IServiceManager.py ServiceManager.py 
	__init__.py hooks.py service-manager.zcml 
Log Message:
Merged Zope-3x-branch into newly forked Zope3 CVS Tree.


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IBindingAware.py 1.1 => 1.2 ===
+#
+# 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.
+# 
+##############################################################################
+"""
+
+Revision information:
+$Id$
+"""
+
+from Interface import Interface
+
+class IBindingAware(Interface):
+    
+    def bound(name):
+        """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


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/IServiceManager.py 1.1 => 1.2 ===
+#
+# 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 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
+
+class IServiceManager(IContainer, IGlobalServiceManager):
+    """
+    Service Managers act as containers for Services.
+    
+    If a Service Manager is asked for a service it
+    checks for those it contains, before using a context
+    based lookup to find another service manager to delegate
+    to. If no other service manager is found they defer
+    to the ComponentArchitecture ServiceManager which
+    contains file based services.
+    """
+
+    def bindService(serviceName, serviceComponentName):
+        """provide a service implementation.  If the named object
+        implements IBindingAware, the wrapped object is notified as per
+        that interface"""
+
+    def unbindService(serviceName):
+        """no longer provide a service implementation.  If the named
+        object implements IBindingAware, the wrapped object is notified
+        as per that interface"""
+
+    def getBoundService(name):
+        """retrieve a bound service implimentation
+
+        Get the component currently bound to the named Service
+        in this ServiceService.  Does not search context.
+        """
+        


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/ServiceManager.py 1.1 => 1.2 ===
+#
+# 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 IServiceManager import IServiceManager
+from Zope.ComponentArchitecture.IServiceManagerContainer \
+     import IServiceManagerContainer
+from Zope.ComponentArchitecture import getService, \
+     getNextServiceManager, getNextService
+from Zope.ComponentArchitecture.GlobalServiceManager import UndefinedService
+from Zope.ComponentArchitecture.GlobalServiceManager import InvalidService
+from Zope.Exceptions import NotFoundError, ZopeError
+from Zope.App.OFS.Content.Folder.Folder import Folder
+from Zope.ContextWrapper import ContextMethod
+from Zope.Proxy.ContextWrapper import ContextWrapper
+from Zope.App.OFS.Container.BTreeContainer import BTreeContainer
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from IBindingAware import IBindingAware
+
+class ServiceManager(BTreeContainer):
+
+    __implements__ = IServiceManager
+
+    def __init__(self):
+        self.__bindings = {}
+        super(ServiceManager, self).__init__()
+
+
+    def getServiceDefinitions(wrapped_self):
+        clean_self=removeAllProxies(wrapped_self)
+        """ see IServiceManager Interface """
+        # Get the services defined here and above us, if any (as held
+        # in a ServiceInterfaceService, presumably)
+        sm=getNextServiceManager(wrapped_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()
+                   )
+               ))
+        return serviceDefs
+
+    getServiceDefinitions=ContextMethod(getServiceDefinitions)
+
+    def getService(wrapped_self, name):
+        """ see IServiceManager Interface"""
+        clean_self=removeAllProxies(wrapped_self)
+
+        service = clean_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
+
+        return getNextService(wrapped_self, name)
+
+    getService=ContextMethod(getService)
+
+    def getBoundService(self, name):
+        """ see IServiceManager Interface"""
+
+        return self.__bindings.get(name)
+
+    def bindService(wrapped_self, serviceName, serviceComponentName):
+        """ see IServiceManager Interface"""
+        clean_self=removeAllProxies(wrapped_self)
+
+        # 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)
+
+        for name,interface in wrapped_self.getServiceDefinitions():
+            if name == serviceName:
+                if not interface.isImplementedBy(clean_serviceComponent):
+                    raise InvalidService(serviceName,
+                                         serviceComponentName,
+                                         interface)
+            break
+
+        # Services are added to the Manager through the Folder interface
+        # self.setObject(name, component)
+        
+        if IBindingAware.isImplementedBy(clean_serviceComponent):
+            wrapped_serviceComponent.bound(serviceName)
+
+        clean_self.__bindings[serviceName] = serviceComponentName
+
+        # trigger persistence
+        clean_self.__bindings = clean_self.__bindings
+
+    bindService=ContextMethod(bindService) # needed because of call to
+    # getServiceDefinitions, as well as IBindingAware stuff
+
+    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)
+        
+        if IBindingAware.isImplementedBy(clean_serviceComponent):
+            wrapped_serviceComponent.unbound(serviceName)
+
+        del clean_self.__bindings[serviceName]
+
+        # trigger persistence
+        clean_self.__bindings = clean_self.__bindings
+    
+    unbindService=ContextMethod(unbindService)
+
+
+    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/__init__.py 1.1 => 1.2 ===
+#
+# 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/lib/python/Zope/App/OFS/Services/ServiceManager/hooks.py 1.1 => 1.2 ===
+#
+# 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.ComponentArchitecture.IServiceManager import IServiceManager
+from Zope.ComponentArchitecture.IServiceManagerContainer import \
+ IServiceManagerContainer
+from Zope.Proxy.ContextWrapper import getWrapperContainer, ContextWrapper
+from Zope.ComponentArchitecture import getServiceManager
+from Zope.ComponentArchitecture.Exceptions import ComponentLookupError
+from Zope.ComponentArchitecture.GlobalServiceManager import serviceManager
+from Zope.Proxy.ProxyIntrospection import removeAllProxies
+from Zope.Security.Proxy import trustedRemoveSecurityProxy
+    
+def getServiceManager_hook(context):
+    """
+    context based lookup, with fallback to component architecture
+    service manager if no service manager found within context
+    """
+    while context is not None:
+        clean_context = removeAllProxies(context)
+
+        # if the context is actually a service or service manager...
+        if IServiceManager.isImplementedBy(clean_context):
+            return trustedRemoveSecurityProxy(context)
+        
+        if (IServiceManagerContainer.isImplementedBy(clean_context) and
+            clean_context.hasServiceManager()
+            ):
+            return ContextWrapper(
+                trustedRemoveSecurityProxy(context.getServiceManager()),
+                context,
+                name="++etc++Services",
+                )
+                                  
+        context = getWrapperContainer(context)
+
+    return serviceManager
+
+def getNextServiceManager_hook(context):
+    """if the context is a service manager or a placeful service, tries
+    to return the next highest service manager"""
+
+    context = getServiceManager(context)
+    if context is serviceManager: return None
+
+    context=getWrapperContainer(context)
+    while (context and not 
+           IServiceManagerContainer.isImplementedBy(removeAllProxies(context))
+           ):
+        context=getWrapperContainer(context) # we should be
+
+    # able to rely on the first step getting us a
+    # ServiceManagerContainer
+    context=getWrapperContainer(context)
+    return getServiceManager(context)


=== Zope3/lib/python/Zope/App/OFS/Services/ServiceManager/service-manager.zcml 1.1 => 1.2 ===
+   xmlns='http://namespaces.zope.org/zope'
+   xmlns:security='http://namespaces.zope.org/security'
+   xmlns:zmi='http://namespaces.zope.org/zmi'
+   xmlns:browser='http://namespaces.zope.org/browser'
+>
+  <content class=".ServiceManager.">
+    <security:require
+        permission="Zope.Public"
+        interface="Zope.App.OFS.Container.IContainer.IReadContainer" />
+    <security:require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Container.IContainer.IWriteContainer" />
+    <security:require
+        permission="Zope.ManageServices"
+        interface="Zope.App.OFS.Services.ServiceManager.IServiceManager." />
+  </content>
+
+  <include package="Zope.App.OFS.Services.ServiceManager.Views" 
+           file="views.zcml" />
+
+  <hook module="Zope.ComponentArchitecture"
+        name="getServiceManager"
+        implementation=".hooks.getServiceManager_hook" />
+  <hook module="Zope.ComponentArchitecture"
+        name="getNextServiceManager"
+        implementation=".hooks.getNextServiceManager_hook" />
+
+</zopeConfigure>