Back to index

plone3  3.1.7
concatfileresource.py
Go to the documentation of this file.
00001 '''\
00002 
00003 Support for concatenation and compression of resources
00004 
00005 We concatenate first and compress afterwards, giving a better
00006 chance for the compressor to optimize
00007 '''
00008 
00009 from zope.interface import implements
00010 from interfaces import IContextFile
00011 # we are aliased to Products, hence the following absolute import
00012 from concatresource.interfaces import IConcatResourceAddon
00013 from fileresource import File
00014 from compression import compress
00015 import time
00016 import zope.component
00017 try:
00018     from zope.component.interfaces import ComponentLookupError
00019 except ImportError:
00020     # Zope < 2.10
00021     from zope.component.exceptions import ComponentLookupError
00022 
00023 class ConcatFiles(object):
00024     '''A resource that concatenates files and compresses the result
00025 
00026     It is also possible to extend the statically given list via
00027     a utility.
00028     '''
00029     implements(IContextFile)
00030 
00031     def __init__(self, pathlist, name, compress_level, caching, lmt_check_period):
00032         # Path is now a list.
00033         assert isinstance(pathlist, (list, tuple))
00034         # check all files, just to raise error if don't exist
00035         for path in pathlist:
00036             file(path, 'rb').close()
00037         #
00038         self.pathlist_base = pathlist
00039         self.__name__ = name
00040         self.compress_level = compress_level
00041         self.caching = caching
00042         self.lmt_check_period = lmt_check_period
00043         # markers for pathlist modification
00044         self.pathlist = []
00045         self.fileslist_changed = None
00046         self.fileslist = []
00047 
00048     def getPathList(self):
00049         'Gets the extended pathlist'
00050         # we allow the list to be extended via an utility
00051         try:
00052             registry = zope.component.getUtility(IConcatResourceAddon, self.__name__)
00053         except ComponentLookupError:
00054             extend = []
00055         else:
00056             extend = registry.getAddonFiles()
00057         pathlist = self.pathlist_base + extend
00058         return pathlist
00059 
00060     def getFilesList(self):
00061         'Gets the list of files'
00062         ## # XXX We have two choices:
00063         ## # 1. We only calculate the list once, on startup
00064         ## # that is, we suppose that the file resource is
00065         ## # called up after the extension reg has been finished
00066         ## # and that it never changes later.
00067         ## # 2. but it also could be like this to allow changes later:
00068         pathlist = self.getPathList()
00069         if pathlist != self.pathlist:
00070         ##if not self.pathlist:
00071             ##pathlist = self.getPathList()
00072             # mark pathlist modification
00073             self.pathlist = pathlist
00074             self.fileslist_changed = time.time()
00075             fileslist = self.fileslist = [File(path, self.__name__) for path in pathlist]
00076         else:
00077             fileslist = self.fileslist
00078         return fileslist
00079 
00080     def getLastMod(self):
00081         # We take in consideration that the pathlist
00082         # itself could have changed too.
00083         return max([f.getLastMod() for f in self.getFilesList()] +
00084             [self.fileslist_changed])
00085 
00086     def getContents(self):
00087         fileslist = self.getFilesList()
00088         assert fileslist, 'Must contain at least one resource.'
00089         result = fileslist[0].getContents()
00090         content_type = result['content_type']
00091         data = [result['data']]
00092         for subres in fileslist[1:]:
00093             d = subres.getContents()
00094             # all elements must have the same content type.
00095             assert d['content_type'] == content_type
00096             data.append(d['data'])
00097         result['data'] = '\n'.join(data)
00098         result['compress_level'] = self.compress_level
00099         # Do compression on the result
00100         result['data'] = compress(**result)
00101         return result