Back to index

plone3  3.1.7
marshaller.py
Go to the documentation of this file.
00001 # Marshall: A framework for pluggable marshalling policies
00002 # Copyright (C) 2004-2006 Enfold Systems, LLC
00003 #
00004 # This program is free software; you can redistribute it and/or modify
00005 # it under the terms of the GNU General Public License as published by
00006 # the Free Software Foundation; either version 2 of the License, or
00007 # (at your option) any later version.
00008 #
00009 # This program is distributed in the hope that it will be useful,
00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 # GNU General Public License for more details.
00013 #
00014 # You should have received a copy of the GNU General Public License
00015 # along with this program; if not, write to the Free Software
00016 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 #
00018 """
00019 $Id: marshaller.py 6864 2006-09-03 07:22:52Z alecm $
00020 """
00021 
00022 from Products.CMFCore.utils import getToolByName
00023 from Products.Archetypes.debug import log
00024 from Products.Archetypes.Marshall import Marshaller
00025 from Products.Marshall.config import TOOL_ID
00026 from Products.Marshall.registry import getComponent
00027 from Products.Marshall.exceptions import MarshallingException
00028 from Acquisition import ImplicitAcquisitionWrapper
00029 
00030 def getContext(obj, REQUEST=None):
00031     context = getattr(obj, 'aq_parent', None)
00032     if context is not None or REQUEST is None:
00033         return obj
00034     return REQUEST['PARENTS'][0]
00035 
00036 class ControlledMarshaller(Marshaller):
00037 
00038     def __init__(self, fallback=None, demarshall_hook=None,
00039                  marshall_hook=None):
00040         Marshaller.__init__(self, demarshall_hook, marshall_hook)
00041         self.fallback = fallback
00042 
00043     def delegate(self, method, obj, data=None, file=None, **kw):
00044         if file is not None:
00045             kw['file'] = file
00046         __traceback_info__ = (method, obj, kw)
00047         context = getContext(obj, kw.get('REQUEST'))
00048         if context is not obj:
00049             # If the object is being created by means of a PUT
00050             # then it has no context, and some of the stuff
00051             # we are doing here may require a context.
00052             # Wrapping it in an ImplicitAcquisitionWrapper should
00053             # be safe as long as nothing tries to persist
00054             # a reference to the wrapped object.
00055             obj = ImplicitAcquisitionWrapper(obj, context)
00056         tool = getToolByName(obj, TOOL_ID, None)
00057         components = None
00058         if tool is not None:
00059             info = kw.copy()
00060             info['data'] = data
00061             info['mode'] = method
00062             components = tool.getMarshallersFor(obj, **info)
00063         else:
00064             # Couldn't find a context to get
00065             # hold of the tool or the tool is not installed.
00066             log('Could not find the marshaller tool. '
00067                 'It might not be installed or you might not '
00068                 'be providing enough context to find it.')
00069         # We just use the first component, if one is returned.
00070         if components:
00071             marshaller = getComponent(components[0])
00072         else:
00073             # If no default marshaller was provided then we complain.
00074             if self.fallback is None:
00075                 raise MarshallingException(
00076                     "Couldn't get a marshaller for %r, %r" % (obj, kw))
00077             # Otherwise, use the default marshaller provided. Note it
00078             # must be an instance, not a factory.
00079             marshaller = self.fallback
00080         __traceback_info__ = (marshaller, method, obj, kw)
00081         args = (obj,)
00082         if method == 'demarshall':
00083             args += (data,)
00084         method = getattr(marshaller, method)
00085         return method(*args, **kw)
00086 
00087     def marshall(self, obj, **kw):
00088         if not 'data' in kw:
00089             kw['data'] = ''
00090         return self.delegate('marshall', obj, **kw)
00091 
00092     def demarshall(self, obj, data, **kw):
00093         if kw.has_key('file'):
00094             if not data:
00095                 # XXX Yuck! Shouldn't read the whole file, never.
00096                 # OTOH, if you care about large files, you should be
00097                 # using the PrimaryFieldMarshaller or something
00098                 # similar.
00099                 data = kw['file'].read()
00100             del kw['file']
00101 
00102         return self.delegate('demarshall', obj, data, **kw)