policy.py revision 16a8d09569a2ebd598cef72fa605be6fb4563607
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Python XPCOM language bindings.
#
# The Initial Developer of the Original Code is
# ActiveState Tool Corp.
# Portions created by the Initial Developer are Copyright (C) 2001
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Mark Hammond <mhammond@skippinet.com.au> (original author)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import xpcom
import operator
import types
import logging
VARIANT_STRING_TYPES = xpcom_consts.VTYPE_CHAR, xpcom_consts.VTYPE_CHAR_STR, xpcom_consts.VTYPE_STRING_SIZE_IS, \
VARIANT_UNICODE_TYPES = xpcom_consts.VTYPE_WCHAR, xpcom_consts.VTYPE_DOMSTRING, xpcom_consts.VTYPE_WSTRING_SIZE_IS, \
_supports_primitives_map_ = {} # Filled on first use.
def _GetNominatedInterfaces(obj):
if ret is None: return None
# See if the user only gave one.
real_ret = []
# For each interface, walk to the root of the interface tree.
# Allow interface name or IID.
interface_info = None
try:
except COMException:
pass
if interface_info is None:
# Allow a real IID
while parent is not None:
if parent_iid == IID_nsISupports:
break
return real_ret
##
## ClassInfo support
##
## We cache class infos by class
class_info_cache = {}
def GetClassInfoForObject(ob):
if ci is None:
return ci
class DefaultClassInfo:
self.interfaces = None
def get_classID(self):
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED, "Class '%r' has no class ID" % (self.klass,))
def getInterfaces(self):
if self.interfaces is None:
return self.interfaces
return None # Not sure what to do here.
class DefaultPolicy:
if ni is None:
# This is really only a check for the user
if __debug__:
# The object may delegate QI.
# Perform the actual QI and throw away the result - the _real_
# QI performed by the framework will set things right!
# Stuff for the magic interface conversion.
self._interface_info_ = None
# Framework allows us to return a single boolean integer,
# or a COM object.
# We return the underlying object re-wrapped
# in a new gateway - which is desirable, as one gateway should only support
# one interface (this wont affect the users of this policy - we can have as many
# gateways as we like pointing to the same Python objects - the users never
# see what object the call came in from.
# NOTE: We could have simply returned the instance and let the framework
# do the auto-wrap for us - but this way we prevent a round-trip back into Python
# code just for the autowrap.
# Always support nsIClassInfo
# See if the instance has a QI
# use lower-case "_query_interface_" as win32com does, and it doesnt really matter.
if delegate is not None:
# The COM object itself doesnt get passed to the child
# (again, as win32com doesnt). It is rarely needed
# (in win32com, we dont even pass it to the policy, although we have identified
# one place where we should - for marshalling - so I figured I may as well pass it
# to the policy layer here, but no all the way down to the object.
# Finally see if we are being queried for one of the "nsISupports primitives"
if not _supports_primitives_map_:
# Out of clever things to try!
return None # We dont support this IID.
# Wrap a "raw" interface object in a nice object. The result of this
# function will be passed to one of the gateway methods.
if iid is None:
# look up the interface info - this will be true for all xpcom called interfaces.
if self._interface_info_ is None:
if iid is None:
# handle nsIVariant
if iid == IID_nsIVariant:
if dt in VARIANT_INT_TYPES:
return interface.getAsInt32()
if dt in VARIANT_LONG_TYPES:
return interface.getAsInt64()
if dt in VARIANT_FLOAT_TYPES:
return interface.getAsFloat()
if dt in VARIANT_STRING_TYPES:
return interface.getAsStringWithSize()
if dt in VARIANT_UNICODE_TYPES:
return interface.getAsWStringWithSize()
return interface.getAsISupports()
return interface.getAsInterface()
return None
return interface.getAsArray()
return []
# all else fails...
try:
return interface.getAsString()
except COMException:
return interface
#print "_CallMethod_", index, info, params
if XPT_MD_IS_GETTER(flags):
# Look for a function of that name
if func is None:
assert len(param_descs)==1 and len(params)==0, "Can only handle a single [out] arg for a default getter"
else:
return 0, ret
elif XPT_MD_IS_SETTER(flags):
# Look for a function of that name
if func is None:
assert len(param_descs)==1 and len(params)==1, "Can only handle a single [in] arg for a default setter"
else:
return 0
else:
# A regular method.
# When a component raised an explicit COM exception, it is
# considered 'normal' - however, we still write a debug log
# record to help track these otherwise silent exceptions.
# Note that Python 2.3 does not allow an explicit exc_info tuple
# and passing 'True' will not work as there is no exception pending.
# Trick things!
try:
except:
# Unhandled exception - always print a warning and the traceback.
# As above, trick the logging module to handle Python 2.3
try:
except:
return nsError.NS_ERROR_FAILURE
# Called whenever an unhandled Python exception is detected as a result
# of _CallMethod_ - this exception may have been raised during the _CallMethod_
# invocation, or after its return, but when unpacking the results
# eg, type errors, such as a Python integer being used as a string "out" param.
# Later we may want to have some smart "am I debugging" flags?
# Or maybe just delegate to the actual object - it's probably got the best
# idea what to do with them!
# use the xpt module to get a better repr for the method.
# But if we fail, ignore it!
try:
except COMException:
except:
# any other errors are evil!? Log it
# And fall through to logging the original error.
# Called whenever a gateway fails due to anything other than _CallMethod_.
# Really only used for the component loader etc objects, so most
# users should never see exceptions triggered here.
]
# Support for the nsISupports primitives:
class SupportsPrimitive:
_com_interfaces_ = ["nsISupports"]
return 1
return None
def _shutdown():