Package x2go :: Module mimebox
[frames] | no frames]

Source Code for Module x2go.mimebox

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Copyright (C) 2010-2011 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> 
  5  # 
  6  # Python X2go is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # Python X2go is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the 
 18  # Free Software Foundation, Inc., 
 19  # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 
 20   
 21  """\ 
 22  L{X2goMIMEboxQueue} sets up a thread that listens for incoming files that 
 23  shall be opened locally on the client. 
 24   
 25  For each file that gets dropped in the MIME box an individual  
 26  thread is started (L{X2goMIMEboxJob}) that handles the processing  
 27  of the incoming file. 
 28   
 29  """ 
 30  __NAME__ = 'x2gomimeboxqueue-pylib' 
 31   
 32  # modules 
 33  import os 
 34  import copy 
 35  import types 
 36  import threading 
 37  import gevent 
 38   
 39  # Python X2go modules 
 40  import defaults 
 41  import utils 
 42  import log 
 43  import mimeboxactions 
 44   
 45  if defaults.X2GOCLIENT_OS != 'Windows': 
 46      from x2go_exceptions import WindowsError 
47 48 49 -class X2goMIMEboxQueue(threading.Thread):
50 """\ 51 If the X2go MIME box is supported in a particaluar L{X2goSession} instance 52 this class provides a sub-thread for handling incoming files in the MIME box 53 directory. The actual handling of a dropped file is handled by the classes 54 L{X2goMIMEboxActionOPEN}, L{X2goMIMEboxActionOPENWITH} and L{X2goMIMEboxActionSAVEAS}. 55 56 """ 57 mimebox_action = None 58 59 mimebox = None 60 active_jobs = {} 61 mimebox_history = [] 62
63 - def __init__(self, profile_name='UNKNOWN', session_name='UNKNOWN', 64 mimebox_dir=None, mimebox_action=None, mimebox_extensions=[], 65 client_instance=None, logger=None, loglevel=log.loglevel_DEFAULT):
66 """\ 67 @param profile_name: name of the session profile this print queue belongs to 68 @type profile_name: C{str} 69 @param mimebox_dir: local directory for incoming MIME box files 70 @type mimebox_dir: C{str} 71 @param mimebox_action: name or instance of either of the possible X2go print action classes 72 @type mimebox_action: C{str} or instance 73 @param client_instance: the underlying L{X2goClient} instance 74 @type client_instance: C{instance} 75 @param logger: you can pass an L{X2goLogger} object to the 76 L{X2goPrintQueue} constructor 77 @type logger: C{instance} 78 @param loglevel: if no L{X2goLogger} object has been supplied a new one will be 79 constructed with the given loglevel 80 @type loglevel: C{int} 81 82 """ 83 if logger is None: 84 self.logger = log.X2goLogger(loglevel=loglevel) 85 else: 86 self.logger = copy.deepcopy(logger) 87 self.logger.tag = __NAME__ 88 89 self.profile_name = profile_name 90 self.session_name = session_name 91 self.mimebox_dir = mimebox_dir 92 self.mimebox_extensions = mimebox_extensions 93 self.client_instance = client_instance 94 self.client_rootdir = client_instance.get_client_rootdir() 95 96 # this has to be set before we set the MIME box action... 97 self._accept_jobs = False 98 99 if mimebox_action is None: 100 mimebox_action = mimebox_actions.X2goMIMEboxActionOPEN(client_instance=self.client_instance, logger=self.logger) 101 elif type(mimebox_action) in (types.StringType, types.UnicodeType): 102 mimebox_action = self.set_mimebox_action(mimebox_action, client_instance=self.client_instance, logger=self.logger) 103 else: 104 # hope it's already an instance... 105 self.mimebox_action = mimebox_action 106 107 threading.Thread.__init__(self) 108 self.daemon = True 109 self._accept_jobs = True
110 111
112 - def __del__(self):
113 """\ 114 Class destructor. 115 116 """ 117 self.stop_thread()
118
119 - def pause(self):
120 """\ 121 Prevent acceptance of new incoming files. The processing of MIME box jobs that 122 are currently still active will be completed, though. 123 124 """ 125 if self._accept_jobs == True: 126 self._accept_jobs = False 127 self.logger('paused thread: %s' % repr(self), loglevel=log.loglevel_DEBUG)
128
129 - def resume(self):
130 """\ 131 Resume operation of the X2go MIME box queue and continue accepting new incoming 132 files. 133 134 """ 135 if self._accept_jobs == False: 136 self._accept_jobs = True 137 self.logger('resumed thread: %s' % repr(self), loglevel=log.loglevel_DEBUG)
138
139 - def stop_thread(self):
140 """\ 141 Stops this L{X2goMIMEboxQueue} thread completely. 142 143 """ 144 self.pause() 145 self._keepalive = False 146 self.logger('stopping thread: %s' % repr(self), loglevel=log.loglevel_DEBUG)
147 148 @property
149 - def _incoming_mimebox_jobs(self):
150 if os.path.exists(self.mimebox_dir): 151 l = os.listdir(self.mimebox_dir) 152 mimebox_jobs = [] 153 for _ext in self.mimebox_extensions: 154 mimebox_jobs.extend([ dj for dj in l if dj.upper().endswith(_ext.upper()) ]) 155 else: 156 mimebox_jobs = l 157 return [ dj for dj in mimebox_jobs if dj not in self.active_jobs.keys() ] 158 else: 159 return []
160
161 - def set_mimebox_action(self, mimebox_action, **kwargs):
162 """\ 163 Modify the MIME box action of this L{X2goMIMEboxQueue} thread during runtime. The 164 change of the MIME box action will be valid for the next incoming file in the MIME box 165 directory. 166 167 """ 168 if mimebox_action in defaults.X2GO_MIMEBOX_ACTIONS.keys(): 169 mimebox_action = defaults.X2GO_MIMEBOX_ACTIONS[mimebox_action] 170 171 if mimebox_action in defaults.X2GO_MIMEBOX_ACTIONS.values(): 172 self.mimebox_action = eval ('mimeboxactions.%s(**kwargs)' % mimebox_action)
173
174 - def run(self):
175 """\ 176 This method gets called once the L{X2goMIMEboxQueue} thread is started by the C{X2goMIMEboxQueue.start()} method. 177 178 """ 179 self.logger('starting MIME box queue thread: %s' % repr(self), loglevel=log.loglevel_DEBUG) 180 181 self._keepalive = True 182 while self._keepalive: 183 184 while self._accept_jobs: 185 186 if self._incoming_mimebox_jobs: 187 188 for _job in self._incoming_mimebox_jobs: 189 self.logger('processing incoming X2go MIME box job: %s' % _job, loglevel=log.loglevel_NOTICE) 190 _new_mimeboxjob_thread = X2goMIMEboxJob(target=x2go_mimeboxjob_handler, 191 kwargs={ 192 'mimebox_file': _job, 193 'mimebox_extensions': self.mimebox_extensions, 194 'mimebox_action': self.mimebox_action, 195 'parent_thread': self, 196 'logger': self.logger, 197 } 198 ) 199 self.active_jobs['%s' % _job] = _new_mimeboxjob_thread 200 _new_mimeboxjob_thread.start() 201 202 gevent.sleep(3) 203 204 gevent.sleep(1)
205
206 207 -def x2go_mimeboxjob_handler(mimebox_file=None, 208 mimebox_extensions=[], 209 mimebox_action=None, 210 parent_thread=None, logger=None, ):
211 """\ 212 This function is called as a handler function for each incoming X2go MIME box file 213 represented by the class L{X2goMIMEboxJob}. 214 215 @param mimebox_file: MIME box file name as placed in to the X2go MIME box spool directory 216 @type mimebox_file: C{str} 217 @param mimebox_action: an instance of either of the possible C{X2goMIMEboxActionXXX} classes 218 @type mimebox_action: C{X2goMIMEboxActionXXX} nstance 219 @param parent_thread: the L{X2goMIMEboxQueue} thread that actually created this handler's L{X2goMIMEboxJob} instance 220 @type parent_thread: C{instance} 221 @param logger: the L{X2goMIMEboxQueue}'s logging instance 222 @type logger: C{instance} 223 224 """ 225 mimebox_action.profile_name = parent_thread.profile_name 226 mimebox_action.session_name = parent_thread.session_name 227 228 logger('action for printing is: %s' % mimebox_action, loglevel=log.loglevel_DEBUG) 229 230 _dotfile = mimebox_file.startswith('.') 231 _blacklisted = mimebox_file.upper().split('.')[-1] in defaults.X2GO_MIMEBOX_EXTENSIONS_BLACKLIST 232 _really_process = bool(not _blacklisted and ((not mimebox_extensions) or [ ext for ext in mimebox_extensions if mimebox_file.upper().endswith('%s' % ext.upper()) ])) 233 if _really_process and not _blacklisted and not _dotfile: 234 mimebox_action.do_process(mimebox_file=mimebox_file, 235 mimebox_dir=parent_thread.mimebox_dir, 236 ) 237 elif not _blacklisted and not _dotfile: 238 logger('file extension of MIME box file %s is prohibited by session profile configuration' % mimebox_file, loglevel=log.loglevel_NOTICE) 239 elif _dotfile: 240 logger('placing files starting with a dot (.<file>) into the X2go MIME box is prohibited, ignoring the file ,,%s\'\'' % mimebox_file, loglevel=log.loglevel_WARN) 241 else: 242 logger('file extension of MIME box file %s has been found in Python X2go\' hardcoded MIME box extenstions blacklist' % mimebox_file, loglevel=log.loglevel_WARN) 243 244 logger('removing MIME box file %s' % mimebox_file, loglevel=log.loglevel_DEBUG) 245 246 utils.patiently_remove_file(parent_thread.mimebox_dir, mimebox_file) 247 logger('removed print job file %s' % mimebox_file, loglevel=log.loglevel_DEBUG) 248 249 del parent_thread.active_jobs['%s' % mimebox_file] 250 parent_thread.mimebox_history.append(mimebox_file) 251 # in case we do a lot of mimebox file exports we do not want to risk an 252 # endlessly growing mimebox job history 253 if len(parent_thread.mimebox_history) > 100: 254 parent_thread.mimebox_history = parent_thread.mimebox_history[-100:]
255
256 257 -class X2goMIMEboxJob(threading.Thread):
258 """\ 259 For each X2go MIME box job we create a sub-thread that let's 260 the MIME box job be processed in the background. 261 262 As a handler for this class the function L{x2go_mimeboxjob_handler()} 263 is used. 264 265 """
266 - def __init__(self, **kwargs):
267 """\ 268 Construct the X2go MIME box job thread... 269 270 All parameters (**kwargs) are passed through to the constructor 271 of C{threading.Thread()}. 272 273 """ 274 threading.Thread.__init__(self, **kwargs) 275 self.daemon = True
276