getattr -> restrictedTraverse : si on utilise geattr au lieu de restrictedTraverse...
[Portfolio.git] / ImageManipulationTool.py
1 # -*- coding: utf-8 -*-
2 ############################################################
3 # Copyright © 2005-2008 Benoît PIN <benoit.pin@ensmp.fr> #
4 # Plinn - http://plinn.org #
5 # #
6 # This program is free software; you can redistribute it #
7 # and/or modify it under the terms of the Creative Commons #
8 # "Attribution-Noncommercial 2.0 Generic" #
9 # http://creativecommons.org/licenses/by-nc/2.0/ #
10 ############################################################
11 """ Image manipulation tool
12 """
13
14 from AccessControl import ClassSecurityInfo
15 from AccessControl.requestmethod import postonly
16 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
17 from Products.CMFCore.permissions import ManagePortal
18 from AccessControl import getSecurityManager
19 from Globals import InitializeClass
20 from OFS.OrderedFolder import OrderedFolder
21 from Products.CMFCore.utils import UniqueObject
22 from Products.CMFCore.utils import getToolByName
23 from utils import Message as _
24 from manipulation import ImageQueueProcessorThread
25 from Products.MailHost.decorator import synchronized
26 import time
27 from logging import getLogger
28 from threading import Lock
29 import weakref
30 console = getLogger('[portal_image_manipulation]')
31 queue_threads = weakref.WeakValueDictionary()
32
33
34 class ImageManipulationTool( UniqueObject, OrderedFolder) :
35 """ Contains image manipulation plugins
36 """
37
38 id = 'portal_image_manipulation'
39 meta_type = 'Image Manipulation Tool'
40 manage_options = ({'label' : _('Processor'), 'action' : 'manage_processor'}, ) + \
41 OrderedFolder.manage_options
42
43 security = ClassSecurityInfo()
44 lock = Lock()
45
46 security.declareProtected( ManagePortal, 'manage_processor' )
47 manage_processor = PageTemplateFile('www/manageProcessor', globals(),
48 __name__='manage_processor')
49
50 security.declareProtected(ManagePortal, 'manage_startProcess')
51 @postonly
52 def manage_startProcess(self, REQUEST) :
53 ' start processor thread '
54 self._startQueueProcessorThread()
55 return self.manage_processor(self, REQUEST,
56 manage_tabs_message=_('Process started.'))
57
58 security.declareProtected(ManagePortal, 'manage_stopProcess')
59 @postonly
60 def manage_stopProcess(self, REQUEST) :
61 ' stop processor thread '
62 self._stopQueueProcessorThread()
63 return self.manage_processor(self, REQUEST,
64 manage_tabs_message=_('Process stopped.'))
65
66 security.declareProtected(ManagePortal, 'isRunning')
67 def isRunning(self):
68 """ returns boolean telling if the processor thread is running.
69 """
70 path = self.absolute_url(1)
71 if queue_threads.has_key(path):
72 thread = queue_threads[path]
73 return thread.isAlive()
74 else :
75 return False
76
77 security.declareProtected(ManagePortal, 'getQueueSize')
78 def getQueueSize(self):
79 """returns queue size
80 """
81 if self.isRunning() :
82 path = self.absolute_url(1)
83 if queue_threads.has_key(path):
84 thread = queue_threads[path]
85 return thread.queueSize
86
87 return 0
88
89 def _queueAdd(self, itemPath) :
90 if not self.isRunning() :
91 self._startQueueProcessorThread(itemPath)
92 else :
93 path = self.absolute_url(1)
94 thread = queue_threads[path]
95 thread.queueAdd(itemPath)
96
97 @synchronized(lock)
98 def _startQueueProcessorThread(self, itemPath=None):
99 """ Start thread for processing image manipulation """
100
101 if not self.isRunning() :
102 utool = getToolByName(self, 'portal_url')
103 ctool = getToolByName(self, 'portal_catalog')
104 portal = utool.getPortalObject()
105 brains = ctool.unrestrictedSearchResults(portal_type='Photo', tiles_available=0)
106 paths = [b.getPath() for b in brains]
107 if itemPath is not None and itemPath not in paths :
108 paths.insert(0, itemPath)
109 thread = ImageQueueProcessorThread(portal.getPhysicalPath(), paths)
110 thread.start()
111 path = self.absolute_url(1)
112 queue_threads[path] = thread
113 console.info('Thread for %s started' % path)
114
115 @synchronized(lock)
116 def _stopQueueProcessorThread(self):
117 """ Stop thread for processing image manipulation """
118
119 path = self.absolute_url(1)
120 if queue_threads.has_key(path):
121 thread = queue_threads[path]
122 thread.stop()
123 while thread.isAlive():
124 # wait until thread is really dead
125 time.sleep(0.3)
126 del queue_threads[path]
127 console.info('Thread for %s stopped' % path)
128
129 InitializeClass( ImageManipulationTool )