summaryrefslogtreecommitdiff
path: root/py/python/Ice.py
diff options
context:
space:
mode:
Diffstat (limited to 'py/python/Ice.py')
-rw-r--r--py/python/Ice.py1355
1 files changed, 1355 insertions, 0 deletions
diff --git a/py/python/Ice.py b/py/python/Ice.py
new file mode 100644
index 00000000000..2bfb3123004
--- /dev/null
+++ b/py/python/Ice.py
@@ -0,0 +1,1355 @@
+# **********************************************************************
+#
+# Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+#
+# This copy of Ice is licensed to you under the terms described in the
+# ICE_LICENSE file included in this distribution.
+#
+# **********************************************************************
+
+"""
+Ice module
+"""
+
+import sys, exceptions, string, imp, os, threading, warnings, datetime
+
+#
+# RTTI problems can occur in C++ code unless we modify Python's dlopen flags.
+# Note that changing these flags might cause problems for other extensions
+# loaded by the application (see bug 3660), so we restore the original settings
+# after loading IcePy.
+#
+_dlopenflags = -1
+try:
+ _dlopenflags = sys.getdlopenflags()
+
+ try:
+ import dl
+ sys.setdlopenflags(dl.RTLD_NOW|dl.RTLD_GLOBAL)
+ except ImportError:
+ #
+ # If the dl module is not available and we're running on a Linux
+ # platform, use the hard coded value of RTLD_NOW|RTLD_GLOBAL.
+ #
+ if sys.platform.startswith("linux"):
+ sys.setdlopenflags(258)
+ pass
+
+except AttributeError:
+ #
+ # sys.getdlopenflags() is not supported (we're probably running on Windows).
+ #
+ pass
+
+#
+# Import the Python extension.
+#
+import IcePy
+
+#
+# Restore the dlopen flags.
+#
+if _dlopenflags >= 0:
+ sys.setdlopenflags(_dlopenflags)
+
+#
+# Add some symbols to the Ice module.
+#
+ObjectPrx = IcePy.ObjectPrx
+stringVersion = IcePy.stringVersion
+intVersion = IcePy.intVersion
+generateUUID = IcePy.generateUUID
+loadSlice = IcePy.loadSlice
+AsyncResult = IcePy.AsyncResult
+
+#
+# This value is used as the default value for struct types in the constructors
+# of user-defined types. It allows us to determine whether the application has
+# supplied a value. (See bug 3676)
+#
+_struct_marker = object()
+
+#
+# Core Ice types.
+#
+class Object(object):
+ def ice_isA(self, id, current=None):
+ '''Determines whether the target object supports the interface denoted
+by the given Slice type id.
+Arguments:
+ id The Slice type id
+Returns:
+ True if the target object supports the interface, or false otherwise.
+'''
+ return id in self.ice_ids(current)
+
+ def ice_ping(self, current=None):
+ '''A reachability test for the target object.'''
+ pass
+
+ def ice_ids(self, current=None):
+ '''Obtains the type ids corresponding to the Slice interface
+that are supported by the target object.
+Returns:
+ A list of type ids.
+'''
+ return [ self.ice_id(current) ]
+
+ def ice_id(self, current=None):
+ '''Obtains the type id corresponding to the most-derived Slice
+interface supported by the target object.
+Returns:
+ The type id.
+'''
+ return '::Ice::Object'
+
+ def ice_staticId():
+ '''Obtains the type id of this Slice class or interface.
+Returns:
+ The type id.
+'''
+ return '::Ice::Object'
+ ice_staticId = staticmethod(ice_staticId)
+
+ #
+ # Do not define these here. They will be invoked if defined by a subclass.
+ #
+ #def ice_preMarshal(self):
+ # pass
+ #
+ #def ice_postUnmarshal(self):
+ # pass
+
+#
+# LocalObject is deprecated; use the Python base 'object' type instead.
+#
+class LocalObject(object):
+ pass
+
+class Blobject(Object):
+ '''Special-purpose servant base class that allows a subclass to
+handle synchronous Ice invocations as "blobs" of bytes.'''
+
+ def ice_invoke(self, bytes, current):
+ '''Dispatch a synchronous Ice invocation. The operation's
+arguments are encoded in the bytes argument. The return
+value must be a tuple of two values: the first is a
+boolean indicating whether the operation succeeded (True)
+or raised a user exception (False), and the second is
+the encoded form of the operation's results or the user
+exception.
+'''
+ pass
+
+class BlobjectAsync(Object):
+ '''Special-purpose servant base class that allows a subclass to
+handle asynchronous Ice invocations as "blobs" of bytes.'''
+
+ def ice_invoke_async(self, cb, bytes, current):
+ '''Dispatch an asynchronous Ice invocation. The operation's
+arguments are encoded in the bytes argument. When the
+dispatch is complete, the subclass can invoke either
+ice_response or ice_exception on the supplied callback
+object.
+'''
+ pass
+
+#
+# Exceptions.
+#
+class Exception(exceptions.Exception):
+ '''The base class for all Ice exceptions.'''
+ def __str__(self):
+ return self.__class__.__name__
+
+ def ice_name(self):
+ '''Returns the type name of this exception.'''
+ return self._ice_name
+
+class LocalException(Exception):
+ '''The base class for all Ice run-time exceptions.'''
+ def __init__(self, args=''):
+ self.args = args
+
+class UserException(Exception):
+ '''The base class for all user-defined exceptions.'''
+ pass
+
+def getSliceDir():
+ '''Convenience function for locating the directory containing the Slice files.'''
+
+ #
+ # Get the parent of the directory containing this file (Ice.py).
+ #
+ pyHome = os.path.join(os.path.dirname(__file__), "..")
+
+ #
+ # For an installation from a source distribution, a binary tarball, or a
+ # Windows installer, the "slice" directory is a sibling of the "python"
+ # directory.
+ #
+ dir = os.path.join(pyHome, "slice")
+ if os.path.exists(dir):
+ return os.path.normpath(dir)
+
+ #
+ # In a source distribution, the "slice" directory is one level higher.
+ #
+ dir = os.path.join(pyHome, "..", "slice")
+ if os.path.exists(dir):
+ return os.path.normpath(dir)
+
+ iceVer = stringVersion()
+
+ if sys.platform[:5] == "linux":
+ #
+ # Check the default RPM location.
+ #
+ dir = os.path.join("/", "usr", "share", "Ice-" + iceVer, "slice")
+ if os.path.exists(dir):
+ return dir
+
+ return None
+
+#
+# Utilities for use by generated code.
+#
+
+_pendingModules = {}
+
+def openModule(name):
+ if sys.modules.has_key(name):
+ result = sys.modules[name]
+ elif _pendingModules.has_key(name):
+ result = _pendingModules[name]
+ else:
+ result = createModule(name)
+
+ return result
+
+def createModule(name):
+ l = string.split(name, ".")
+ curr = ''
+ mod = None
+
+ for s in l:
+ curr = curr + s
+
+ if sys.modules.has_key(curr):
+ mod = sys.modules[curr]
+ elif _pendingModules.has_key(curr):
+ mod = _pendingModules[curr]
+ else:
+ nmod = imp.new_module(curr)
+ _pendingModules[curr] = nmod
+ mod = nmod
+
+ curr = curr + "."
+
+ return mod
+
+def updateModule(name):
+ if _pendingModules.has_key(name):
+ pendingModule = _pendingModules[name]
+ mod = sys.modules[name]
+ mod.__dict__.update(pendingModule.__dict__)
+ del _pendingModules[name]
+
+def updateModules():
+ for name in _pendingModules.keys():
+ if sys.modules.has_key(name):
+ sys.modules[name].__dict__.update(_pendingModules[name].__dict__)
+ else:
+ sys.modules[name] = _pendingModules[name]
+ del _pendingModules[name]
+
+def createTempClass():
+ class __temp: pass
+ return __temp
+
+#
+# Forward declarations.
+#
+IcePy._t_Object = IcePy.declareClass('::Ice::Object')
+IcePy._t_ObjectPrx = IcePy.declareProxy('::Ice::Object')
+IcePy._t_LocalObject = IcePy.declareClass('::Ice::LocalObject')
+
+#
+# Sequence mappings.
+#
+IcePy.SEQ_DEFAULT = 0
+IcePy.SEQ_TUPLE = 1
+IcePy.SEQ_LIST = 2
+#IcePy.SEQ_ARRAY = 3
+
+#
+# Slice checksum dictionary.
+#
+sliceChecksums = {}
+
+#
+# Import generated Ice modules.
+#
+import Ice_BuiltinSequences_ice
+import Ice_Communicator_ice
+import Ice_Current_ice
+import Ice_ImplicitContext_ice
+import Ice_Endpoint_ice
+import Ice_EndpointTypes_ice
+import Ice_Identity_ice
+import Ice_LocalException_ice
+import Ice_Locator_ice
+import Ice_Logger_ice
+import Ice_ObjectAdapter_ice
+import Ice_ObjectFactory_ice
+import Ice_Properties_ice
+import Ice_Router_ice
+import Ice_ServantLocator_ice
+import Ice_Connection_ice
+
+#
+# Replace EndpointInfo with our implementation.
+#
+del EndpointInfo
+EndpointInfo = IcePy.EndpointInfo
+del IPEndpointInfo
+IPEndpointInfo = IcePy.IPEndpointInfo
+del TCPEndpointInfo
+TCPEndpointInfo = IcePy.TCPEndpointInfo
+del UDPEndpointInfo
+UDPEndpointInfo = IcePy.UDPEndpointInfo
+del OpaqueEndpointInfo
+OpaqueEndpointInfo = IcePy.OpaqueEndpointInfo
+
+#
+# Replace ConnectionInfo with our implementation.
+#
+del ConnectionInfo
+ConnectionInfo = IcePy.ConnectionInfo
+del IPConnectionInfo
+IPConnectionInfo = IcePy.IPConnectionInfo
+del TCPConnectionInfo
+TCPConnectionInfo = IcePy.TCPConnectionInfo
+del UDPConnectionInfo
+UDPConnectionInfo = IcePy.UDPConnectionInfo
+
+class ThreadNotification(object):
+ '''Base class for thread notification callbacks. A subclass must
+define the start and stop methods.'''
+
+ def __init__(self):
+ pass
+
+ def start():
+ '''Invoked in the context of a thread created by the Ice run time.'''
+ pass
+
+ def stop():
+ '''Invoked in the context of an Ice run-time thread that is about
+to terminate.'''
+ pass
+
+#
+# Initialization data.
+#
+class InitializationData(object):
+ '''The attributes of this class are used to initialize a new
+communicator instance. The supported attributes are as follows:
+
+properties: An instance of Ice.Properties. You can use the
+ Ice.createProperties function to create a new property set.
+
+logger: An instance of Ice.Logger.
+
+threadHook: An object that implements ThreadNotification.
+'''
+ def __init__(self):
+ self.properties = None
+ self.logger = None
+ #self.stats = None # Stats not currently supported in Python.
+ self.threadHook = None
+
+#
+# Communicator wrapper.
+#
+class CommunicatorI(Communicator):
+ def __init__(self, impl):
+ self._impl = impl
+ impl._setWrapper(self)
+
+ def destroy(self):
+ self._impl.destroy()
+
+ def shutdown(self):
+ self._impl.shutdown()
+
+ def waitForShutdown(self):
+ #
+ # If invoked by the main thread, waitForShutdown only blocks for
+ # the specified timeout in order to give us a chance to handle
+ # signals.
+ #
+ while not self._impl.waitForShutdown(500):
+ pass
+
+ def isShutdown(self):
+ return self._impl.isShutdown()
+
+ def stringToProxy(self, str):
+ return self._impl.stringToProxy(str)
+
+ def proxyToString(self, obj):
+ return self._impl.proxyToString(obj)
+
+ def propertyToProxy(self, str):
+ return self._impl.propertyToProxy(str)
+
+ def proxyToProperty(self, obj, str):
+ return self._impl.proxyToProperty(obj, str)
+
+ def stringToIdentity(self, str):
+ return self._impl.stringToIdentity(str)
+
+ def identityToString(self, ident):
+ return self._impl.identityToString(ident)
+
+ def createObjectAdapter(self, name):
+ adapter = self._impl.createObjectAdapter(name)
+ return ObjectAdapterI(adapter)
+
+ def createObjectAdapterWithEndpoints(self, name, endpoints):
+ adapter = self._impl.createObjectAdapterWithEndpoints(name, endpoints)
+ return ObjectAdapterI(adapter)
+
+ def createObjectAdapterWithRouter(self, name, router):
+ adapter = self._impl.createObjectAdapterWithRouter(name, router)
+ return ObjectAdapterI(adapter)
+
+ def addObjectFactory(self, factory, id):
+ self._impl.addObjectFactory(factory, id)
+
+ def findObjectFactory(self, id):
+ return self._impl.findObjectFactory(id)
+
+ def getImplicitContext(self):
+ context = self._impl.getImplicitContext()
+ if context == None:
+ return None;
+ else:
+ return ImplicitContextI(context)
+
+ def getProperties(self):
+ properties = self._impl.getProperties()
+ return PropertiesI(properties)
+
+ def getLogger(self):
+ logger = self._impl.getLogger()
+ if isinstance(logger, Logger):
+ return logger
+ else:
+ return LoggerI(logger)
+
+ def getStats(self):
+ raise RuntimeError("operation `getStats' not implemented")
+
+ def getDefaultRouter(self):
+ return self._impl.getDefaultRouter()
+
+ def setDefaultRouter(self, rtr):
+ self._impl.setDefaultRouter(rtr)
+
+ def getDefaultLocator(self):
+ return self._impl.getDefaultLocator()
+
+ def setDefaultLocator(self, loc):
+ self._impl.setDefaultLocator(loc)
+
+ def getPluginManager(self):
+ raise RuntimeError("operation `getPluginManager' not implemented")
+
+ def flushBatchRequests(self):
+ self._impl.flushBatchRequests()
+
+ def begin_flushBatchRequests(self, _ex=None, _sent=None):
+ return self._impl.begin_flushBatchRequests(_ex, _sent)
+
+ def end_flushBatchRequests(self, r):
+ return self._impl.end_flushBatchRequests(r)
+
+ def getAdmin(self):
+ return self._impl.getAdmin()
+
+ def addAdminFacet(self, servant, facet):
+ self._impl.addAdminFacet(servant, facet)
+
+ def removeAdminFacet(self, facet):
+ return self._impl.removeAdminFacet(facet)
+
+#
+# Ice.initialize()
+#
+def initialize(args=None, data=None):
+ '''Initializes a new communicator. The optional arguments represent
+an argument list (such as sys.argv) and an instance of InitializationData.
+You can invoke this function as follows:
+
+Ice.initialize()
+Ice.initialize(args)
+Ice.initialize(data)
+Ice.initialize(args, data)
+
+If you supply an argument list, the function removes those arguments from
+the list that were recognized by the Ice run time.
+'''
+ communicator = IcePy.Communicator(args, data)
+ return CommunicatorI(communicator)
+
+#
+# ObjectAdapter wrapper.
+#
+class ObjectAdapterI(ObjectAdapter):
+ def __init__(self, impl):
+ self._impl = impl
+
+ def getName(self):
+ return self._impl.getName()
+
+ def getCommunicator(self):
+ communicator = self._impl.getCommunicator()
+ return communicator._getWrapper()
+
+ def activate(self):
+ self._impl.activate()
+
+ def hold(self):
+ self._impl.hold()
+
+ def waitForHold(self):
+ #
+ # If invoked by the main thread, waitForHold only blocks for
+ # the specified timeout in order to give us a chance to handle
+ # signals.
+ #
+ while not self._impl.waitForHold(1000):
+ pass
+
+ def deactivate(self):
+ self._impl.deactivate()
+
+ def waitForDeactivate(self):
+ #
+ # If invoked by the main thread, waitForDeactivate only blocks for
+ # the specified timeout in order to give us a chance to handle
+ # signals.
+ #
+ while not self._impl.waitForDeactivate(1000):
+ pass
+
+ def isDeactivated(self):
+ self._impl.isDeactivated()
+
+ def destroy(self):
+ self._impl.destroy()
+
+ def add(self, servant, id):
+ return self._impl.add(servant, id)
+
+ def addFacet(self, servant, id, facet):
+ return self._impl.addFacet(servant, id, facet)
+
+ def addWithUUID(self, servant):
+ return self._impl.addWithUUID(servant)
+
+ def addFacetWithUUID(self, servant, facet):
+ return self._impl.addFacetWIthUUID(servant, facet)
+
+ def addDefaultServant(self, servant, category):
+ self._impl.addDefaultServant(servant, category)
+
+ def remove(self, id):
+ return self._impl.remove(id)
+
+ def removeFacet(self, id, facet):
+ return self._impl.removeFacet(id, facet)
+
+ def removeAllFacets(self, id):
+ return self._impl.removeAllFacets(id)
+
+ def removeDefaultServant(self, category):
+ return self._impl.removeDefaultServant(category)
+
+ def find(self, id):
+ return self._impl.find(id)
+
+ def findFacet(self, id, facet):
+ return self._impl.findFacet(id, facet)
+
+ def findAllFacets(self, id):
+ return self._impl.findAllFacets(id)
+
+ def findByProxy(self, proxy):
+ return self._impl.findByProxy(proxy)
+
+ def findDefaultServant(self, category):
+ return self._impl.findDefaultServant(category)
+
+ def addServantLocator(self, locator, category):
+ self._impl.addServantLocator(locator, category)
+
+ def removeServantLocator(self, category):
+ return self._impl.removeServantLocator(category)
+
+ def findServantLocator(self, category):
+ return self._impl.findServantLocator(category)
+
+ def createProxy(self, id):
+ return self._impl.createProxy(id)
+
+ def createDirectProxy(self, id):
+ return self._impl.createDirectProxy(id)
+
+ def createIndirectProxy(self, id):
+ return self._impl.createIndirectProxy(id)
+
+ def createReverseProxy(self, id):
+ return self._impl.createReverseProxy(id)
+
+ def setLocator(self, loc):
+ self._impl.setLocator(loc)
+
+ def refreshPublishedEndpoints(self):
+ self._impl.refreshPublishedEndpoints()
+
+ def getEndpoints(self):
+ return self._impl.getEndpoints()
+
+ def getPublishedEndpoints(self):
+ return self._impl.getPublishedEndpoints()
+
+#
+# Logger wrapper.
+#
+class LoggerI(Logger):
+ def __init__(self, impl):
+ self._impl = impl
+
+ def _print(self, message):
+ return self._impl._print(message)
+
+ def trace(self, category, message):
+ return self._impl.trace(category, message)
+
+ def warning(self, message):
+ return self._impl.warning(message)
+
+ def error(self, message):
+ return self._impl.error(message)
+
+ def cloneWithPrefix(self, prefix):
+ logger = self._impl.cloneWithPrefix(prefix)
+ return LoggerI(logger)
+
+#
+# Properties wrapper.
+#
+class PropertiesI(Properties):
+ def __init__(self, impl):
+ self._impl = impl
+
+ def getProperty(self, key):
+ return self._impl.getProperty(key)
+
+ def getPropertyWithDefault(self, key, value):
+ return self._impl.getPropertyWithDefault(key, value)
+
+ def getPropertyAsInt(self, key):
+ return self._impl.getPropertyAsInt(key)
+
+ def getPropertyAsIntWithDefault(self, key, value):
+ return self._impl.getPropertyAsIntWithDefault(key, value)
+
+ def getPropertyAsList(self, key):
+ return self._impl.getPropertyAsList(key)
+
+ def getPropertyAsListWithDefault(self, key, value):
+ return self._impl.getPropertyAsListWithDefault(key, value)
+
+ def getPropertiesForPrefix(self, prefix):
+ return self._impl.getPropertiesForPrefix(prefix)
+
+ def setProperty(self, key, value):
+ self._impl.setProperty(key, value)
+
+ def getCommandLineOptions(self):
+ return self._impl.getCommandLineOptions()
+
+ def parseCommandLineOptions(self, prefix, options):
+ return self._impl.parseCommandLineOptions(prefix, options)
+
+ def parseIceCommandLineOptions(self, options):
+ return self._impl.parseIceCommandLineOptions(options)
+
+ def load(self, file):
+ self._impl.load(file)
+
+ def clone(self):
+ properties = self._impl.clone()
+ return PropertiesI(properties)
+
+ def __iter__(self):
+ dict = self._impl.getPropertiesForPrefix('')
+ return iter(dict)
+
+ def __str__(self):
+ return str(self._impl)
+
+#
+# Ice.createProperties()
+#
+def createProperties(args=None, defaults=None):
+ '''Creates a new property set. The optional arguments represent
+an argument list (such as sys.argv) and a property set that supplies
+default values. You can invoke this function as follows:
+
+Ice.createProperties()
+Ice.createProperties(args)
+Ice.createProperties(defaults)
+Ice.createProperties(args, defaults)
+
+If you supply an argument list, the function removes those arguments
+from the list that were recognized by the Ice run time.
+'''
+
+ properties = IcePy.createProperties(args, defaults)
+ return PropertiesI(properties)
+
+#
+# Ice.getProcessLogger()
+# Ice.setProcessLogger()
+#
+def getProcessLogger():
+ '''Returns the default logger object.'''
+ logger = IcePy.getProcessLogger()
+ if isinstance(logger, Logger):
+ return logger
+ else:
+ return LoggerI(logger)
+
+def setProcessLogger(logger):
+ '''Sets the default logger object.'''
+ IcePy.setProcessLogger(logger)
+
+#
+# ImplicitContext wrapper
+#
+class ImplicitContextI(ImplicitContext):
+ def __init__(self, impl):
+ self._impl = impl
+
+ def setContext(self, ctx):
+ self._impl.setContext(ctx)
+
+ def getContext(self):
+ return self._impl.getContext()
+
+ def containsKey(self, key):
+ return self._impl.containsKey(key)
+
+ def get(self, key):
+ return self._impl.get(key)
+
+ def put(self, key, value):
+ return self._impl.put(key, value)
+
+ def remove(self, key):
+ return self._impl.remove(key)
+
+
+#
+# Its not possible to block in a python signal handler since this
+# blocks the main thread from doing further work. As such we queue the
+# signal with a worker thread which then "dispatches" the signal to
+# the registered callback object.
+#
+# Note the interface is the same as the C++ CtrlCHandler
+# implementation, however, the implementation is different.
+#
+class CtrlCHandler(threading.Thread):
+ # Class variable referring to the one and only handler for use
+ # from the signal handling callback.
+ _self = None
+
+ def __init__(self):
+ threading.Thread.__init__(self)
+
+ if CtrlCHandler._self != None:
+ raise RuntimeError("Only a single instance of a CtrlCHandler can be instantiated.")
+ CtrlCHandler._self = self
+
+ # State variables. These are not class static variables.
+ self._condVar = threading.Condition()
+ self._queue = []
+ self._done = False
+ self._callback = None
+
+ #
+ # Setup and install signal handlers
+ #
+ if signal.__dict__.has_key('SIGHUP'):
+ signal.signal(signal.SIGHUP, CtrlCHandler.signalHandler)
+ if signal.__dict__.has_key('SIGBREAK'):
+ signal.signal(signal.SIGBREAK, CtrlCHandler.signalHandler)
+ signal.signal(signal.SIGINT, CtrlCHandler.signalHandler)
+ signal.signal(signal.SIGTERM, CtrlCHandler.signalHandler)
+
+ # Start the thread once everything else is done.
+ self.start()
+
+ # Dequeue and dispatch signals.
+ def run(self):
+ while True:
+ self._condVar.acquire()
+ while len(self._queue) == 0 and not self._done:
+ self._condVar.wait()
+ if self._done:
+ self._condVar.release()
+ break
+ sig, callback = self._queue.pop()
+ self._condVar.release()
+ if callback:
+ callback(sig)
+
+ # Destroy the object. Wait for the thread to terminate and cleanup
+ # the internal state.
+ def destroy(self):
+ self._condVar.acquire()
+ self._done = True
+ self._condVar.notify()
+ self._condVar.release()
+
+ # Wait for the thread to terminate
+ self.join()
+ #
+ # Cleanup any state set by the CtrlCHandler.
+ #
+ if signal.__dict__.has_key('SIGHUP'):
+ signal.signal(signal.SIGHUP, signal.SIG_DFL)
+ if signal.__dict__.has_key('SIGBREAK'):
+ signal.signal(signal.SIGBREAK, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGTERM, signal.SIG_DFL)
+ CtrlCHandler._self = None
+
+ def setCallback(self, callback):
+ self._condVar.acquire()
+ self._callback = callback
+ self._condVar.release()
+
+ def getCallback(self):
+ self._condVar.acquire()
+ callback = self._callback
+ self._condVar.release()
+ return callback
+
+ # Private. Only called by the signal handling mechanism.
+ def signalHandler(self, sig, frame):
+ self._self._condVar.acquire()
+ #
+ # The signal AND the current callback are queued together.
+ #
+ self._self._queue.append([sig, self._self._callback])
+ self._self._condVar.notify()
+ self._self._condVar.release()
+ signalHandler = classmethod(signalHandler)
+
+#
+# Application logger.
+#
+class _ApplicationLoggerI(Logger):
+ def __init__(self, prefix):
+ if len(prefix) > 0:
+ self._prefix = prefix + ": "
+ else:
+ self._prefix = ""
+ self._outputMutex = threading.Lock()
+
+ def _print(self, message):
+ s = "[ " + str(datetime.datetime.now()) + " " + self._prefix
+ self._outputMutex.acquire()
+ sys.stderr.write(message + "\n")
+ self._outputMutex.release()
+
+ def trace(self, category, message):
+ s = "[ " + str(datetime.datetime.now()) + " " + self._prefix
+ if len(category) > 0:
+ s += category + ": "
+ s += message + " ]"
+
+ s = s.replace("\n", "\n ")
+
+ self._outputMutex.acquire()
+ sys.stderr.write(s + "\n")
+ self._outputMutex.release()
+
+ def warning(self, message):
+ self._outputMutex.acquire()
+ sys.stderr.write(str(datetime.datetime.now()) + " " + self._prefix + "warning: " + message + "\n")
+ self._outputMutex.release()
+
+ def error(self, message):
+ self._outputMutex.acquire()
+ sys.stderr.write(str(datetime.datetime.now()) + " " + self._prefix + "error: " + message + "\n")
+ self._outputMutex.release()
+
+#
+# Application class.
+#
+import signal, traceback
+class Application(object):
+ '''Convenience class that initializes a communicator and reacts
+gracefully to signals. An application must define a subclass
+of this class and supply an implementation of the run method.
+'''
+
+ def __init__(self, signalPolicy=0): # HandleSignals=0
+ '''The constructor accepts an optional argument indicating
+whether to handle signals. The value should be either
+Application.HandleSignals (the default) or
+Application.NoSignalHandling.
+'''
+ if type(self) == Application:
+ raise RuntimeError("Ice.Application is an abstract class")
+ Application._signalPolicy = signalPolicy
+
+ def main(self, args, configFile=None, initData=None):
+ '''The main entry point for the Application class. The arguments
+are an argument list (such as sys.argv), the name of an Ice
+configuration file (optional), and an instance of
+InitializationData (optional). This method does not return
+until after the completion of the run method. The return
+value is an integer representing the exit status.
+'''
+
+ if Application._communicator:
+ getProcessLogger().error(args[0] + ": only one instance of the Application class can be used")
+ return 1
+
+ #
+ # We parse the properties here to extract Ice.ProgramName.
+ #
+ if not initData:
+ initData = InitializationData()
+ if configFile:
+ try:
+ initData.properties = createProperties(None, initData.properties)
+ initData.properties.load(configFile)
+ except:
+ getProcessLogger().error(traceback.format_exc())
+ return 1
+ initData.properties = createProperties(args, initData.properties)
+
+ #
+ # If the process logger is the default logger, we replace it with a
+ # a logger which is using the program name for the prefix.
+ #
+ if isinstance(getProcessLogger(), LoggerI):
+ setProcessLogger(_ApplicationLoggerI(initData.properties.getProperty("Ice.ProgramName")))
+
+ #
+ # Install our handler for the signals we are interested in. We assume main()
+ # is called from the main thread.
+ #
+ Application._ctrlCHandler = CtrlCHandler()
+
+ try:
+ status = 0
+
+ Application._interrupted = False
+ Application._appName = initData.properties.getPropertyWithDefault("Ice.ProgramName", args[0])
+ Application._application = self
+ Application._communicator = initialize(args, initData)
+ Application._destroyed = False
+
+ #
+ # Used by _destroyOnInterruptCallback and _shutdownOnInterruptCallback.
+ #
+ Application._nohup = Application._communicator.getProperties().getPropertyAsInt("Ice.Nohup") > 0
+
+ #
+ # The default is to destroy when a signal is received.
+ #
+ if Application._signalPolicy == Application.HandleSignals:
+ Application.destroyOnInterrupt()
+
+ status = self.doMain(args, initData)
+ except:
+ getProcessLogger().error(traceback.format_exc())
+ status = 1
+
+ #
+ # Don't want any new interrupt and at this point (post-run),
+ # it would not make sense to release a held signal to run
+ # shutdown or destroy.
+ #
+ if Application._signalPolicy == Application.HandleSignals:
+ Application.ignoreInterrupt()
+
+ Application._condVar.acquire()
+ while Application._callbackInProgress:
+ Application._condVar.wait()
+ if Application._destroyed:
+ Application._communicator = None
+ else:
+ Application._destroyed = True
+ #
+ # And _communicator != 0, meaning will be destroyed
+ # next, _destroyed = true also ensures that any
+ # remaining callback won't do anything
+ #
+ Application._application = None
+ Application._condVar.release()
+
+ if Application._communicator:
+ try:
+ Application._communicator.destroy()
+ except:
+ getProcessLogger().error(traceback.format_exc())
+ status = 1
+
+ Application._communicator = None
+
+ #
+ # Set _ctrlCHandler to 0 only once communicator.destroy() has
+ # completed.
+ #
+ Application._ctrlCHandler.destroy()
+ Application._ctrlCHandler = None
+
+ return status
+
+ def doMain(self, args, initData):
+ return self.run(args)
+
+ def run(self, args):
+ '''This method must be overridden in a subclass. The base
+class supplies an argument list from which all Ice arguments
+have already been removed. The method returns an integer
+exit status (0 is success, non-zero is failure).
+'''
+ raise RuntimeError('run() not implemented')
+
+ def interruptCallback(self, sig):
+ '''Subclass hook to intercept an interrupt.'''
+ pass
+
+ def appName(self):
+ '''Returns the application name (the first element of
+the argument list).'''
+ return self._appName
+ appName = classmethod(appName)
+
+ def communicator(self):
+ '''Returns the communicator that was initialized for
+the application.'''
+ return self._communicator
+ communicator = classmethod(communicator)
+
+ def destroyOnInterrupt(self):
+ '''Configures the application to destroy its communicator
+when interrupted by a signal.'''
+ if Application._signalPolicy == Application.HandleSignals:
+ self._condVar.acquire()
+ if self._ctrlCHandler.getCallback() == self._holdInterruptCallback:
+ self._released = True
+ self._condVar.notify()
+ self._ctrlCHandler.setCallback(self._destroyOnInterruptCallback)
+ self._condVar.release()
+ else:
+ getProcessLogger().error(Application._appName + \
+ ": warning: interrupt method called on Application configured to not handle interrupts.")
+ destroyOnInterrupt = classmethod(destroyOnInterrupt)
+
+ def shutdownOnInterrupt(self):
+ '''Configures the application to shutdown its communicator
+when interrupted by a signal.'''
+ if Application._signalPolicy == Application.HandleSignals:
+ self._condVar.acquire()
+ if self._ctrlCHandler.getCallback() == self._holdInterruptCallback:
+ self._released = True
+ self._condVar.notify()
+ self._ctrlCHandler.setCallback(self._shutdownOnInterruptCallback)
+ self._condVar.release()
+ else:
+ getProcessLogger().error(Application._appName + \
+ ": warning: interrupt method called on Application configured to not handle interrupts.")
+ shutdownOnInterrupt = classmethod(shutdownOnInterrupt)
+
+ def ignoreInterrupt(self):
+ '''Configures the application to ignore signals.'''
+ if Application._signalPolicy == Application.HandleSignals:
+ self._condVar.acquire()
+ if self._ctrlCHandler.getCallback() == self._holdInterruptCallback:
+ self._released = True
+ self._condVar.notify()
+ self._ctrlCHandler.setCallback(None)
+ self._condVar.release()
+ else:
+ getProcessLogger().error(Application._appName + \
+ ": warning: interrupt method called on Application configured to not handle interrupts.")
+ ignoreInterrupt = classmethod(ignoreInterrupt)
+
+ def callbackOnInterrupt(self):
+ '''Configures the application to invoke interruptCallback
+when interrupted by a signal.'''
+ if Application._signalPolicy == Application.HandleSignals:
+ self._condVar.acquire()
+ if self._ctrlCHandler.getCallback() == self._holdInterruptCallback:
+ self._released = True
+ self._condVar.notify()
+ self._ctrlCHandler.setCallback(self._callbackOnInterruptCallback)
+ self._condVar.release()
+ else:
+ getProcessLogger().error(Application._appName + \
+ ": warning: interrupt method called on Application configured to not handle interrupts.")
+ callbackOnInterrupt = classmethod(callbackOnInterrupt)
+
+ def holdInterrupt(self):
+ '''Configures the application to queue an interrupt for
+later processing.'''
+ if Application._signalPolicy == Application.HandleSignals:
+ self._condVar.acquire()
+ if self._ctrlCHandler.getCallback() != self._holdInterruptCallback:
+ self._previousCallback = self._ctrlCHandler.getCallback()
+ self._released = False
+ self._ctrlCHandler.setCallback(self._holdInterruptCallback)
+ # else, we were already holding signals
+ self._condVar.release()
+ else:
+ getProcessLogger().error(Application._appName + \
+ ": warning: interrupt method called on Application configured to not handle interrupts.")
+ holdInterrupt = classmethod(holdInterrupt)
+
+ def releaseInterrupt(self):
+ '''Instructs the application to process any queued interrupt.'''
+ if Application._signalPolicy == Application.HandleSignals:
+ self._condVar.acquire()
+ if self._ctrlCHandler.getCallback() == self._holdInterruptCallback:
+ #
+ # Note that it's very possible no signal is held;
+ # in this case the callback is just replaced and
+ # setting _released to true and signalling _condVar
+ # do no harm.
+ #
+ self._released = True
+ self._ctrlCHandler.setCallback(self._previousCallback)
+ self._condVar.notify()
+ # Else nothing to release.
+ self._condVar.release()
+ else:
+ getProcessLogger().error(Application._appName + \
+ ": warning: interrupt method called on Application configured to not handle interrupts.")
+ releaseInterrupt = classmethod(releaseInterrupt)
+
+ def interrupted(self):
+ '''Returns True if the application was interrupted by a
+signal, or False otherwise.'''
+ self._condVar.acquire()
+ result = self._interrupted
+ self._condVar.release()
+ return result
+ interrupted = classmethod(interrupted)
+
+ def _holdInterruptCallback(self, sig):
+ self._condVar.acquire()
+ while not self._released:
+ self._condVar.wait()
+ if self._destroyed:
+ #
+ # Being destroyed by main thread
+ #
+ self._condVar.release()
+ return
+ callback = self._ctrlCHandler.getCallback()
+ self._condVar.release()
+ if callback:
+ callback(sig)
+ _holdInterruptCallback = classmethod(_holdInterruptCallback)
+
+ def _destroyOnInterruptCallback(self, sig):
+ self._condVar.acquire()
+ if self._destroyed or self._nohup and sig == signal.SIGHUP:
+ #
+ # Being destroyed by main thread, or nohup.
+ #
+ self._condVar.release()
+ return
+
+ self._callbackInProcess = True
+ self._interrupted = True
+ self._destroyed = True
+ self._condVar.release()
+
+ try:
+ self._communicator.destroy()
+ except:
+ getProcessLogger().error(self._appName + " (while destroying in response to signal " + str(sig) + "):" + \
+ traceback.format_exc())
+
+ self._condVar.acquire()
+ self._callbackInProcess = False
+ self._condVar.notify()
+ self._condVar.release()
+ _destroyOnInterruptCallback = classmethod(_destroyOnInterruptCallback)
+
+ def _shutdownOnInterruptCallback(self, sig):
+ self._condVar.acquire()
+ if self._destroyed or self._nohup and sig == signal.SIGHUP:
+ #
+ # Being destroyed by main thread, or nohup.
+ #
+ self._condVar.release()
+ return
+
+ self._callbackInProcess = True
+ self._interrupted = True
+ self._condVar.release()
+
+ try:
+ self._communicator.shutdown()
+ except:
+ getProcessLogger().error(self._appName + " (while shutting down in response to signal " + str(sig) + \
+ "):" + traceback.format_exc())
+
+ self._condVar.acquire()
+ self._callbackInProcess = False
+ self._condVar.notify()
+ self._condVar.release()
+ _shutdownOnInterruptCallback = classmethod(_shutdownOnInterruptCallback)
+
+ def _callbackOnInterruptCallback(self, sig):
+ self._condVar.acquire()
+ if self._destroyed:
+ #
+ # Being destroyed by main thread.
+ #
+ self._condVar.release()
+ return
+ # For SIGHUP the user callback is always called. It can decide
+ # what to do.
+
+ self._callbackInProcess = True
+ self._interrupted = True
+ self._condVar.release()
+
+ try:
+ self._application.interruptCallback(sig)
+ except:
+ getProcessLogger().error(self._appName + " (while interrupting in response to signal " + str(sig) + \
+ "):" + traceback.format_exc())
+
+ self._condVar.acquire()
+ self._callbackInProcess = False
+ self._condVar.notify()
+ self._condVar.release()
+
+ _callbackOnInterruptCallback = classmethod(_callbackOnInterruptCallback)
+
+ HandleSignals = 0
+ NoSignalHandling = 1
+
+ _appName = None
+ _communicator = None
+ _application = None
+ _ctrlCHandler = None
+ _previousCallback = None
+ _interrupted = False
+ _released = False
+ _destroyed = False
+ _callbackInProgress = False
+ _condVar = threading.Condition()
+ _signalPolicy = HandleSignals
+
+#
+# Define Ice::Object and Ice::ObjectPrx.
+#
+IcePy._t_Object = IcePy.defineClass('::Ice::Object', Object, (), False, None, (), ())
+IcePy._t_ObjectPrx = IcePy.defineProxy('::Ice::Object', ObjectPrx)
+Object._ice_type = IcePy._t_Object
+
+Object._op_ice_isA = IcePy.Operation('ice_isA', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (((), IcePy._t_string),), (), IcePy._t_bool, ())
+Object._op_ice_ping = IcePy.Operation('ice_ping', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (), (), None, ())
+Object._op_ice_ids = IcePy.Operation('ice_ids', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (), (), _t_StringSeq, ())
+Object._op_ice_id = IcePy.Operation('ice_id', OperationMode.Idempotent, OperationMode.Nonmutating, False, (), (), (), IcePy._t_string, ())
+
+IcePy._t_LocalObject = IcePy.defineClass('::Ice::LocalObject', object, (), False, None, (), ())
+
+#
+# Annotate some exceptions.
+#
+def SyscallException__str__(self):
+ return "Ice.SyscallException:\n" + os.strerror(self.error)
+SyscallException.__str__ = SyscallException__str__
+del SyscallException__str__
+
+def SocketException__str__(self):
+ return "Ice.SocketException:\n" + os.strerror(self.error)
+SocketException.__str__ = SocketException__str__
+del SocketException__str__
+
+def ConnectFailedException__str__(self):
+ return "Ice.ConnectFailedException:\n" + os.strerror(self.error)
+ConnectFailedException.__str__ = ConnectFailedException__str__
+del ConnectFailedException__str__
+
+def ConnectionRefusedException__str__(self):
+ return "Ice.ConnectionRefusedException:\n" + os.strerror(self.error)
+ConnectionRefusedException.__str__ = ConnectionRefusedException__str__
+del ConnectionRefusedException__str__
+
+def ConnectionLostException__str__(self):
+ if self.error == 0:
+ return "Ice.ConnectionLostException:\nrecv() returned zero"
+ else:
+ return "Ice.ConnectionLostException:\n" + os.strerror(self.error)
+ConnectionLostException.__str__ = ConnectionLostException__str__
+del ConnectionLostException__str__
+
+#
+# Proxy comparison functions.
+#
+def proxyIdentityEqual(lhs, rhs):
+ '''Determines whether the identities of two proxies are equal.'''
+ return proxyIdentityCompare(lhs, rhs) == 0
+
+def proxyIdentityCompare(lhs, rhs):
+ '''Compares the identities of two proxies.'''
+ if (lhs and not isinstance(lhs, ObjectPrx)) or (rhs and not isinstance(rhs, ObjectPrx)):
+ raise ValueError('argument is not a proxy')
+ if not lhs and not rhs:
+ return True
+ elif not lhs and rhs:
+ return -1
+ elif lhs and not rhs:
+ return 1
+ else:
+ return cmp(lhs.ice_getIdentity(), rhs.ice_getIdentity())
+
+def proxyIdentityAndFacetEqual(lhs, rhs):
+ '''Determines whether the identities and facets of two
+proxies are equal.'''
+ return proxyIdentityAndFacetCompare(lhs, rhs) == 0
+
+def proxyIdentityAndFacetCompare(lhs, rhs):
+ '''Compares the identities and facets of two proxies.'''
+ if (lhs and not isinstance(lhs, ObjectPrx)) or (rhs and not isinstance(rhs, ObjectPrx)):
+ raise ValueError('argument is not a proxy')
+ if not lhs and not rhs:
+ return True
+ elif not lhs and rhs:
+ return -1
+ elif lhs and not rhs:
+ return 1
+ elif lhs.ice_getIdentity() != rhs.ice_getIdentity():
+ return cmp(lhs.ice_getIdentity(), rhs.ice_getIdentity())
+ else:
+ return cmp(lhs.ice_getFacet(), rhs.ice_getFacet())