VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/python/components.py@ 53409

Last change on this file since 53409 was 11746, checked in by vboxsync, 16 years ago

export python lib to OSE

  • Property svn:eol-style set to native
File size: 9.4 KB
Line 
1# ***** BEGIN LICENSE BLOCK *****
2# Version: MPL 1.1/GPL 2.0/LGPL 2.1
3#
4# The contents of this file are subject to the Mozilla Public License Version
5# 1.1 (the "License"); you may not use this file except in compliance with
6# the License. You may obtain a copy of the License at
7# http://www.mozilla.org/MPL/
8#
9# Software distributed under the License is distributed on an "AS IS" basis,
10# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11# for the specific language governing rights and limitations under the
12# License.
13#
14# The Original Code is the Python XPCOM language bindings.
15#
16# The Initial Developer of the Original Code is
17# ActiveState Tool Corp.
18# Portions created by the Initial Developer are Copyright (C) 2000, 2001
19# the Initial Developer. All Rights Reserved.
20#
21# Contributor(s):
22# Mark Hammond <[email protected]> (original author)
23#
24# Alternatively, the contents of this file may be used under the terms of
25# either the GNU General Public License Version 2 or later (the "GPL"), or
26# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27# in which case the provisions of the GPL or the LGPL are applicable instead
28# of those above. If you wish to allow use of your version of this file only
29# under the terms of either the GPL or the LGPL, and not to allow others to
30# use your version of this file under the terms of the MPL, indicate your
31# decision by deleting the provisions above and replace them with the notice
32# and other provisions required by the GPL or the LGPL. If you do not delete
33# the provisions above, a recipient may use your version of this file under
34# the terms of any one of the MPL, the GPL or the LGPL.
35#
36# ***** END LICENSE BLOCK *****
37
38# This module provides the JavaScript "components" interface
39import xpt
40import xpcom, _xpcom
41import xpcom.client
42import xpcom.server
43import types
44
45StringTypes = [types.StringType, types.UnicodeType]
46
47def _get_good_iid(iid):
48 if iid is None:
49 iid = _xpcom.IID_nsISupports
50 elif type(iid) in StringTypes and len(iid)>0 and iid[0] != "{":
51 iid = getattr(interfaces, iid)
52 return iid
53
54# The "manager" object.
55manager = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentManager)
56
57# The component registrar
58registrar = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentRegistrar)
59
60# The "interfaceInfoManager" object - JS doesnt have this.
61interfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager()
62
63# The serviceManager - JS doesnt have this either!
64serviceManager = _xpcom.GetServiceManager()
65
66# The "Exception" object
67Exception = xpcom.COMException
68
69# Base class for our collections.
70# It appears that all objects supports "." and "[]" notation.
71# eg, "interface.nsISupports" or interfaces["nsISupports"]
72class _ComponentCollection:
73 # Bases are to over-ride 2 methods.
74 # _get_one(self, name) - to return one object by name
75 # _build_dict - to return a dictionary which provide access into
76 def __init__(self):
77 self._dict_data = None
78 def keys(self):
79 if self._dict_data is None:
80 self._dict_data = self._build_dict()
81 return self._dict_data.keys()
82 def items(self):
83 if self._dict_data is None:
84 self._dict_data = self._build_dict()
85 return self._dict_data.items()
86 def values(self):
87 if self._dict_data is None:
88 self._dict_data = self._build_dict()
89 return self._dict_data.values()
90 def has_key(self, key):
91 if self._dict_data is None:
92 self._dict_data = self._build_dict()
93 return self._dict_data.has_key(key)
94
95 def __len__(self):
96 if self._dict_data is None:
97 self._dict_data = self._build_dict()
98 return len(self._dict_data)
99
100 def __getattr__(self, attr):
101 if self._dict_data is not None and self._dict_data.has_key(attr):
102 return self._dict_data[attr]
103 return self._get_one(attr)
104 def __getitem__(self, item):
105 if self._dict_data is not None and self._dict_data.has_key(item):
106 return self._dict_data[item]
107 return self._get_one(item)
108
109_constants_by_iid_map = {}
110
111class _Interface:
112 # An interface object.
113 def __init__(self, name, iid):
114 # Bypass self.__setattr__ when initializing attributes.
115 d = self.__dict__
116 d['_iidobj_'] = iid # Allows the C++ framework to treat this as a native IID.
117 d['name'] = name
118 def __cmp__(self, other):
119 this_iid = self._iidobj_
120 other_iid = getattr(other, "_iidobj_", other)
121 return cmp(this_iid, other_iid)
122 def __hash__(self):
123 return hash(self._iidobj_)
124 def __str__(self):
125 return str(self._iidobj_)
126 def __getitem__(self, item):
127 raise TypeError, "components.interface objects are not subscriptable"
128 def __setitem__(self, item, value):
129 raise TypeError, "components.interface objects are not subscriptable"
130 def __setattr__(self, attr, value):
131 raise AttributeError, "Can not set attributes on components.Interface objects"
132 def __getattr__(self, attr):
133 # Support constants as attributes.
134 c = _constants_by_iid_map.get(self._iidobj_)
135 if c is None:
136 c = {}
137 i = xpt.Interface(self._iidobj_)
138 for c_ob in i.constants:
139 c[c_ob.name] = c_ob.value
140 _constants_by_iid_map[self._iidobj_] = c
141 if c.has_key(attr):
142 return c[attr]
143 raise AttributeError, "'%s' interfaces do not define a constant '%s'" % (self.name, attr)
144
145
146class _Interfaces(_ComponentCollection):
147 def _get_one(self, name):
148 try:
149 item = interfaceInfoManager.GetInfoForName(name)
150 except xpcom.COMException, why:
151 # Present a better exception message, and give a more useful error code.
152 import nsError
153 raise xpcom.COMException(nsError.NS_ERROR_NO_INTERFACE, "The interface '%s' does not exist" % (name,))
154 return _Interface(item.GetName(), item.GetIID())
155
156 def _build_dict(self):
157 ret = {}
158 enum = interfaceInfoManager.EnumerateInterfaces()
159 while not enum.IsDone():
160 # Call the Python-specific FetchBlock, to keep the loop in C.
161 items = enum.FetchBlock(500, _xpcom.IID_nsIInterfaceInfo)
162 # This shouldnt be necessary, but appears to be so!
163 for item in items:
164 ret[item.GetName()] = _Interface(item.GetName(), item.GetIID())
165 return ret
166
167# And the actual object people use.
168interfaces = _Interfaces()
169
170del _Interfaces # Keep our namespace clean.
171
172#################################################
173class _Class:
174 def __init__(self, contractid):
175 self.contractid = contractid
176 def __getattr__(self, attr):
177 if attr == "clsid":
178 rc = registrar.contractIDToCID(self.contractid)
179 # stash it away - it can never change!
180 self.clsid = rc
181 return rc
182 raise AttributeError, "%s class has no attribute '%s'" % (self.contractid, attr)
183 def createInstance(self, iid = None):
184 import xpcom.client
185 try:
186 return xpcom.client.Component(self.contractid, _get_good_iid(iid))
187 except xpcom.COMException, details:
188 import nsError
189 # Handle "no such component" in a cleaner way for the user.
190 if details.errno == nsError.NS_ERROR_FACTORY_NOT_REGISTERED:
191 raise xpcom.COMException(details.errno, "No such component '%s'" % (self.contractid,))
192 raise # Any other exception reraise.
193 def getService(self, iid = None):
194 return serviceManager.getServiceByContractID(self.contractid, _get_good_iid(iid))
195
196class _Classes(_ComponentCollection):
197 def __init__(self):
198 _ComponentCollection.__init__(self)
199 def _get_one(self, name):
200 # XXX - Need to check the contractid is valid!
201 return _Class(name)
202
203 def _build_dict(self):
204 ret = {}
205 enum = registrar.enumerateContractIDs()
206 while enum.hasMoreElements():
207 # Call the Python-specific FetchBlock, to keep the loop in C.
208 items = enum.fetchBlock(2000, _xpcom.IID_nsISupportsCString)
209 for item in items:
210 name = str(item.data)
211 ret[name] = _Class(name)
212 return ret
213
214classes = _Classes()
215
216del _Classes
217
218del _ComponentCollection
219
220# The ID function
221ID = _xpcom.IID
222
223# A helper to cleanup our namespace as xpcom shuts down.
224class _ShutdownObserver:
225 _com_interfaces_ = interfaces.nsIObserver
226 def observe(self, service, topic, extra):
227 global manager, registrar, classes, interfaces, interfaceInfoManager, _shutdownObserver, serviceManager, _constants_by_iid_map
228 manager = registrar = classes = interfaces = interfaceInfoManager = _shutdownObserver = serviceManager = _constants_by_iid_map = None
229 xpcom.client._shutdown()
230 xpcom.server._shutdown()
231
232svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/observer-service;1", interfaces.nsIObserverService)
233# Observers will be QI'd for a weak-reference, so we must keep the
234# observer alive ourself, and must keep the COM object alive,
235# _not_ just the Python instance!!!
236_shutdownObserver = xpcom.server.WrapObject(_ShutdownObserver(), interfaces.nsIObserver)
237# Say we want a weak ref due to an assertion failing. If this is fixed, we can pass 0,
238# and remove the lifetime hacks above! See http://bugzilla.mozilla.org/show_bug.cgi?id=99163
239svc.addObserver(_shutdownObserver, "xpcom-shutdown", 1)
240del svc, _ShutdownObserver
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette