############################################################################## # # Copyright (c) 2005 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 # ############################################################################## """ GenericSetup export / import support for PluginRegistry. $Id: exportimport.py 74714 2007-04-24 18:21:57Z tseaver $ """ from StringIO import StringIO from Persistence import PersistentMapping from zope.interface import implements from Products.GenericSetup.interfaces import IFilesystemExporter from Products.GenericSetup.interfaces import IFilesystemImporter from Products.GenericSetup.content import FauxDAVRequest from Products.GenericSetup.content import FauxDAVResponse from Products.GenericSetup.utils import ExportConfiguratorBase from Products.GenericSetup.utils import ImportConfiguratorBase from Products.GenericSetup.utils import _getDottedName from Products.GenericSetup.utils import _resolveDottedName from Products.GenericSetup.utils import CONVERTER from Products.GenericSetup.utils import DEFAULT from Products.GenericSetup.utils import KEY from Products.PageTemplates.PageTemplateFile import PageTemplateFile from interfaces import IPluginRegistry def _providedBy(obj, iface): try: return iface.providedBy(obj) except AttributeError: return iface.isImplementedBy(obj) # Z2 interfaces _FILENAME = 'pluginregistry.xml' def _getRegistry(site): registries = [x for x in site.objectValues() if _providedBy(x, IPluginRegistry)] if len(registries) < 1: raise ValueError, 'No plugin registries' if len(registries) > 1: raise ValueError, 'Too many plugin registries' return registries[0] def exportPluginRegistry(context): """ Export plugin registry as an XML file. o Designed for use as a GenericSetup export step. """ registry = _getRegistry(context.getSite()) pre = PluginRegistryExporter(registry).__of__(registry) xml = pre.generateXML() context.writeDataFile(_FILENAME, xml, 'text/xml') return 'Plugin registry exported.' def _updatePluginRegistry(registry, xml, should_purge, encoding=None): if should_purge: registry._plugin_types = [] registry._plugin_type_info = PersistentMapping() registry._plugins = PersistentMapping() pir = PluginRegistryImporter(registry, encoding) reg_info = pir.parseXML(xml) for info in reg_info['plugin_types']: iface = _resolveDottedName(info['interface']) # Avoid duplicate plugin types if iface not in registry._plugin_types: registry._plugin_types.append(iface) registry._plugin_type_info[iface] = {'id': info['id'], 'title': info['title'], 'description': info['description'], } registry._plugins[iface] = tuple([x['id'] for x in info['plugins']]) def importPluginRegistry(context): """ Import plugin registry from an XML file. o Designed for use as a GenericSetup import step. """ registry = _getRegistry(context.getSite()) encoding = context.getEncoding() xml = context.readDataFile(_FILENAME) if xml is None: return 'Site properties: Nothing to import.' _updatePluginRegistry(registry, xml, context.shouldPurge(), encoding) return 'Plugin registry imported.' class PluginRegistryExporter(ExportConfiguratorBase): def __init__(self, context, encoding=None): ExportConfiguratorBase.__init__(self, None, encoding) self.context = context def _getExportTemplate(self): return PageTemplateFile('xml/pirExport.xml', globals()) def listPluginTypes(self): for info in self.context.listPluginTypeInfo(): iface = info['interface'] info['interface'] = _getDottedName(iface) info['plugins'] = self.context.listPluginIds(iface) yield info class PluginRegistryImporter(ImportConfiguratorBase): def __init__(self, context, encoding=None): ImportConfiguratorBase.__init__(self, None, encoding) self.context = context def _getImportMapping(self): return { 'plugin-registry': {'plugin-type': {KEY: 'plugin_types', DEFAULT: ()}, }, 'plugin-type': {'id': {KEY: 'id'}, 'interface': {KEY: 'interface'}, 'title': {KEY: 'title'}, 'description': {KEY: 'description'}, 'plugin': {KEY: 'plugins', DEFAULT: ()} }, 'plugin': {'id': {KEY: 'id'}, }, } class PluginRegistryFileExportImportAdapter(object): """ Designed for ues when exporting / importing PR's within a container. """ implements(IFilesystemExporter, IFilesystemImporter) def __init__(self, context): self.context = context def export(self, export_context, subdir, root=False): """ See IFilesystemExporter. """ context = self.context pre = PluginRegistryExporter(context).__of__(context) xml = pre.generateXML() export_context.writeDataFile(_FILENAME, xml, 'text/xml', subdir, ) def listExportableItems(self): """ See IFilesystemExporter. """ return () def import_(self, import_context, subdir, root=False): """ See IFilesystemImporter. """ data = import_context.readDataFile(_FILENAME, subdir) if data is None: import_context.note('SGAIFA', 'no pluginregistry.xml in %s' % subdir) else: request = FauxDAVRequest(BODY=data, BODYFILE=StringIO(data)) response = FauxDAVResponse() _updatePluginRegistry(self.context, data, import_context.shouldPurge(), import_context.getEncoding(), )