Package pulp :: Package messaging :: Module dispatcher
[hide private]
[frames] | no frames]

Source Code for Module pulp.messaging.dispatcher

  1  # 
  2  # Copyright (c) 2010 Red Hat, Inc. 
  3  # 
  4  # This software is licensed to you under the GNU General Public License, 
  5  # version 2 (GPLv2). There is NO WARRANTY for this software, express or 
  6  # implied, including the implied warranties of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 
  8  # along with this software; if not, see 
  9  # http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. 
 10  # 
 11  # Red Hat trademarks are not licensed under GPLv2. No permission is 
 12  # granted to use or replicate Red Hat trademarks that are incorporated 
 13  # in this software or its documentation. 
 14  # 
 15  """ 
 16  Provides RMI dispatcher classes. 
 17  """ 
 18   
 19  import sys 
 20  import traceback as tb 
 21  from pulp.messaging import * 
 22  from pulp.messaging.decorators import mayinvoke 
 23  from logging import getLogger 
 24   
 25   
 26  log = getLogger(__name__) 
27 28 29 -class ClassNotFound(Exception):
30 """ 31 Target class not found. 32 """ 33
34 - def __init__(self, classname):
35 Exception.__init__(self, classname)
36
37 38 -class MethodNotFound(Exception):
39 """ 40 Target method not found. 41 """ 42
43 - def __init__(self, classname, method):
44 message = 'method %s.%s(), not found' % (classname, method) 45 Exception.__init__(self, message)
46
47 48 -class NotPermitted(Exception):
49 """ 50 Permission denied or not visible. 51 """ 52
53 - def __init__(self, classname, method):
54 message = 'method %s.%s(), not permitted' % (classname, method) 55 Exception.__init__(self, message)
56
57 58 -class Return(Envelope):
59 """ 60 Return envelope. 61 """ 62 63 @classmethod
64 - def succeed(cls, x):
65 """ 66 Return successful 67 @param x: The returned value. 68 @type x: any 69 @return: A return envelope. 70 @rtype: L{Return} 71 """ 72 return Return(retval=x)
73 74 @classmethod
75 - def exception(cls):
76 """ 77 Return raised exception. 78 @return: A return envelope. 79 @rtype: L{Return} 80 """ 81 info = sys.exc_info() 82 ex = '\n'.join(tb.format_exception(*info)) 83 return Return(exval=ex)
84
85 - def succeeded(self):
86 """ 87 Test whether the return indicates success. 88 @return: True when indicates success. 89 @rtype: bool 90 """ 91 return ( 'retval' in self )
92
93 - def failed(self):
94 """ 95 Test whether the return indicates failure. 96 @return: True when indicates failure. 97 @rtype: bool 98 """ 99 return ( not self.succeeded() )
100
101 102 -class Request(Envelope):
103 """ 104 An RMI request envelope. 105 """ 106 pass
107
108 109 -class RMI(object):
110 """ 111 The RMI object performs the invocation. 112 @ivar request: The request envelope. 113 @type request: L{Request} 114 @ivar catalog: A dict of class mappings. 115 @type catalog: dict 116 """ 117
118 - def __init__(self, request, catalog):
119 """ 120 @param request: The request envelope. 121 @type request: L{Request} 122 @param catalog: A dict of class mappings. 123 @type catalog: dict 124 """ 125 self.request = request 126 self.catalog = catalog
127
128 - def resolve(self):
129 """ 130 Resolve the class/method in the request. 131 @return: A tuple (inst, method) 132 @rtype: tuple 133 """ 134 inst = self.getclass() 135 method = self.getmethod(inst) 136 return (inst, method)
137
138 - def getclass(self):
139 """ 140 Get an instance of the class specified in 141 the request using the catalog. 142 @return: An instance of the class. 143 @rtype: object 144 """ 145 key = self.request.classname 146 inst = self.catalog.get(key, None) 147 if inst is None: 148 raise ClassNotFound(key) 149 return inst()
150
151 - def getmethod(self, inst):
152 """ 153 Get method of the class specified in the request. 154 Ensures that remote invocation is permitted. 155 @return: The requested method. 156 @rtype: instancemethod 157 """ 158 cn, fn = \ 159 (self.request.classname, 160 self.request.method) 161 if hasattr(inst, fn): 162 method = getattr(inst, fn) 163 if not mayinvoke(method): 164 raise NotPermitted(cn, fn) 165 return method 166 else: 167 raise MethodNotFound(cn, fn)
168
169 - def __call__(self):
170 """ 171 Invoke the method. 172 @return: The invocation result. 173 @rtype: L{Return} 174 """ 175 args, keywords = \ 176 (self.request.args, 177 self.request.kws) 178 try: 179 inst, method = self.resolve() 180 retval = method(*args, **keywords) 181 return Return.succeed(retval) 182 except: 183 return Return.exception()
184
185 - def __str__(self):
186 return str(self.request)
187
188 - def __repr__(self):
189 return str(self)
190
191 192 -class Dispatcher:
193 """ 194 The remote invocation dispatcher. 195 @ivar classes: The (catalog) of target classes. 196 @type classes: list 197 """ 198
199 - def __init__(self):
200 """ 201 """ 202 self.classes = {}
203
204 - def dispatch(self, request):
205 """ 206 Dispatch the requested RMI. 207 @param request: A request. 208 @type request: L{Request} 209 @return: The result. 210 @rtype: any 211 """ 212 request = Request(request) 213 rmi = RMI(request, self.classes) 214 log.info('dispatching:%s', rmi) 215 return rmi()
216
217 - def register(self, *classes):
218 """ 219 Register classes exposed as RMI targets. 220 @param classes: A list of classes 221 @type classes: [cls,..] 222 @return self 223 @rtype: L{Dispatcher} 224 """ 225 for cls in classes: 226 self.classes[cls.__name__] = cls 227 return self
228