Package x2go :: Module mimebox

[frames] | no frames]

# Source Code for Module x2go.mimebox

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