Back to index

plone3  3.1.7
components.py
Go to the documentation of this file.
00001 ##############################################################################
00002 #
00003 # Copyright (c) 2006 Zope Corporation and Contributors. All Rights Reserved.
00004 #
00005 # This software is subject to the provisions of the Zope Public License,
00006 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
00007 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
00008 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00009 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
00010 # FOR A PARTICULAR PURPOSE.
00011 #
00012 ##############################################################################
00013 """Local component registry export / import handler.
00014 
00015 $Id: components.py 82390 2007-12-22 13:29:55Z yuppie $
00016 """
00017 
00018 from operator import itemgetter
00019 
00020 from zope.component import adapts
00021 from zope.component import getSiteManager
00022 from zope.component import queryMultiAdapter
00023 from zope.component.interfaces import IComponentRegistry
00024 
00025 from Acquisition import aq_base
00026 from Acquisition import aq_parent
00027 
00028 from interfaces import IBody
00029 from interfaces import ISetupEnviron
00030 from utils import XMLAdapterBase
00031 from utils import _getDottedName
00032 from utils import _resolveDottedName
00033 
00034 
00035 class ComponentRegistryXMLAdapter(XMLAdapterBase):
00036 
00037     """XML im- and exporter for a local component registry.
00038     """
00039 
00040     adapts(IComponentRegistry, ISetupEnviron)
00041 
00042     _LOGGER_ID = 'componentregistry'
00043 
00044     name = 'componentregistry'
00045 
00046     def _exportNode(self):
00047         node = self._doc.createElement('componentregistry')
00048         fragment = self._doc.createDocumentFragment()
00049 
00050         child = self._doc.createElement('adapters')
00051         child.appendChild(self._extractAdapters())
00052         self._logger.info('Adapters exported.')
00053         fragment.appendChild(child)
00054 
00055         child = self._doc.createElement('utilities')
00056         child.appendChild(self._extractUtilities())
00057         self._logger.info('Utilities exported.')
00058         fragment.appendChild(child)
00059 
00060         node.appendChild(fragment)
00061 
00062         return node
00063 
00064     def _importNode(self, node):
00065         if self.environ.shouldPurge():
00066             self._purgeAdapters()
00067             self._logger.info('Adapters purged.')
00068             self._purgeUtilities()
00069             self._logger.info('Utilities purged.')
00070 
00071         for child in node.childNodes:
00072             if child.nodeName == 'adapters':
00073                 self._initAdapters(child)
00074                 self._logger.info('Adapters registered.')
00075             if child.nodeName == 'utilities':
00076                 self._initUtilities(child)
00077                 self._logger.info('Utilities registered.')
00078 
00079     def _purgeAdapters(self):
00080         registrations = tuple(self.context.registeredAdapters())
00081         
00082         for registration in registrations:
00083             factory = registration.factory
00084             required = registration.required
00085             provided = registration.provided
00086             name = registration.name
00087 
00088             self.context.unregisterAdapter(factory=factory,
00089                                            required=required,
00090                                            provided=provided,
00091                                            name=name)
00092 
00093     def _purgeUtilities(self):
00094         registrations = tuple(self.context.registeredUtilities())
00095         
00096         for registration in registrations:
00097             provided = registration.provided
00098             name = registration.name
00099             self.context.unregisterUtility(provided=provided, name=name)
00100 
00101     def _initAdapters(self, node):
00102         for child in node.childNodes:
00103             if child.nodeName != 'adapter':
00104                 continue
00105 
00106             factory = _resolveDottedName(child.getAttribute('factory'))
00107             provided = _resolveDottedName(child.getAttribute('provides'))
00108             name = unicode(str(child.getAttribute('name')))
00109 
00110             for_ = child.getAttribute('for_')
00111             required = []
00112             for interface in for_.split(u' '):
00113                 if interface:
00114                     required.append(_resolveDottedName(interface))
00115 
00116             self.context.registerAdapter(factory,
00117                                          required=required,
00118                                          provided=provided,
00119                                          name=name)
00120 
00121     def _getSite(self):
00122         # Get the site by either __parent__ or Acquisition
00123         site = getattr(self.context, '__parent__', None)
00124         if site is None:
00125             site = aq_parent(self.context)
00126         return site
00127 
00128     def _initUtilities(self, node):
00129         site = self._getSite()
00130         for child in node.childNodes:
00131             if child.nodeName != 'utility':
00132                 continue
00133 
00134             provided = _resolveDottedName(child.getAttribute('interface'))
00135             name = unicode(str(child.getAttribute('name')))
00136 
00137             component = child.getAttribute('component')
00138             component = component and _resolveDottedName(component) or None
00139 
00140             factory = child.getAttribute('factory')
00141             factory = factory and _resolveDottedName(factory) or None
00142 
00143             obj_path = child.getAttribute('object')
00144             if not component and not factory and obj_path is not None:
00145                 # Support for registering the site itself
00146                 if obj_path in ('', '/'):
00147                     obj = site
00148                 else:
00149                     # BBB: filter out path segments, we did claim to support
00150                     # nested paths once
00151                     id_ = [p for p in obj_path.split('/') if p][0]
00152                     obj = getattr(site, id_, None)
00153 
00154                 if obj is not None:
00155                     self.context.registerUtility(aq_base(obj), provided, name)
00156                 else:
00157                     # Log an error, object not found
00158                     self._logger.warning("The object %s was not found, while "
00159                                          "trying to register an utility. The "
00160                                          "provided object definition was %s. "
00161                                          "The site used was: %s"
00162                                          % (repr(obj), obj_path, repr(site)))
00163             elif component:
00164                 self.context.registerUtility(component, provided, name)
00165             elif factory is not None:
00166                 self.context.registerUtility(factory(), provided, name)
00167             else:
00168                 self._logger.warning("Invalid utility registration for "
00169                                      "interface %s" % provided)
00170 
00171     def _extractAdapters(self):
00172         fragment = self._doc.createDocumentFragment()
00173 
00174         registrations = [ {'factory': _getDottedName(reg.factory),
00175                            'provided': _getDottedName(reg.provided),
00176                            'required': reg.required,
00177                            'name': reg.name}
00178                           for reg in self.context.registeredAdapters() ]
00179         registrations.sort(key=itemgetter('name'))
00180         registrations.sort(key=itemgetter('provided'))
00181 
00182         for reg_info in registrations:
00183             child = self._doc.createElement('adapter')
00184 
00185             for_ = u''
00186             for interface in reg_info['required']:
00187                 for_ = for_ + _getDottedName(interface) + u'\n           '
00188 
00189             child.setAttribute('factory', reg_info['factory'])
00190             child.setAttribute('provides', reg_info['provided'])
00191             child.setAttribute('for_', for_.strip())
00192             if reg_info['name']:
00193                 child.setAttribute('name', reg_info['name'])
00194 
00195             fragment.appendChild(child)
00196 
00197         return fragment
00198 
00199     def _extractUtilities(self):
00200         fragment = self._doc.createDocumentFragment()
00201 
00202         registrations = [ {'component': reg.component,
00203                            'provided': _getDottedName(reg.provided),
00204                            'name': reg.name}
00205                           for reg in self.context.registeredUtilities() ]
00206         registrations.sort(key=itemgetter('name'))
00207         registrations.sort(key=itemgetter('provided'))
00208         site = aq_base(self._getSite())
00209 
00210         for reg_info in registrations:
00211             child = self._doc.createElement('utility')
00212 
00213             child.setAttribute('interface', reg_info['provided'])
00214 
00215             if reg_info['name']:
00216                 child.setAttribute('name', reg_info['name'])
00217 
00218             comp = reg_info['component']
00219             # check if the component is acquisition wrapped. If it is, export
00220             # an object reference instead of a factory reference
00221             if getattr(comp, 'aq_base', None) is not None:
00222                 if aq_base(comp) is site:
00223                     child.setAttribute('object', '')
00224                 elif hasattr(aq_base(comp), 'getId'):
00225                     child.setAttribute('object', comp.getId())
00226                 else:
00227                     # This is a five.localsitemanager wrapped utility
00228                     factory = _getDottedName(type(aq_base(comp)))
00229                     child.setAttribute('factory', factory)
00230             else:
00231                 factory = _getDottedName(type(comp))
00232                 child.setAttribute('factory', factory)
00233 
00234             fragment.appendChild(child)
00235 
00236         return fragment
00237 
00238 
00239 def importComponentRegistry(context):
00240     """Import local components.
00241     """
00242     sm = getSiteManager(context.getSite())
00243     if sm is None or not IComponentRegistry.providedBy(sm):
00244         logger = context.getLogger('componentregistry')
00245         logger.info("Can not register components, as no registry was found.")
00246         return
00247 
00248     importer = queryMultiAdapter((sm, context), IBody)
00249     if importer:
00250         body = context.readDataFile('componentregistry.xml')
00251         if body is not None:
00252             importer.body = body
00253 
00254 def exportComponentRegistry(context):
00255     """Export local components.
00256     """
00257     sm = getSiteManager(context.getSite())
00258     if sm is None or not IComponentRegistry.providedBy(sm):
00259         logger = context.getLogger('componentregistry')
00260         logger.debug("Nothing to export.")
00261         return
00262 
00263     exporter = queryMultiAdapter((sm, context), IBody)
00264     if exporter:
00265         body = exporter.body
00266         if body is not None:
00267             context.writeDataFile('componentregistry.xml', body,
00268                                   exporter.mime_type)