home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Freeware / Miro 1.0 / Miro_Installer.exe / xulrunner / python / xpcom / server / loader.py < prev    next >
Encoding:
Python Source  |  2007-11-12  |  9.7 KB  |  226 lines

  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
  19. # the Initial Developer. All Rights Reserved.
  20. #
  21. # Contributor(s):
  22. #    Mark Hammond <MarkH@ActiveState.com>
  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. import xpcom
  39. from xpcom import components
  40.  
  41. import module
  42.  
  43. import glob, os, types
  44. import traceback
  45.  
  46. from xpcom.client import Component
  47.  
  48. # Until we get interface constants.
  49. When_Startup = 0
  50. When_Component = 1
  51. When_Timer = 2
  52.  
  53. def _has_good_attr(object, attr):
  54.     # Actually allows "None" to be specified to disable inherited attributes.
  55.     return getattr(object, attr, None) is not None
  56.  
  57. def FindCOMComponents(py_module):
  58.     # For now, just run over all classes looking for likely candidates.
  59.     comps = []
  60.     for name, object in py_module.__dict__.items():
  61.         if type(object)==types.ClassType and \
  62.            _has_good_attr(object, "_com_interfaces_") and \
  63.            _has_good_attr(object, "_reg_clsid_") and \
  64.            _has_good_attr(object, "_reg_contractid_"):
  65.             comps.append(object)
  66.     return comps
  67.  
  68. def register_self(klass, compMgr, location, registryLocation, componentType):
  69.     pcl = PythonComponentLoader
  70.     from xpcom import _xpcom
  71.     svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/categorymanager;1", components.interfaces.nsICategoryManager)
  72.     svc.addCategoryEntry("component-loader", pcl._reg_component_type_, pcl._reg_contractid_, 1, 1)
  73.  
  74. class PythonComponentLoader:
  75.     _com_interfaces_ = components.interfaces.nsIComponentLoader
  76.     _reg_clsid_ = "{63B68B1E-3E62-45f0-98E3-5E0B5797970C}" # Never copy these!
  77.     _reg_contractid_ = "moz.pyloader.1"
  78.     _reg_desc_ = "Python component loader"
  79.     # Optional function which performs additional special registration
  80.     # Appears that no special unregistration is needed for ComponentLoaders, hence no unregister function.
  81.     _reg_registrar_ = (register_self,None)
  82.     # Custom attributes for ComponentLoader registration.
  83.     _reg_component_type_ = "script/python"
  84.  
  85.     def __init__(self):
  86.         self.com_modules = {} # Keyed by module's FQN as obtained from nsIFile.path
  87.         self.moduleFactory = module.Module
  88.         self.num_modules_this_register = 0
  89.  
  90.     def _getCOMModuleForLocation(self, componentFile):
  91.         fqn = componentFile.path
  92.         mod = self.com_modules.get(fqn)
  93.         if mod is not None:
  94.             return mod
  95.         import ihooks, sys
  96.         base_name = os.path.splitext(os.path.basename(fqn))[0]
  97.         loader = ihooks.ModuleLoader()
  98.  
  99.         module_name_in_sys = "component:%s" % (base_name,)
  100.         stuff = loader.find_module(base_name, [componentFile.parent.path])
  101.         assert stuff is not None, "Couldnt find the module '%s'" % (base_name,)
  102.         py_mod = loader.load_module( module_name_in_sys, stuff )
  103.  
  104.         # Make and remember the COM module.
  105.         comps = FindCOMComponents(py_mod)
  106.         mod = self.moduleFactory(comps)
  107.         
  108.         self.com_modules[fqn] = mod
  109.         return mod
  110.         
  111.     def getFactory(self, clsid, location, type):
  112.         # return the factory
  113.         assert type == self._reg_component_type_, "Being asked to create an object not of my type:%s" % (type,)
  114.         # FIXME: how to do this without obsolete component manager?
  115.         cmo = components.manager.queryInterface(components.interfaces.nsIComponentManagerObsolete)    
  116.         file_interface = cmo.specForRegistryLocation(location)
  117.         # delegate to the module.
  118.         m = self._getCOMModuleForLocation(file_interface)
  119.         return m.getClassObject(components.manager, clsid, components.interfaces.nsIFactory)
  120.  
  121.     def init(self, comp_mgr, registry):
  122.         # void
  123.         self.comp_mgr = comp_mgr
  124.         if xpcom.verbose:
  125.             print "Python component loader init() called"
  126.  
  127.      # Called when a component of the appropriate type is registered,
  128.      # to give the component loader an opportunity to do things like
  129.      # annotate the registry and such.
  130.     def onRegister (self, clsid, type, className, proId, location, replace, persist):
  131.         if xpcom.verbose:
  132.             print "Python component loader - onRegister() called"
  133.  
  134.     def autoRegisterComponents (self, when, directory):
  135.         directory_path = directory.path
  136.         self.num_modules_this_register = 0
  137.         if xpcom.verbose:
  138.             print "Auto-registering all Python components in", directory_path
  139.  
  140.         # ToDo - work out the right thing here
  141.         # eg - do we recurse?
  142.         # - do we support packages?
  143.         entries = directory.directoryEntries
  144.         while entries.HasMoreElements():
  145.             entry = entries.GetNext(components.interfaces.nsIFile)
  146.             if os.path.splitext(entry.path)[1]==".py":
  147.                 try:
  148.                     self.autoRegisterComponent(when, entry)
  149.                 # Handle some common user errors
  150.                 except xpcom.COMException, details:
  151.                     from xpcom import nsError
  152.                     # If the interface name does not exist, suppress the traceback
  153.                     if details.errno==nsError.NS_ERROR_NO_INTERFACE:
  154.                         print "** Registration of '%s' failed\n %s" % (entry.leafName,details.message,)
  155.                     else:
  156.                         print "** Registration of '%s' failed!" % (entry.leafName,)
  157.                         traceback.print_exc()
  158.                 except SyntaxError, details:
  159.                     # Syntax error in source file - no useful traceback here either.
  160.                     print "** Registration of '%s' failed!" % (entry.leafName,)
  161.                     traceback.print_exception(SyntaxError, details, None)
  162.                 except:
  163.                     # All other exceptions get the full traceback.
  164.                     print "** Registration of '%s' failed!" % (entry.leafName,)
  165.                     traceback.print_exc()
  166.  
  167.     def autoRegisterComponent (self, when, componentFile):
  168.         # bool return
  169.         
  170.         # Check if we actually need to do anything
  171.         modtime = componentFile.lastModifiedTime
  172.         loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
  173.         if not loader_mgr.hasFileChanged(componentFile, None, modtime):
  174.             return 1
  175.  
  176.         if self.num_modules_this_register == 0:
  177.             # New components may have just installed new Python
  178.             # modules into the main python directory (including new .pth files)
  179.             # So we ask Python to re-process our site directory.
  180.             # Note that the pyloader does the equivalent when loading.
  181.             try:
  182.                 from xpcom import _xpcom
  183.                 import site
  184.                 NS_XPCOM_CURRENT_PROCESS_DIR="XCurProcD"
  185.                 dirname = _xpcom.GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR)
  186.                 dirname.append("python")
  187.                 site.addsitedir(dirname.path)
  188.             except:
  189.                 print "PyXPCOM loader failed to process site directory before component registration"
  190.                 traceback.print_exc()
  191.  
  192.         self.num_modules_this_register += 1
  193.  
  194.         # auto-register via the module.
  195.         m = self._getCOMModuleForLocation(componentFile)
  196.         m.registerSelf(components.manager, componentFile, None, self._reg_component_type_)
  197.         loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
  198.         loader_mgr.saveFileInfo(componentFile, None, modtime)
  199.         return 1
  200.  
  201.     def autoUnregisterComponent (self, when, componentFile):
  202.         # bool return
  203.         # auto-unregister via the module.
  204.         m = self._getCOMModuleForLocation(componentFile)
  205.         loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager)
  206.         try:
  207.             m.unregisterSelf(components.manager, componentFile)
  208.         finally:
  209.             loader_mgr.removeFileInfo(componentFile, None)
  210.         return 1
  211.  
  212.     def registerDeferredComponents (self, when):
  213.         # bool return
  214.         if xpcom.verbose:
  215.             print "Python component loader - registerDeferred() called"
  216.         return 0 # no more to register
  217.     def unloadAll (self, when):
  218.         if xpcom.verbose:
  219.             print "Python component loader being asked to unload all components!"
  220.         self.comp_mgr = None
  221.         self.com_modules = {}
  222.  
  223. def MakePythonComponentLoaderModule(serviceManager, nsIFile):
  224.     import module
  225.     return module.Module( [PythonComponentLoader] )
  226.