home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / fnb101.zip / Lib / site-packages / Fnorb / cos / naming / NamingContext.py < prev    next >
Text File  |  1999-06-28  |  15KB  |  516 lines

  1. #!/usr/bin/env python
  2. #############################################################################
  3. # Copyright (C) DSTC Pty Ltd (ACN 052 372 577) 1997, 1998, 1999
  4. # All Rights Reserved.
  5. #
  6. # The software contained on this media is the property of the DSTC Pty
  7. # Ltd.  Use of this software is strictly in accordance with the
  8. # license agreement in the accompanying LICENSE.HTML file.  If your
  9. # distribution of this software does not contain a LICENSE.HTML file
  10. # then you have no rights to use this software in any manner and
  11. # should contact DSTC at the address below to determine an appropriate
  12. # licensing arrangement.
  13. #      DSTC Pty Ltd
  14. #      Level 7, GP South
  15. #      Staff House Road
  16. #      University of Queensland
  17. #      St Lucia, 4072
  18. #      Australia
  19. #      Tel: +61 7 3365 4310
  20. #      Fax: +61 7 3365 4311
  21. #      Email: enquiries@dstc.edu.au
  22. # This software is being provided "AS IS" without warranty of any
  23. # kind.  In no event shall DSTC Pty Ltd be liable for damage of any
  24. # kind arising out of or in connection with the use or performance of
  25. # this software.
  26. #
  27. # Project:      Fnorb
  28. # File:         $Source: /units/arch/src/Fnorb/cos/naming/RCS/NamingContext.py,v $
  29. # Version:      @(#)$RCSfile: NamingContext.py,v $ $Revision: 1.10 $
  30. #
  31. #############################################################################
  32. """ COS Naming Service Naming Contexts. """
  33.  
  34.  
  35. # Standard/built-in modules.
  36. import string
  37.  
  38. # Fnorb modules.
  39. from Fnorb.orb import fnorb_thread, uuid, BOA, CORBA
  40.  
  41. # Stubs and skeletons.
  42. import CosNaming, CosNaming_skel
  43.  
  44. # Naming service modules.
  45. import BindingIterator
  46.  
  47.  
  48. def NamingContextFactory_init():
  49.     """ Initialise the Naming Contect Factory.
  50.  
  51.     This is a factory function for the NamingContextFactory class (the factory 
  52.     is a singleton (ie. there can only be one instance per process)).
  53.  
  54.     """
  55.     try:
  56.     ncf = NamingContextFactory()
  57.  
  58.     except NamingContextFactory, ncf:
  59.     pass
  60.  
  61.     return ncf
  62.  
  63.  
  64. class NamingContextFactory:
  65.     """ A factory for naming contexts!
  66.  
  67.     The factory is a singleton (ie. there can only be one instance per
  68.     process).
  69.  
  70.     """
  71.     # Singleton instance.
  72.     __instance = None
  73.  
  74.     def __init__(self):
  75.     """ Constructor. """
  76.  
  77.     # The factory is a singleton (ie. there can only be one instance per
  78.     # process).
  79.     if NamingContextFactory.__instance is not None:
  80.         raise NamingContextFactory.__instance
  81.  
  82.     NamingContextFactory.__instance = self
  83.  
  84.     return
  85.  
  86.     def create_naming_context(self, object_key=None):
  87.     """ Create and return a new naming context. """
  88.  
  89.     # Create an object key for the context.
  90.     if object_key is None:
  91.         # Generate a unique object key for the context.
  92.         object_key = uuid.uuid()
  93.  
  94.     # Create an instance of the implementation class.
  95.     impl = NamingContext()
  96.  
  97.     # Create an object reference.
  98.     boa = BOA.BOA_init()
  99.     nc = boa.create(object_key, NamingContext._FNORB_ID)
  100.  
  101.     # Activate the implementation (ie. connect the generated object
  102.     # reference to the implementation).
  103.     boa.obj_is_ready(nc, impl)
  104.  
  105.     return impl
  106.  
  107.  
  108. class NamingContext(CosNaming_skel.NamingContext_skel):
  109.     """ Naming context implementation. """
  110.  
  111.     # A binding iterator factory that is shared by every context instance.
  112.     bif = BindingIterator.BindingIteratorFactory_init()
  113.  
  114.     def __init__(self, nc_factory=None, d_bindings=None):
  115.     """ Constructor. """
  116.  
  117.     # A factory responsible for creating new naming contexts.
  118.     if nc_factory is None:
  119.         self.__nc_factory = NamingContextFactory_init()
  120.  
  121.     else:
  122.         self.__nc_factory = nc_factory
  123.  
  124.     # A dictionary containing the bindings in the context, in the form:-
  125.     # {(NameComponentId, NameComponentKind): (Binding, StringifiedIOR)}.
  126.     #
  127.     # We cannot key the dictionary directly on a NameComponent instance
  128.     # because the NameComponent class is generated automatically by the
  129.     # IDL compiler and therefore has no '__hash__' method.
  130.     if d_bindings is None:
  131.         self.__d_bindings = {}
  132.  
  133.     else:
  134.         self.__d_bindings = d_bindings
  135.  
  136.     # A mutex to make access to the binding dictionary safe in threaded
  137.     # environments.
  138.     self.__lk = fnorb_thread.allocate_lock()
  139.  
  140.     return
  141.  
  142.     #########################################################################
  143.     # CORBA interface.
  144.     #########################################################################
  145.  
  146.     def bind(self, n, obj):
  147.     """ Bind the name 'n' to the object reference obj. """
  148.  
  149.     # An 'empty' name is invalid.
  150.     if len(n) == 0:
  151.         raise CosNaming.NamingContext.InvalidName()
  152.  
  153.     # Get the first component of the name.
  154.     component = n[0]
  155.  
  156.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  157.     key = str((component.id, component.kind))
  158.  
  159.     # If there is exactly one component in the name then the operation
  160.     # takes place in *this* context.
  161.     if len(n) == 1:
  162.         self.__lk.acquire()
  163.         try:
  164.         # Is the component already bound?
  165.         if self.__d_bindings.has_key(key):
  166.             raise CosNaming.NamingContext.AlreadyBound()
  167.  
  168.         # Create the binding.
  169.         binding = CosNaming.Binding(n, CosNaming.nobject)
  170.  
  171.         # Stringify the object reference.
  172.         orb = CORBA.ORB_init()
  173.         stringified_ior = orb.object_to_string(obj)
  174.  
  175.         # Add it to the binding dictionary.
  176.         self.__d_bindings[key] = (binding, stringified_ior)
  177.  
  178.         finally:
  179.         self.__lk.release()
  180.  
  181.     # Otherwise, attempt to continue resolution into the next context.
  182.     else:
  183.         self.__resolve('bind', key, n, obj)
  184.  
  185.     return
  186.  
  187.     def rebind(self, n, obj):
  188.     """ Rebind the name 'n' to the object reference obj. """
  189.  
  190.     # An 'empty' name is invalid.
  191.     if len(n) == 0:
  192.         raise CosNaming.NamingContext.InvalidName()
  193.  
  194.     # Get the first component of the name.
  195.     component = n[0]
  196.  
  197.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  198.     key = str((component.id, component.kind))
  199.  
  200.     # If there is exactly one component in the name then the operation
  201.     # takes place in *this* context.
  202.     if len(n) == 1:
  203.         # Create the binding.
  204.         binding = CosNaming.Binding(n, CosNaming.nobject)
  205.  
  206.         # Stringify the object reference.
  207.         orb = CORBA.ORB_init()
  208.         stringified_ior = orb.object_to_string(obj)
  209.  
  210.         # Add it to the binding dictionary.
  211.         self.__lk.acquire()
  212.         self.__d_bindings[key] = (binding, stringified_ior)
  213.         self.__lk.release()
  214.  
  215.     # Otherwise, attempt to continue resolution into the next context.
  216.     else:
  217.         self.__resolve('rebind', key, n, obj)
  218.  
  219.     return
  220.  
  221.     def bind_context(self, n, nc):
  222.     """ Bind the name 'n' to the naming context nc. """
  223.  
  224.     # An 'empty' name is invalid.
  225.     if len(n) == 0:
  226.         raise CosNaming.NamingContext.InvalidName()
  227.  
  228.     # Get the first component of the name.
  229.     component = n[0]
  230.  
  231.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  232.     key = str((component.id, component.kind))
  233.  
  234.     # If there is exactly one component in the name then the operation
  235.     # takes place in *this* context.
  236.     if len(n) == 1:
  237.         self.__lk.acquire()
  238.         try:
  239.         # Is the component already bound?
  240.         if self.__d_bindings.has_key(key):
  241.             raise CosNaming.NamingContext.AlreadyBound()
  242.  
  243.         # Create the binding.
  244.         binding = CosNaming.Binding(n, CosNaming.ncontext)
  245.  
  246.         # Stringify the object reference.
  247.         orb = CORBA.ORB_init()
  248.         stringified_ior = orb.object_to_string(nc)
  249.  
  250.         # Add it to the binding dictionary.
  251.         self.__d_bindings[key] = (binding, stringified_ior)
  252.  
  253.         finally:
  254.         self.__lk.release()
  255.  
  256.     # Otherwise, attempt to continue resolution into the next context.
  257.     else:
  258.         self.__resolve('bind_context', key, n, nc)
  259.  
  260.     return
  261.  
  262.     def rebind_context(self, n, nc):
  263.     """ Rebind the name 'n' to the naming context nc. """
  264.  
  265.     # An 'empty' name is invalid.
  266.     if len(n) == 0:
  267.         raise CosNaming.NamingContext.InvalidName()
  268.  
  269.     # Get the first component of the name.
  270.     component = n[0]
  271.  
  272.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  273.     key = str((component.id, component.kind))
  274.  
  275.     # If there is exactly one component in the name then the operation
  276.     # takes place in *this* context.
  277.     if len(n) == 1:
  278.         # Create the binding.
  279.         binding = CosNaming.Binding(n, CosNaming.ncontext)
  280.  
  281.         # Stringify the object reference.
  282.         orb = CORBA.ORB_init()
  283.         stringified_ior = orb.object_to_string(nc)
  284.  
  285.         # Add it to the binding dictionary.
  286.         self.__lk.acquire()
  287.         self.__d_bindings[key] = (binding, stringified_ior)
  288.         self.__lk.release()
  289.  
  290.     # Otherwise, attempt to continue resolution into the next context.
  291.     else:
  292.         self.__resolve('rebind_context', key, n, nc)
  293.  
  294.     return
  295.  
  296.     def resolve(self, n):
  297.     """ Resolve the name 'n'. """
  298.  
  299.     # An 'empty' name is invalid.
  300.     if len(n) == 0:
  301.         raise CosNaming.NamingContext.InvalidName()
  302.  
  303.     # Get the first component of the name.
  304.     component = n[0]
  305.  
  306.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  307.     key = str((component.id, component.kind))
  308.  
  309.     # If there is exactly one component in the name then the operation
  310.     # takes place in *this* context.
  311.     if len(n) == 1:
  312.         self.__lk.acquire()
  313.         try:
  314.         # Is the component bound in this context?
  315.         if not self.__d_bindings.has_key(key):
  316.             raise CosNaming.NamingContext.NotFound \
  317.               (CosNaming.NamingContext.missing_node, n)
  318.  
  319.         # Get the stringified IOR bound to the component.
  320.         (binding, stringified_ior) = self.__d_bindings[key]
  321.  
  322.         # Convert the stringified IOR into an active object reference.
  323.         orb = CORBA.ORB_init()
  324.         result = orb.string_to_object(stringified_ior)
  325.  
  326.         finally:
  327.         self.__lk.release()
  328.         
  329.     # Otherwise, attempt to continue resolution into the next context.
  330.     else:
  331.         result = self.__resolve('resolve', key, n)
  332.  
  333.     return result
  334.  
  335.     def unbind(self, n):
  336.     """ Unbind the name 'n'. """
  337.  
  338.     # An 'empty' name is invalid.
  339.     if len(n) == 0:
  340.         raise CosNaming.NamingContext.InvalidName()
  341.  
  342.     # Get the first component of the name.
  343.     component = n[0]
  344.  
  345.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  346.     key = str((component.id, component.kind))
  347.  
  348.     # If there is exactly one component in the name then the operation
  349.     # takes place in *this* context.
  350.     if len(n) == 1:
  351.         self.__lk.acquire()
  352.         try:
  353.         # Is the component bound in this context?
  354.         if not self.__d_bindings.has_key(key):
  355.             raise CosNaming.NamingContext.NotFound()
  356.  
  357.         # Delete the binding.
  358.         del self.__d_bindings[key]
  359.  
  360.         finally:
  361.         self.__lk.release()
  362.  
  363.     # Otherwise, attempt to continue resolution into the next context.
  364.     else:
  365.         self.__resolve('unbind', key, n)
  366.  
  367.     return
  368.  
  369.     def new_context(self):
  370.     """ Create a new naming context. """
  371.  
  372.     # Ask the factory to create a new naming context for us.
  373.     return self.__nc_factory.create_naming_context()
  374.  
  375.     def bind_new_context(self, n):
  376.     """ Create a new naming context and bind it to the name 'n'. """
  377.  
  378.     # An 'empty' name is invalid.
  379.     if len(n) == 0:
  380.         raise CosNaming.NamingContext.NotFound()
  381.  
  382.     # Get the first component of the name.
  383.     component = n[0]
  384.  
  385.     # The binding dictionary is keyed on (ComponentId, ComponentKind).
  386.     key = str((component.id, component.kind))
  387.  
  388.     # If there is exactly one component in the name then the operation
  389.     # takes place in *this* context.
  390.     if len(n) == 1:
  391.         self.__lk.acquire()
  392.         try:
  393.         # Is the component already bound?
  394.         if self.__d_bindings.has_key(key):
  395.             raise CosNaming.NamingContext.AlreadyBound()
  396.  
  397.         # Create the binding.
  398.         binding = CosNaming.Binding(n, CosNaming.ncontext)
  399.  
  400.         # Create a new context.
  401.         nc = self.new_context()
  402.  
  403.         # Stringify the object reference.
  404.         orb = CORBA.ORB_init()
  405.         stringified_ior = orb.object_to_string(nc)
  406.  
  407.         # Add it to the binding dictionary.
  408.         self.__d_bindings[key] = (binding, stringified_ior)
  409.         
  410.         finally:
  411.         self.__lk.release()
  412.  
  413.     # Otherwise, attempt to continue resolution into the next context.
  414.     else:
  415.         nc = self.__resolve('bind_new_context', key, n)
  416.  
  417.     return nc
  418.  
  419.     def destroy(self):
  420.     """ Destroy the naming context. """
  421.  
  422.     self.__lk.acquire()
  423.     try:
  424.         # Naming contexts must be empty to be destroyed!
  425.         if len(self.__d_bindings.keys()) > 0:
  426.         raise CosNaming.NamingContext.NotEmpty()
  427.  
  428.     finally:
  429.         self.__lk.release()
  430.  
  431.     # Unregister myself from the BOA.
  432.     boa = BOA.BOA_init()
  433.     boa.deactivate_obj(self)
  434.  
  435.     return
  436.     
  437.     def list(self, how_many):
  438.     """ List the bindings in a context. """
  439.  
  440.     # Create a list of the bindings in the context.
  441.     #
  442.     # Note that we do not use 'self.__d_bindings.values()' to get at the
  443.     # dictionary contents; this is a small concession to allow Python
  444.     # shelves to be used for creating persistent contexts (shelves do not
  445.     # implement the 'values' method).
  446.     self.__lk.acquire()
  447.     bl = []
  448.     for key in self.__d_bindings.keys():
  449.         (binding, obj) = self.__d_bindings[key]
  450.         bl.append(binding)
  451.     self.__lk.release()
  452.  
  453.     # If there are more bindings than have been requested, then return a
  454.     # binding iterator.
  455.     if len(bl) > how_many:
  456.         iterator = NamingContext.bif.create_binding_iterator(bl[how_many:])
  457.  
  458.     # Otherwise return a nil reference for the iterator.
  459.     else:
  460. ##        orb = CORBA.ORB_init()
  461. ##        iterator = orb.nil()
  462.         iterator = None
  463.  
  464.     return (bl[:how_many], iterator)
  465.  
  466.     #########################################################################
  467.     # Internal interface.
  468.     #########################################################################
  469.  
  470.     def __resolve(self, op, key, n, *args):
  471.     """ Resolve a naming operation through a naming graph. """
  472.  
  473.     self.__lk.acquire()
  474.     try:
  475.         # If the component is not bound in this context then we can go no
  476.         # further!
  477.         if not self.__d_bindings.has_key(key):
  478.         raise CosNaming.NamingContext.NotFound \
  479.               (CosNaming.NamingContext.missing_node, n)
  480.  
  481.         # Get the binding!
  482.         (binding, stringified_ior) = self.__d_bindings[key]
  483.  
  484.     finally:
  485.         self.__lk.release()
  486.  
  487.     # If the binding contains another naming context then continue the
  488.     # resolution.
  489.     if binding.binding_type == CosNaming.ncontext:
  490.         # Convert the stringified IOR into an active object reference.
  491.         orb = CORBA.ORB_init()
  492.         next = orb.string_to_object(stringified_ior)
  493.  
  494.         # Find the appropriate method on the context.
  495.         method = getattr(next, op)
  496.  
  497.         # Invoke the method translating CORBA system exceptions into
  498.         # 'CannotProceed' exceptions.
  499.         try:
  500.         result = apply(method, (n[1:],) + args)
  501.  
  502.         except CORBA.SystemException:
  503.         raise CosNaming.NamingContext.CannotProceed(self, n)
  504.  
  505.     # Otherwise, the binding contains some other object reference and
  506.     # therefore we cannot continue the resolution.
  507.     else:
  508.         raise CosNaming.NamingContext.NotFound \
  509.           (CosNaming.NamingContext.not_context, n)
  510.  
  511.     return result
  512.  
  513. #############################################################################
  514.