Package smartcard :: Module CardMonitoring
[hide private]
[frames] | no frames]

Source Code for Module smartcard.CardMonitoring

  1  """Smart card insertion/removal monitoring classes. 
  2   
  3  CardObserver is a base class for objects that are to be notified 
  4  upon smart card insertion/removal. 
  5   
  6  CardMonitor is a singleton object notifying registered CardObservers 
  7  upon reader insertion/removal. 
  8   
  9  __author__ = "http://www.gemalto.com" 
 10   
 11  Copyright 2001-2012 gemalto 
 12  Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 
 13   
 14  This file is part of pyscard. 
 15   
 16  pyscard is free software; you can redistribute it and/or modify 
 17  it under the terms of the GNU Lesser General Public License as published by 
 18  the Free Software Foundation; either version 2.1 of the License, or 
 19  (at your option) any later version. 
 20   
 21  pyscard is distributed in the hope that it will be useful, 
 22  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 23  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 24  GNU Lesser General Public License for more details. 
 25   
 26  You should have received a copy of the GNU Lesser General Public License 
 27  along with pyscard; if not, write to the Free Software 
 28  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 29  """ 
 30   
 31  from __future__ import print_function 
 32  from threading import Thread, Event 
 33  from time import sleep 
 34  import traceback 
 35   
 36  from smartcard.Observer import Observer 
 37  from smartcard.Observer import Observable 
 38   
 39  from smartcard.CardRequest import CardRequest 
 40   
 41  _START_ON_DEMAND_ = False 
 42   
 43   
 44  # CardObserver interface 
45 -class CardObserver(Observer):
46 """ 47 CardObserver is a base abstract class for objects that are to be notified 48 upon smart card insertion / removal. 49 """ 50
51 - def __init__(self):
52 pass
53
54 - def update(self, observable, handlers):
55 """Called upon smart card insertion / removal. 56 57 @param observable: 58 @param handlers: 59 - addedcards: list of inserted smart cards causing notification 60 - removedcards: list of removed smart cards causing notification 61 """ 62 pass
63 64
65 -class CardMonitor(object):
66 """Class that monitors smart card insertion / removals. 67 and notify observers 68 69 note: a card monitoring thread will be running 70 as long as the card monitor has observers, or CardMonitor.stop() 71 is called. Do not forget to delete all your observers by 72 calling deleteObserver, or your program will run forever... 73 74 Uses the singleton pattern from Thinking in Python 75 Bruce Eckel, http://mindview.net/Books/TIPython to make sure 76 there is only one CardMonitor. 77 """ 78
79 - class __CardMonitorSingleton(Observable):
80 """The real smart card monitor class. 81 82 A single instance of this class is created 83 by the public CardMonitor class. 84 """ 85
86 - def __init__(self):
87 Observable.__init__(self) 88 if _START_ON_DEMAND_: 89 self.rmthread = None 90 else: 91 self.rmthread = CardMonitoringThread(self)
92
93 - def addObserver(self, observer):
94 """Add an observer. 95 96 We only start the card monitoring thread when 97 there are observers. 98 """ 99 Observable.addObserver(self, observer) 100 if _START_ON_DEMAND_: 101 if self.countObservers() > 0 and self.rmthread == None: 102 self.rmthread = CardMonitoringThread(self) 103 else: 104 observer.update(self, (self.rmthread.cards, []))
105
106 - def deleteObserver(self, observer):
107 """Remove an observer. 108 109 We delete the CardMonitoringThread reference when there 110 are no more observers. 111 """ 112 Observable.deleteObserver(self, observer) 113 if _START_ON_DEMAND_: 114 if self.countObservers() == 0: 115 if self.rmthread != None: 116 self.rmthread = None
117
118 - def __str__(self):
119 return 'CardMonitor'
120 121 # the singleton 122 instance = None 123
124 - def __init__(self):
127
128 - def __getattr__(self, name):
129 return getattr(self.instance, name)
130 131
132 -class CardMonitoringThread(object):
133 """Card insertion thread. 134 This thread waits for card insertion. 135 """ 136
138 """The real card monitoring thread class. 139 140 A single instance of this class is created 141 by the public CardMonitoringThread class. 142 """ 143
144 - def __init__(self, observable):
145 Thread.__init__(self) 146 self.observable = observable 147 self.stopEvent = Event() 148 self.stopEvent.clear() 149 self.cards = [] 150 self.setDaemon(True)
151 152 # the actual monitoring thread
153 - def run(self):
154 """Runs until stopEvent is notified, and notify 155 observers of all card insertion/removal. 156 """ 157 self.cardrequest = CardRequest(timeout=0.1) 158 while self.stopEvent.isSet() != 1: 159 try: 160 currentcards = self.cardrequest.waitforcardevent() 161 162 addedcards = [] 163 for card in currentcards: 164 if not self.cards.__contains__(card): 165 addedcards.append(card) 166 167 removedcards = [] 168 for card in self.cards: 169 if not currentcards.__contains__(card): 170 removedcards.append(card) 171 172 if addedcards != [] or removedcards != []: 173 self.cards = currentcards 174 self.observable.setChanged() 175 self.observable.notifyObservers( 176 (addedcards, removedcards)) 177 178 # when CardMonitoringThread.__del__() is invoked in 179 # response to shutdown, e.g., when execution of the 180 # program is done, other globals referenced by the 181 # __del__() method may already have been deleted. 182 # this causes ReaderMonitoringThread.run() to except 183 # with a TypeError or AttributeError 184 except TypeError: 185 pass 186 except AttributeError: 187 pass 188 189 except: 190 # FIXME Tighten the exceptions caught by this block 191 traceback.print_exc() 192 # Most likely raised during interpreter shutdown due 193 # to unclean exit which failed to remove all observers. 194 # To solve this, we set the stop event and pass the 195 # exception to let the thread finish gracefully. 196 self.stopEvent.set()
197 198 # stop the thread by signaling stopEvent
199 - def stop(self):
200 self.stopEvent.set()
201 202 # the singleton 203 instance = None 204
205 - def __init__(self, observable):
210
211 - def __getattr__(self, name):
212 if self.instance: 213 return getattr(self.instance, name)
214 215 # commented to avoid bad clean-up sequence of python where __del__ 216 # is called when some objects it uses are already gargabe collected 217 #def __del__(self): 218 # if CardMonitoringThread.instance!=None: 219 # CardMonitoringThread.instance.stop() 220 # CardMonitoringThread.instance = None 221 222 223 if __name__ == "__main__": 224 print('insert or remove cards in the next 10 seconds') 225 226 # a simple card observer that prints added/removed cards
227 - class printobserver(CardObserver):
228
229 - def __init__(self, obsindex):
230 self.obsindex = obsindex
231
232 - def update(self, observable, handlers):
233 addedcards, removedcards = handlers 234 print("%d - added: %s" % (self.obsindex, str(addedcards))) 235 print("%d - removed: %s" % (self.obsindex, str(removedcards)))
236
237 - class testthread(Thread):
238
239 - def __init__(self, obsindex):
240 Thread.__init__(self) 241 self.readermonitor = CardMonitor() 242 self.obsindex = obsindex 243 self.observer = None
244
245 - def run(self):
246 # create and register observer 247 self.observer = printobserver(self.obsindex) 248 self.readermonitor.addObserver(self.observer) 249 sleep(10) 250 self.readermonitor.deleteObserver(self.observer)
251 252 t1 = testthread(1) 253 t2 = testthread(2) 254 t1.start() 255 t2.start() 256