Package omero :: Module clients
[hide private]
[frames] | no frames]

Source Code for Module omero.clients

  1  #!/usr/bin/env python 
  2  """ 
  3   
  4     Copyright 2009 Glencoe Software, Inc. All rights reserved. 
  5     Use is subject to license terms supplied in LICENSE.txt 
  6   
  7  """ 
  8   
  9  __save__ = __name__ 
 10  __name__ = 'omero' 
 11  try: 
 12      api = __import__('omero.api') 
 13      model = __import__('omero.model') 
 14      util = __import__('omero.util') 
 15      sys = __import__('omero.sys') 
 16      import omero.all 
 17  finally: 
 18      __name__ = __save__ 
 19      del __save__ 
 20   
 21  sys = __import__("sys") 
 22  import exceptions, traceback, threading, logging 
 23  import Ice, Glacier2, Glacier2_Router_ice 
 24  import uuid 
 25   
26 -class BaseClient(object):
27 """ 28 Central client-side blitz entry point, and should be in sync with OmeroJava's omero.client 29 and OmeroCpp's omero::client. 30 31 Typical usage includes:: 32 33 client = omero.client() # Uses --Ice.Config argument or ICE_CONFIG variable 34 client = omero.client(host = host) # Defines "omero.host" 35 client = omero.client(host = host, port = port) # Defines "omero.host" and "omero.port" 36 37 For more information, see: 38 39 - U{https://trac.openmicroscopy.org.uk/omero/wiki/ClientDesign} 40 41 """ 42
43 - def __init__(self, args = None, id = None, \ 44 host = None, port = None, pmap = None):
45 """ 46 Constructor which takes one sys.argv-style list, one initialization 47 data, one host string, one port integer, and one properties map, in 48 that order. *However*, to simplify use, we reassign values based on 49 their type with a warning printed. A cleaner approach is to use named 50 parameters. 51 :: 52 c1 = omero.client(None, None, "host", myPort) # Correct 53 c2 = omero.client(host = "host", port = myPort) # Correct 54 c3 = omero.client("host", myPort) # Works with warning 55 56 Both "Ice" and "omero" prefixed properties will be parsed. 57 58 Defines the state variables:: 59 __previous : InitializationData from any previous communicator, if any 60 Used to re-initialization the client post-closeSession() 61 62 __ic : communicator. Nullness => init() needed on createSession() 63 64 __sf : current session. Nullness => createSession() needed. 65 66 __resources: if non-null, hs access to this client instance and will 67 periodically call sf.keepAlive(None) in order to keep any 68 session alive. This can be enabled either via the omero.keep_alive 69 configuration property, or by calling the enableKeepAlive() method. 70 Once enabled, the period cannot be adjusted during a single 71 session. 72 73 Modifying these variables outside of the accessors can lead to 74 undefined behavior. 75 76 Equivalent to all OmeroJava and OmeroCpp constructors 77 """ 78 79 # Setting all protected values to prevent AttributeError 80 self.__agent = "OMERO.py" #: See setAgent 81 self.__insecure = False 82 self.__previous = None 83 self.__ic = None 84 self.__oa = None 85 self.__sf = None 86 self.__uuid = None 87 self.__resources = None 88 self.__lock = threading.RLock() 89 90 # Logging 91 self.__logger = logging.getLogger("omero.client") 92 logging.basicConfig() # Does nothing if already configured 93 94 # Reassigning based on argument type 95 96 args, id, host, port, pmap = self._repair(args, id, host, port, pmap) 97 98 # Copying args since we don't really want them edited 99 if not args: 100 args = [] 101 else: 102 args = list(args) 103 104 # Equiv to multiple constructors. ####################### 105 if id == None: 106 id = Ice.InitializationData() 107 108 if id.properties == None: 109 id.properties = Ice.createProperties(args) 110 111 id.properties.parseCommandLineOptions("omero", args); 112 if host: 113 id.properties.setProperty("omero.host", str(host)) 114 if not port: 115 port = id.properties.getPropertyWithDefault("omero.port",\ 116 str(omero.constants.GLACIER2PORT)) 117 id.properties.setProperty("omero.port", str(port)) 118 if pmap: 119 for k,v in pmap.items(): 120 id.properties.setProperty(str(k), str(v)) 121 122 self._initData(id)
123
124 - def _repair(self, args, id, host, port, pmap):
125 """ 126 Takes the 5 arguments passed to the __init__ method 127 and attempts to re-order them based on their types. 128 This allows for simplified usage without parameter 129 names. 130 """ 131 types = [list, Ice.InitializationData, str, int, dict] 132 original = [args, id, host, port, pmap] 133 repaired = [None, None, None, None, None] 134 135 # Check all to see if valid 136 valid = True 137 for i in range(0, len(types)): 138 if None != original[i] and not isinstance(original[i], types[i]): 139 valid = False 140 break 141 if valid: 142 return original 143 144 # Now try to find corrections. 145 for i in range(0, len(types)): 146 found = None 147 for j in range(0, len(types)): 148 if isinstance(original[j], types[i]): 149 if not found: 150 found = original[j] 151 else: 152 raise omero.ClientError("Found two arguments of same type: " + str(types[i])) 153 if found: 154 repaired[i] = found 155 return repaired
156
157 - def _initData(self, id):
158 """ 159 Initializes the current client via an Ice.InitializationData 160 instance. This is called by all of the constructors, but may 161 also be called on createSession(name, pass) if a previous 162 call to closeSession() has nulled the Ice.Communicator. 163 """ 164 165 if not id: 166 raise ClientError("No initialization data provided."); 167 168 # Strictly necessary for this class to work 169 id.properties.setProperty("Ice.ImplicitContext", "Shared") 170 id.properties.setProperty("Ice.ACM.Client", "0") 171 id.properties.setProperty("Ice.RetryIntervals", "-1") 172 id.properties.setProperty("Ice.Default.EndpointSelection", "Ordered") 173 id.properties.setProperty("Ice.Default.PreferSecure", "1") 174 id.properties.setProperty("Ice.Plugin.IceSSL" , "IceSSL:createIceSSL") 175 id.properties.setProperty("IceSSL.Ciphers" , "ADH") 176 id.properties.setProperty("IceSSL.VerifyPeer" , "0") 177 178 # Setting MessageSizeMax 179 messageSize = id.properties.getProperty("Ice.MessageSizeMax") 180 if not messageSize or len(messageSize) == 0: 181 id.properties.setProperty("Ice.MessageSizeMax", str(omero.constants.MESSAGESIZEMAX)) 182 183 # Setting ConnectTimeout 184 self.parseAndSetInt(id, "Ice.Override.ConnectTimeout",\ 185 omero.constants.CONNECTTIMEOUT) 186 187 # Endpoints set to tcp if not present 188 endpoints = id.properties.getProperty("omero.ClientCallback.Endpoints") 189 if not endpoints or len(endpoints) == 0: 190 id.properties.setProperty("omero.ClientCallback.Endpoints", "tcp") 191 192 # ThreadPool to 5 if not present 193 threadpool = id.properties.getProperty("omero.ClientCallback.ThreadPool.Size") 194 if not threadpool or len(threadpool) == 0: 195 id.properties.setProperty("omero.ClientCallback.ThreadPool.Size", str(omero.constants.CLIENTTHREADPOOLSIZE)) 196 197 # Port, setting to default if not present 198 port = self.parseAndSetInt(id, "omero.port",\ 199 omero.constants.GLACIER2PORT) 200 201 # Default Router, set a default and then replace 202 router = id.properties.getProperty("Ice.Default.Router") 203 if not router or len(router) == 0: 204 router = str(omero.constants.DEFAULTROUTER) 205 host = id.properties.getPropertyWithDefault("omero.host", """<"omero.host" not set>""") 206 router = router.replace("@omero.port@", str(port)) 207 router = router.replace("@omero.host@", str(host)) 208 id.properties.setProperty("Ice.Default.Router", router) 209 210 # Dump properties 211 dump = id.properties.getProperty("omero.dump") 212 if len(dump) > 0: 213 m = self.getPropertyMap(id.properties) 214 keys = list(m.keys()) 215 keys.sort() 216 for key in keys: 217 print "%s=%s" % (key, m[key]) 218 219 self.__lock.acquire() 220 try: 221 if self.__ic: 222 raise ClientError("Client already initialized") 223 224 self.__ic = Ice.initialize(id) 225 226 if not self.__ic: 227 raise ClientError("Improper initialization") 228 229 # Register Object Factory 230 self.of = ObjectFactory() 231 self.of.registerObjectFactory(self.__ic) 232 for of in omero.rtypes.ObjectFactories.values(): 233 of.register(self.__ic) 234 235 # Define our unique identifier (used during close/detach) 236 self.__uuid = str(uuid.uuid4()) 237 ctx = self.__ic.getImplicitContext() 238 if not ctx: 239 raise ClientError("Ice.ImplicitContext not set to Shared") 240 ctx.put(omero.constants.CLIENTUUID, self.__uuid) 241 242 # Register the default client callback 243 self.__oa = self.__ic.createObjectAdapter("omero.ClientCallback") 244 cb = BaseClient.CallbackI(self.__ic, self.__oa) 245 self.__oa.add(cb, self.__ic.stringToIdentity("ClientCallback/%s" % self.__uuid)) 246 self.__oa.activate() 247 finally: 248 self.__lock.release()
249
250 - def setAgent(self, agent):
251 """ 252 Sets the omero.model.Session#getUserAgent() string for 253 this client. Every session creation will be passed this argument. Finding 254 open sesssions with the same agent can be done via 255 omero.api.ISessionPrx#getMyOpenAgentSessions(String). 256 """ 257 self.__agent = agent
258
259 - def isSecure(self):
260 """ 261 Specifies whether or not this client was created via a call to 262 createClient with a boolean of False. If insecure, then all 263 remote calls will use the insecure connection defined by the server. 264 """ 265 return not self.__insecure
266
267 - def createClient(self, secure):
268 """ 269 Creates a possibly insecure omero.client instance and calls joinSession 270 using the current getSessionId value. If secure is False, then first the 271 "omero.router.insecure" configuration property is retrieved from the server 272 and used as the value of "Ice.Default.Router" for the new client. Any exception 273 thrown during creation is passed on to the caller. 274 """ 275 props = self.getPropertyMap() 276 if not secure: 277 insecure = self.getSession().getConfigService().getConfigValue("omero.router.insecure") 278 if insecure is not None and insecure != "": 279 props["Ice.Default.Router"] = insecure 280 else: 281 self.__logger.warn("Could not retrieve \"omero.router.insecure\"") 282 283 nClient = omero.client(props) 284 nClient.__insecure = not secure 285 nClient.setAgent("%s;secure=%s" % (self.__agent, secure)) 286 nClient.joinSession(self.getSessionId()) 287 return nClient
288
289 - def __del__(self):
290 """ 291 Calls closeSession() and ignores any exceptions. 292 293 Equivalent to close() in OmeroJava or omero::client::~client() 294 """ 295 try: 296 self.closeSession() 297 except exceptions.Exception, e: 298 self.__logger.warning("Ignoring error in client.__del__:" + str(e.__class__))
299
300 - def getCommunicator(self):
301 """ 302 Returns the Ice.Communicator for this instance or throws 303 an exception if None. 304 """ 305 self.__lock.acquire() 306 try: 307 if not self.__ic: 308 raise ClientError("No Ice.Communicator active; call createSession() or create a new client instance") 309 return self.__ic 310 finally: 311 self.__lock.release()
312
313 - def getAdapter(self):
314 """ 315 Returns the Ice.ObjectAdapter for this instance or throws 316 an exception if None. 317 """ 318 self.__lock.acquire() 319 try: 320 if not self.__oa: 321 raise ClientError("No Ice.ObjectAdapter active; call createSession() or create a new client instance") 322 return self.__oa 323 finally: 324 self.__lock.release()
325
326 - def getSession(self):
327 """ 328 Returns the current active session or throws an exception if none has been 329 created since the last closeSession() 330 """ 331 self.__lock.acquire() 332 try: 333 sf = self.__sf 334 if not sf: 335 raise omero.ClientError("No session available") 336 return sf 337 finally: 338 self.__lock.release()
339
340 - def getSessionId(self):
341 """ 342 Returns the UUID for the current session without making a remote call. 343 Uses getSession() internally and will throw an exception if no session 344 is active. 345 """ 346 return self.getSession().ice_getIdentity().name
347
348 - def getImplicitContext(self):
349 """ 350 Returns the Ice.ImplicitContext which defines what properties 351 will be sent on every method invocation. 352 """ 353 return self.getCommunicator().getImplicitContext()
354
355 - def getProperties(self):
356 """ 357 Returns the active properties for this instance 358 """ 359 self.__lock.acquire() 360 try: 361 return self.__ic.getProperties() 362 finally: 363 self.__lock.release()
364
365 - def getProperty(self, key):
366 """ 367 Returns the property for the given key or "" if none present 368 """ 369 return self.getProperties().getProperty(key)
370
371 - def getPropertyMap(self, properties = None):
372 """ 373 Returns all properties which are prefixed with "omero." or "Ice." 374 """ 375 if properties is None: 376 properties = self.getProperties() 377 378 rv = dict() 379 for prefix in ["omero","Ice"]: 380 for k,v in properties.getPropertiesForPrefix(prefix).items(): 381 rv[k] = v 382 return rv
383
384 - def joinSession(self, session):
385 """ 386 Uses the given session uuid as name 387 and password to rejoin a running session 388 """ 389 return self.createSession(session, session)
390
391 - def createSession(self, username=None, password=None):
392 """ 393 Performs the actual logic of logging in, which is done via the 394 getRouter(). Disallows an extant ServiceFactoryPrx, and 395 tries to re-create a null Ice.Communicator. A null or empty 396 username will throw an exception, but an empty password is allowed. 397 """ 398 import omero 399 400 self.__lock.acquire() 401 try: 402 403 # Checking state 404 405 if self.__sf: 406 raise ClientError("Session already active. Create a new omero.client or closeSession()") 407 408 if not self.__ic: 409 if not self.__previous: 410 raise ClientError("No previous data to recreate communicator.") 411 self._initData(self.__previous) 412 self.__previous = None 413 414 # Check the required properties 415 416 if not username: 417 username = self.getProperty("omero.user") 418 elif isinstance(username,omero.RString): 419 username = username.val 420 421 if not username or len(username) == 0: 422 raise ClientError("No username specified") 423 424 if not password: 425 password = self.getProperty("omero.pass") 426 elif isinstance(password,omero.RString): 427 password = password.val 428 429 if not password: 430 raise ClientError("No password specified") 431 432 # Acquire router and get the proxy 433 prx = None 434 retries = 0 435 while retries < 3: 436 reason = None 437 if retries > 0: 438 self.__logger.warning(\ 439 "%s - createSession retry: %s"% (reason, retries) ) 440 try: 441 ctx = dict(self.getImplicitContext().getContext()) 442 ctx[omero.constants.AGENT] = self.__agent 443 prx = self.getRouter(self.__ic).createSession(username, password, ctx) 444 break 445 except omero.WrappedCreateSessionException, wrapped: 446 if not wrapped.concurrency: 447 raise wrapped # We only retry concurrency issues. 448 reason = "%s:%s" % (wrapped.type, wrapped.reason) 449 retries = retries + 1 450 except Ice.ConnectTimeoutException, cte: 451 reason = "Ice.ConnectTimeoutException:%s" % str(cte) 452 retries = retries + 1 453 454 if not prx: 455 raise ClientError("Obtained null object prox") 456 457 # Check type 458 self.__sf = omero.api.ServiceFactoryPrx.uncheckedCast(prx) 459 if not self.__sf: 460 raise ClientError("Obtained object proxy is not a ServiceFactory") 461 462 # Configure keep alive 463 keep_alive = self.__ic.getProperties().getPropertyWithDefault("omero.keep_alive", "-1") 464 try: 465 i = int(keep_alive) 466 self.enableKeepAlive(i) 467 except: 468 pass 469 470 # Set the client callback on the session 471 # and pass it to icestorm 472 try: 473 id = self.__ic.stringToIdentity("ClientCallback/%s" % self.__uuid ) 474 raw = self.__oa.createProxy(id) 475 self.__sf.setCallback(omero.api.ClientCallbackPrx.uncheckedCast(raw)) 476 #self.__sf.subscribe("/public/HeartBeat", raw) 477 except: 478 self.__del__() 479 raise 480 481 # Set the session uuid in the implicit context 482 self.getImplicitContext().put(omero.constants.SESSIONUUID, self.getSessionId()) 483 484 return self.__sf 485 finally: 486 self.__lock.release()
487
488 - def enableKeepAlive(self, seconds):
489 """ 490 Resets the "omero.keep_alive" property on the current 491 Ice.Communicator which is used on initialization to determine 492 the time-period between Resource checks. If no __resources 493 instance is available currently, one is also created. 494 """ 495 496 self.__lock.acquire() 497 try: 498 # A communicator must be configured! 499 ic = self.getCommunicator() 500 # Setting this here guarantees that after closeSession() 501 # the next createSession() will use the new value despite 502 # what was in the configuration file 503 ic.getProperties().setProperty("omero.keep_alive", str(seconds)) 504 505 # If it's not null, then there's already an entry for keeping 506 # any existing session alive 507 if self.__resources == None and seconds > 0: 508 self.__resources = omero.util.Resources(seconds) 509 class Entry: 510 def __init__(self, c): 511 self.c = c
512 def cleanup(self): pass 513 def check(self): 514 sf = self.c._BaseClient__sf 515 ic = self.c._BaseClient__ic 516 if sf != None: 517 try: 518 sf.keepAlive(None) 519 except exceptions.Exception, e: 520 if ic != None: 521 ic.getLogger().warning("Proxy keep alive failed.") 522 return False 523 return True
524 self.__resources.add(Entry(self)) 525 finally: 526 self.__lock.release() 527
528 - def getRouter(self, comm):
529 """ 530 Acquires the default router, and throws an exception 531 if it is not of type Glacier2.Router. Also sets the 532 Ice.ImplicitContext on the router proxy. 533 """ 534 prx = comm.getDefaultRouter() 535 if not prx: 536 raise ClientError("No default router found.") 537 router = Glacier2.RouterPrx.uncheckedCast(prx) 538 if not router: 539 raise ClientError("Error obtaining Glacier2 router") 540 541 # For whatever reason, we have to set the context 542 # on the router context here as well 543 router = router.ice_context(comm.getImplicitContext().getContext()) 544 return router
545
546 - def sha1(self, filename):
547 """ 548 Calculates the local sha1 for a file. 549 """ 550 try: 551 from hashlib import sha1 as sha_new 552 except ImportError: 553 from sha import new as sha_new 554 digest = sha_new() 555 file = open(filename, 'rb') 556 try: 557 while True: 558 block = file.read(1024) 559 if not block: 560 break 561 digest.update(block) 562 finally: 563 file.close() 564 return digest.hexdigest()
565
566 - def upload(self, filename, name = None, path = None, 567 type = None, ofile = None, block_size = 1024):
568 """ 569 Utility method to upload a file to the server. 570 """ 571 if not self.__sf: 572 raise ClientError("No session. Use createSession first.") 573 574 import os, types 575 if not filename or not isinstance(filename, types.StringType): 576 raise ClientError("Non-null filename must be provided") 577 578 if not os.path.exists(filename): 579 raise ClientError("File does not exist: " + filename) 580 581 from path import path as __path__ 582 filepath = __path__(filename) 583 file = open(filename, 'rb') 584 try: 585 586 size = os.path.getsize(file.name) 587 if block_size > size: 588 block_size = size 589 590 if not ofile: 591 ofile = omero.model.OriginalFileI() 592 593 ofile.size = omero.rtypes.rlong(size) 594 ofile.sha1 = omero.rtypes.rstring(self.sha1(file.name)) 595 596 abspath = filepath.normpath().abspath() 597 if not ofile.name: 598 if name: 599 ofile.name = omero.rtypes.rstring(name) 600 else: 601 ofile.name = omero.rtypes.rstring(str(abspath.basename())) 602 603 if not ofile.path: 604 ofile.path = omero.rtypes.rstring(str(abspath.dirname())+os.path.sep) 605 606 if not ofile.mimetype: 607 if type: 608 # ofile.mimetype = 'application/octet-stream' by default 609 ofile.mimetype = omero.rtypes.rstring(type) 610 611 # Disabled with group permissions #1434 612 # if permissions: 613 # ofile.details.permissions = permissions 614 615 up = self.__sf.getUpdateService() 616 ofile = up.saveAndReturnObject(ofile) 617 618 prx = self.__sf.createRawFileStore() 619 try: 620 prx.setFileId(ofile.id.val) 621 prx.truncate(size) # ticket:2337 622 offset = 0 623 while True: 624 block = file.read(block_size) 625 if not block: 626 break 627 prx.write(block, offset, len(block)) 628 offset += len(block) 629 finally: 630 prx.close() 631 finally: 632 file.close() 633 634 return ofile
635
636 - def download(self, ofile, filename = None, block_size = 1024*1024, filehandle = None):
637 prx = self.__sf.createRawFileStore() 638 try: 639 if not ofile or not ofile.id: 640 raise ClientError("No file to download") 641 ofile = self.__sf.getQueryService().get("OriginalFile", ofile.id.val) 642 643 if block_size > ofile.size.val: 644 block_size = ofile.size.val 645 646 prx.setFileId(ofile.id.val) 647 648 size = ofile.size.val 649 offset = 0 650 651 if filehandle is None: 652 if filename is None: 653 raise ClientError("no filename or filehandle specified") 654 filehandle = open(filename, 'wb') 655 else: 656 if filename: 657 raise ClientError("filename and filehandle specified.") 658 659 try: 660 while (offset+block_size) < size: 661 filehandle.write(prx.read(offset, block_size)) 662 offset += block_size 663 filehandle.write(prx.read(offset, (size-offset))) 664 finally: 665 if filename: 666 filehandle.close() 667 finally: 668 prx.close()
669
670 - def getStatefulServices(self):
671 """ 672 Returns all active StatefulServiceInterface proxies. This can 673 be used to call close before calling setSecurityContext. 674 """ 675 rv = [] 676 sf = self.sf 677 services = sf.activeServices() 678 for srv in services: 679 try: 680 prx = sf.getByName(srv) 681 prx = omero.api.StatefulServiceInterfacePrx.checkedCast(prx) 682 if prx is not None: 683 rv.append(prx) 684 except: 685 self.__logger.warn("Error looking up proxy: %s" % srv, exc_info=1) 686 return rv
687
688 - def closeSession(self):
689 """ 690 Closes the Router connection created by createSession(). Due to a bug in Ice, 691 only one connection is allowed per communicator, so we also destroy the communicator. 692 """ 693 694 self.__lock.acquire() 695 try: 696 self.__sf = None 697 698 oldOa = self.__oa 699 self.__oa = None 700 701 oldIc = self.__ic 702 self.__ic = None 703 704 # Only possible if improperly configured. 705 if not oldIc: 706 return 707 708 if oldOa: 709 try: 710 oldOa.deactivate() 711 except exceptions.Exception, e: 712 self.__logger.warning("While deactivating adapter: " + str(e.message)) 713 714 self.__previous = Ice.InitializationData() 715 self.__previous.properties = oldIc.getProperties().clone() 716 717 oldR = self.__resources 718 self.__resources = None 719 if oldR != None: 720 try: 721 oldR.cleanup() 722 except exceptions.Exception, e: 723 oldIc.getLogger().warning( 724 "While cleaning up resources: " + str(e)) 725 726 try: 727 try: 728 self.getRouter(oldIc).destroySession() 729 except Glacier2.SessionNotExistException: 730 # ok. We don't want it to exist 731 pass 732 except Ice.ConnectionLostException: 733 # ok. Exception will always be thrown 734 pass 735 except Ice.ConnectionRefusedException: 736 # ok. Server probably went down 737 pass 738 except Ice.ConnectTimeoutException: 739 # ok. Server probably went down 740 pass 741 # Possible other items to handle/ignore: 742 # * Ice.DNSException 743 finally: 744 oldIc.destroy() 745 del oldIc._impl # WORKAROUND ticket:2007 746 747 finally: 748 self.__lock.release()
749 750
751 - def killSession(self):
752 """ 753 Calls ISession.closeSession(omero.model.Session) until 754 the returned reference count is greater than zero. The 755 number of invocations is returned. If ISession.closeSession() 756 cannot be called, -1 is returned. 757 """ 758 759 s = omero.model.SessionI() 760 s.uuid = omero.rtypes.rstring(self.getSessionId()) 761 try: 762 svc = self.sf.getSessionService() 763 except: 764 self.__logger.warning("Cannot get session service for killSession. Using closeSession") 765 self.closeSession() 766 return -1; 767 768 count = 0 769 try: 770 r = 1 771 while r > 0: 772 count += 1 773 r = svc.closeSession(s) 774 except omero.RemovedSessionException: 775 pass 776 except: 777 self.__logger.warning("Unknown exception while closing all references", exc_info = True) 778 779 # Now the server-side session is dead, call closeSession() 780 self.closeSession() 781 return count
782 783 # Environment Methods 784 # =========================================================== 785
786 - def _env(self, _unwrap, method, *args):
787 """ Helper method to access session environment""" 788 session = self.getSession() 789 if not session: 790 raise ClientError("No session active") 791 a = session.getAdminService() 792 u = a.getEventContext().sessionUuid 793 s = session.getSessionService() 794 m = getattr(s, method) 795 rv = apply(m, (u,)+args) 796 if callable(_unwrap): 797 rv = _unwrap(rv) # Passed in function 798 elif _unwrap: 799 rv = omero.rtypes.unwrap(rv) # Default method 800 return rv
801
802 - def getInput(self, key, unwrap=False):
803 """ 804 Retrieves an item from the "input" shared (session) memory. 805 """ 806 return self._env(unwrap, "getInput", key)
807
808 - def getOutput(self, key, unwrap=False):
809 """ 810 Retrieves an item from the "output" shared (session) memory. 811 """ 812 return self._env(unwrap, "getOutput", key)
813 814
815 - def setInput(self, key, value):
816 """ 817 Sets an item in the "input" shared (session) memory under the given name. 818 """ 819 self._env(False, "setInput", key, value)
820
821 - def setOutput(self, key, value):
822 """ 823 Sets an item in the "output" shared (session) memory under the given name. 824 """ 825 self._env(False, "setOutput", key, value)
826
827 - def getInputKeys(self):
828 """ 829 Returns a list of keys for all items in the "input" shared (session) memory 830 """ 831 return self._env(False, "getInputKeys")
832
833 - def getOutputKeys(self):
834 """ 835 Returns a list of keys for all items in the "output" shared (session) memory 836 """ 837 return self._env(False, "getOutputKeys")
838
839 - def getInputs(self, unwrap=False):
840 """ 841 Returns all items in the "input" shared (session) memory 842 """ 843 return self._env(unwrap, "getInputs")
844
845 - def getOutputs(self, unwrap=False):
846 """ 847 Returns all items in the "output" shared (session) memory 848 """ 849 return self._env(unwrap, "getOutputKeys")
850 # 851 # Misc. 852 # 853
854 - def parseAndSetInt(self, data, key, newValue):
855 currentValue = data.properties.getProperty(key) 856 if not currentValue or len(currentValue) == 0: 857 newStr = str(newValue) 858 data.properties.setProperty(key, newStr) 859 currentValue = newStr 860 return currentValue
861
862 - def __getattr__(self, name):
863 """ 864 Compatibility layer, which allows calls to getCommunicator() and getSession() 865 to be called via self.ic and self.sf 866 """ 867 if name == "ic": 868 return self.getCommunicator() 869 elif name == "sf": 870 return self.getSession() 871 elif name == "adapter": 872 return self.getAdapter() 873 else: 874 raise AttributeError("Unknown property: " + name)
875 876 # 877 # Callback 878 #
879 - def _getCb(self):
880 if not self.__oa: 881 raise ClientError("No session active; call createSession()") 882 obj = self.__oa.find(self.ic.stringToIdentity("ClientCallback/%s" % self.__uuid)) 883 if not isinstance(obj, BaseClient.CallbackI): 884 raise ClientError("Cannot find CallbackI in ObjectAdapter") 885 return obj
886
887 - def onHeartbeat(self, myCallable):
888 self._getCb().onHeartbeat = myCallable
889
890 - def onSessionClosed(self, myCallable):
891 self._getCb().onSessionClosed = myCallable
892
893 - def onShutdownIn(self, myCallable):
894 self._getCb().onShutdownIn = myCallable
895
896 - class CallbackI(omero.api.ClientCallback):
897 """ 898 Implemention of ClientCallback which will be added to 899 any Session which this instance creates. Note: this client 900 should avoid all interaction with the {@link client#lock} since it 901 can lead to deadlocks during shutdown. See: ticket:1210 902 """ 903 904 # 905 # Default callbacks 906 #
907 - def _noop(self):
908 pass
909 - def _closeSession(self):
910 try: 911 self.oa.deactivate(); 912 except exceptions.Exception, e: 913 sys.err.write("On session closed: " + str(e))
914
915 - def __init__(self, ic, oa):
916 self.ic = ic 917 self.oa = oa 918 self.onHeartbeat = self._noop 919 self.onShutdownIn = self._noop 920 self.onSessionClosed = self._noop
921 - def execute(self, myCallable, action):
922 try: 923 myCallable() 924 # self.ic.getLogger().trace("ClientCallback", action + " run") 925 except: 926 try: 927 self.ic.getLogger().error("Error performing %s" % action) 928 except: 929 print "Error performing %s" % action
930
931 - def requestHeartbeat(self, current = None):
932 self.execute(self.onHeartbeat, "heartbeat")
933 - def shutdownIn(self, milliseconds, current = None):
934 self.execute(self.onShutdownIn, "shutdown")
935 - def sessionClosed(self, current = None):
936 self.execute(self.onSessionClosed, "sessionClosed")
937 938 # 939 # Other 940 # 941 942 import util.FactoryMap
943 -class ObjectFactory(Ice.ObjectFactory):
944 """ 945 Responsible for instantiating objects during deserialization. 946 """ 947
948 - def __init__(self, pmap = util.FactoryMap.map()):
949 self.__m = pmap
950
951 - def registerObjectFactory(self, ic):
952 for key in self.__m: 953 if not ic.findObjectFactory(key): 954 ic.addObjectFactory(self,key)
955
956 - def create(self, type):
957 generator = self.__m[type] 958 if generator == None: 959 raise ClientError("Unknown type:"+type) 960 return generator.next()
961
962 - def destroy(self):
963 # Nothing to do 964 pass
965 966 967
968 -class ClientError(exceptions.Exception):
969 """ 970 Top of client exception hierarchy. 971 """ 972 pass
973
974 -class UnloadedEntityException(ClientError):
975 pass
976
977 -class UnloadedCollectionException(ClientError):
978 pass
979