1 #----------------------------------------------------------------------
2 # Copyright (c) 2008 Board of Trustees, Princeton University
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and/or hardware specification (the "Work") to
6 # deal in the Work without restriction, including without limitation the
7 # rights to use, copy, modify, merge, publish, distribute, sublicense,
8 # and/or sell copies of the Work, and to permit persons to whom the Work
9 # is furnished to do so, subject to the following conditions:
11 # The above copyright notice and this permission notice shall be
12 # included in all copies or substantial portions of the Work.
14 # THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
22 #----------------------------------------------------------------------
26 from sfa.util.faults import SfaAPIError
28 # for convenience and smoother translation - we should get rid of these
29 # functions eventually
32 def get_leaf(hrn): return Xrn(hrn).get_leaf()
35 def get_authority(hrn): return Xrn(hrn).get_authority_hrn()
38 def urn_to_hrn(urn): xrn = Xrn(urn)
39 return (xrn.hrn, xrn.type)
42 def hrn_to_urn(hrn, type): return Xrn(hrn, type=type).urn
46 parenthrn, hrn): return Xrn.hrn_is_auth_for_hrn(parenthrn, hrn)
52 # split a HRN-like string into pieces
53 # this is like split('.') except for escaped (backslashed) dots
54 # e.g. hrn_split ('a\.b.c.d') -> [ 'a\.b','c','d']
57 return [x.replace('--sep--', '\\.') for x in hrn.replace('\\.', '--sep--').split('.')]
59 # e.g. hrn_leaf ('a\.b.c.d') -> 'd'
61 def hrn_leaf(hrn): return Xrn.hrn_split(hrn)[-1]
63 # e.g. hrn_auth_list ('a\.b.c.d') -> ['a\.b', 'c']
65 def hrn_auth_list(hrn): return Xrn.hrn_split(hrn)[0:-1]
67 # e.g. hrn_auth ('a\.b.c.d') -> 'a\.b.c'
69 def hrn_auth(hrn): return '.'.join(Xrn.hrn_auth_list(hrn))
71 # e.g. escape ('a.b') -> 'a\.b'
73 def escape(token): return re.sub(r'([^\\])\.', r'\1\.', token)
75 # e.g. unescape ('a\.b') -> 'a.b'
77 def unescape(token): return token.replace('\\.', '.')
79 # Return the HRN authority chain from top to bottom.
80 # e.g. hrn_auth_chain('a\.b.c.d') -> ['a\.b', 'a\.b.c']
82 def hrn_auth_chain(hrn):
83 parts = Xrn.hrn_auth_list(hrn)
85 for i in range(len(parts)):
86 chain.append('.'.join(parts[:i + 1]))
87 # Include the HRN itself?
91 # Is the given HRN a true authority over the namespace of the other
93 # A better alternative than childHRN.startswith(parentHRN)
94 # e.g. hrn_is_auth_for_hrn('a\.b', 'a\.b.c.d') -> True,
95 # but hrn_is_auth_for_hrn('a', 'a\.b.c.d') -> False
96 # Also hrn_is_auth_for_hrn('a\.b.c.d', 'a\.b.c.d') -> True
98 def hrn_is_auth_for_hrn(parenthrn, hrn):
101 for auth in Xrn.hrn_auth_chain(hrn):
102 if parenthrn == auth:
106 # basic tools on URNs
107 URN_PREFIX = "urn:publicid:IDN"
108 URN_PREFIX_lower = "urn:publicid:idn"
112 return text.lower().startswith(Xrn.URN_PREFIX_lower)
119 return Xrn.URN_PREFIX + urn
122 def urn_meaningful(urn):
124 return urn[len(Xrn.URN_PREFIX):]
130 return Xrn.urn_meaningful(urn).split('+')
133 def filter_type(urns=None, type=None):
142 if (xrn.type == type):
143 # Xrn is probably a urn so we can just compare types
147 # the local fields that are kept consistent
152 # provide either urn, or (hrn + type)
154 def __init__(self, xrn="", type=None, id=None):
157 # user has specified xrn : guess if urn or hrn
163 self.urn = "%s:%s" % (self.urn, str(id))
171 # happens all the time ..
173 # debug_logger.debug("type-less Xrn's are not safe")
176 result = "<XRN u=%s h=%s" % (self.urn, self.hrn)
177 if hasattr(self, 'leaf'):
178 result += " leaf=%s" % self.leaf
179 if hasattr(self, 'authority'):
180 result += " auth=%s" % self.authority
184 def get_urn(self): return self.urn
186 def get_hrn(self): return self.hrn
188 def get_type(self): return self.type
190 def get_hrn_type(self): return (self.hrn, self.type)
192 def _normalize(self):
194 raise SfaAPIError("Xrn._normalize")
195 if not hasattr(self, 'leaf'):
196 self.leaf = Xrn.hrn_split(self.hrn)[-1]
197 # self.authority keeps a list
198 if not hasattr(self, 'authority'):
199 self.authority = Xrn.hrn_auth_list(self.hrn)
205 def get_authority_hrn(self):
207 return '.'.join(self.authority)
209 def get_authority_urn(self):
211 return ':'.join([Xrn.unescape(x) for x in self.authority])
213 def set_authority(self, authority):
215 update the authority section of an existing urn
217 authority_hrn = self.get_authority_hrn()
218 if not authority_hrn.startswith(authority):
219 hrn = ".".join([authority, authority_hrn, self.get_leaf()])
221 hrn = ".".join([authority_hrn, self.get_leaf()])
227 # sliver_id_parts is list that contains the sliver's
228 # slice id and node id
229 def get_sliver_id_parts(self):
231 if self.type == 'sliver' or '-' in self.leaf:
232 sliver_id_parts = self.leaf.split('-')
233 return sliver_id_parts
235 def urn_to_hrn(self):
237 compute tuple (hrn, type) from urn
240 # if not self.urn or not self.urn.startswith(Xrn.URN_PREFIX):
241 if not Xrn.is_urn(self.urn):
242 raise SfaAPIError("Xrn.urn_to_hrn")
244 parts = Xrn.urn_split(self.urn)
246 # Remove the authority name (e.g. '.sa')
247 if type == 'authority':
249 # Drop the sa. This is a bad hack, but its either this
250 # or completely change how record types are generated/stored
252 type = type + "+" + name
255 name = parts.pop(len(parts) - 1)
256 # convert parts (list) into hrn (str) by doing the following
257 # 1. remove blank parts
258 # 2. escape dots inside parts
259 # 3. replace ':' with '.' inside parts
260 # 3. join parts using '.'
261 hrn = '.'.join([Xrn.escape(part).replace(':', '.')
262 for part in parts if part])
263 # dont replace ':' in the name section
265 parts = name.split(':')
267 self.id = ":".join(parts[1:])
269 hrn += '.%s' % Xrn.escape(name)
272 self.type = str(type)
274 def hrn_to_urn(self):
276 compute urn from (hrn, type)
279 # if not self.hrn or self.hrn.startswith(Xrn.URN_PREFIX):
280 if Xrn.is_urn(self.hrn):
281 raise SfaAPIError("Xrn.hrn_to_urn, hrn=%s" % self.hrn)
283 if self.type and self.type.startswith('authority'):
284 self.authority = Xrn.hrn_auth_list(self.hrn)
285 leaf = self.get_leaf()
286 # if not self.authority:
287 # self.authority = [self.hrn]
288 type_parts = self.type.split("+")
289 self.type = type_parts[0]
291 if len(type_parts) > 1:
293 auth_parts = [part for part in [
294 self.get_authority_urn(), leaf] if part]
295 authority_string = ":".join(auth_parts)
297 self.authority = Xrn.hrn_auth_list(self.hrn)
298 name = Xrn.hrn_leaf(self.hrn)
299 authority_string = self.get_authority_urn()
301 if self.type == None:
302 urn = "+".join(['', authority_string, Xrn.unescape(name)])
304 urn = "+".join(['', authority_string,
305 self.type, Xrn.unescape(name)])
307 if hasattr(self, 'id') and self.id:
308 urn = "%s:%s" % (urn, self.id)
310 self.urn = Xrn.URN_PREFIX + urn
312 def dump_string(self):
313 result = "-------------------- XRN\n"
314 result += "URN=%s\n" % self.urn
315 result += "HRN=%s\n" % self.hrn
316 result += "TYPE=%s\n" % self.type
317 result += "LEAF=%s\n" % self.get_leaf()
318 result += "AUTH(hrn format)=%s\n" % self.get_authority_hrn()
319 result += "AUTH(urn format)=%s\n" % self.get_authority_urn()