[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>