4865N/A#!/usr/bin/python
4865N/A
4865N/A# CDDL HEADER START
4865N/A#
4865N/A# The contents of this file are subject to the terms of the
4865N/A# Common Development and Distribution License, Version 1.0 only
4865N/A# (the "License"). You may not use this file except in compliance
4865N/A# with the License.
4865N/A#
6982N/A# You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
6982N/A# or http://forgerock.org/license/CDDLv1.0.html.
4865N/A# See the License for the specific language governing permissions
4865N/A# and limitations under the License.
4865N/A#
4865N/A# When distributing Covered Code, include this CDDL HEADER in each
6982N/A# file and include the License file at legal-notices/CDDLv1_0.txt.
6982N/A# If applicable, add the following below this CDDL HEADER, with the
6982N/A# fields enclosed by brackets "[]" replaced with your own identifying
4865N/A# information:
4865N/A# Portions Copyright [yyyy] [name of copyright owner]
4865N/A#
4865N/A# CDDL HEADER END
4865N/A#
4865N/A#
4865N/A# Copyright 2009 Sun Microsystems, Inc.
4865N/A
4865N/A
4865N/A
4865N/A
4865N/A
4865N/A# Global variable containing the list of servers ("Server" class instances) deployed
4865N/A
4865N/A
4865N/A
4865N/A# Define ChangelogServer class
4865N/Aclass OIDDict:
4865N/A """OIDDict is a dictionary class that help lookup OID <-> litteral name
4865N/A of both objeclasses, and attributtypes"""
4865N/A
4865N/A def __init__(self, schema=None):
4974N/A self.attrDict = {}
4974N/A self.objDict = {}
4865N/A self.sup = {}
4865N/A self.may = {}
4865N/A self.must = {}
4974N/A self.allmay = []
4974N/A self.allmust = []
4865N/A
4865N/A def _getOID(self, line):
4865N/A """given a schema entry definition for objectclass/attributtype
4865N/A return the tuple (OID,List of names)
4865N/A the List of aliases starts from list of names[1:] when exist. for ex :
4865N/A attributeTypes: ( 2.5.4.4 NAME ( 'sn' 'surname' ) SUP name X-ORIGIN 'RFC 4519' )
4865N/A (2.5.4.4,['sn','surname']
4974N/A More details : https://www.opends.org/wiki/page/AttributeTypeDescriptionFormat
4865N/A """
4865N/A pNdx = line.find('(')
4865N/A nNdx = line.find('NAME',pNdx)
4865N/A OID = line[pNdx+1:nNdx].strip()
4865N/A
4865N/A # populate the NAME to OID : "dict" dictionary
4865N/A NAMES = self._getStr(line,'NAME')
4865N/A if NAMES:
4974N/A if line.startswith('objectClasses:'):
4974N/A # TODO encoded schema is not handled for now
4974N/A self.objDict.update({OID:NAMES})
4974N/A for name in NAMES:
4974N/A self.objDict.update({name:OID})
4974N/A elif line.startswith('attributeTypes:'):
4974N/A # TODO encoded schema is not handled for now
4974N/A self.attrDict.update({OID:NAMES})
4974N/A for name in NAMES:
4974N/A self.attrDict.update({name:OID})
4974N/A # populate SUP and MUST / MAY, : "sup", "may", "must" dictionaries
4865N/A if line.startswith('objectClasses:'):
4865N/A r = self._getStr(line,'SUP')
4865N/A if r:
4865N/A self.sup.update({NAMES[0]:r})
4865N/A r = self._getStr(line,'MUST')
4865N/A if r:
4865N/A self.must.update({NAMES[0]:r})
4974N/A for m in r:
4974N/A if not m in self.allmust:
4974N/A self.allmust.append(m)
4865N/A r = self._getStr(line,'MAY')
4865N/A if r:
4865N/A self.may.update({NAMES[0]:r})
4974N/A for m in r:
4974N/A if not m in self.allmay:
4974N/A self.allmay.append(m)
4865N/A
4865N/A return OID, NAMES
4865N/A
4865N/A def _getStr(self, line, myStr, right=None):
4865N/A """extract a list of attributes for a given myStr section.
4865N/A The section should contain () when multivalued.
4865N/A If another section comes after it starts with a Upercase.
4865N/A example MUST (sn cn) MAY ( description ... )
4865N/A
4865N/A line : line to parse
4865N/A myStr : name of the section ex(MAY)
4865N/A right : right boundary,
4865N/A if None, function will figure out end of section"""
4865N/A left = line.find(myStr)
4865N/A if left == -1:
4865N/A return None
4865N/A
4865N/A if not right:
4865N/A right = len(line)
4865N/A lpNdx = line.find('(', left)
4865N/A if lpNdx > 0:
4865N/A spaces=line[left+len(myStr) : lpNdx]
4865N/A if len(spaces.strip()) == 0:
4865N/A right = line.find(')',lpNdx)
4865N/A left = lpNdx + 1
4865N/A else:
4865N/A left = left+len(myStr)+1
4865N/A else:
4865N/A left = left+len(myStr)
4865N/A strs = line[left:right]
4865N/A realStrs = []
4865N/A for s in strs.split(' '):
4865N/A if len(s) > 0:
4865N/A if s[0] >= 'A' and s[0] <= 'Z':
4865N/A break
4865N/A elif s[0] != '$' and s[0] != '|':
4865N/A if s[0] == '\'' and s[-1] == '\'':
4865N/A s = s[1:-1]
4974N/A realStrs.append(s.lower())
4865N/A return realStrs
4865N/A
4865N/A def getMust(self, objectclassname):
4865N/A """will return the attributes the objectclassname MUST implement"""
4865N/A if self.must.has_key(objectclassname):
4865N/A ret = self.must.get(objectclassname)
4865N/A else:
4865N/A ret = []
4865N/A for h in self.getHierarchy(objectclassname):
4865N/A # avoiding duplication of MUSTs
4865N/A ret.extend([e for e in self.getMust(h) if ret.count(e) == 0])
4865N/A return ret
4865N/A
4865N/A def getMay(self, objectclassname):
4865N/A """will return the attributes the objectclassname MAY implement"""
4865N/A if self.may.has_key(objectclassname):
4865N/A ret = self.may.get(objectclassname)
4865N/A else:
4865N/A ret = []
4865N/A for h in self.getHierarchy(objectclassname):
4865N/A # avoiding duplication of MAYs
4865N/A ret.extend([e for e in self.getMay(h) if ret.count(e) == 0])
4865N/A return ret
4865N/A
4865N/A def getSup(self, objectclassname):
4865N/A """will return the objectclassname that this objectclassname inherit"""
4865N/A if objectclassname == 'top':
4865N/A return None
4865N/A else:
4865N/A ret = self.sup.get(objectclassname)
4865N/A return ret[0]
4865N/A
4865N/A def getHierarchy(self, objectclassname):
4865N/A hierachy = []
4865N/A up = self.getSup(objectclassname)
4865N/A while up:
4865N/A if hierachy.count(up) == 0:
4865N/A hierachy.append(up)
4865N/A up = self.getSup(up)
4865N/A return hierachy
4865N/A
4865N/A
4865N/A def parseSchema(self, ref_content):
4865N/A """get the schema as a string
4865N/A lookit up line by line, extracting OID/literal name for objectclasses
4865N/A and attributetypes only."""
4865N/A lines=[]
4865N/A line=''
4974N/A for f in ref_content.splitlines():
4865N/A if len(line) == 0 and \
4865N/A not (f.startswith("objectClasses") or \
4865N/A f.startswith("attributeTypes")):
4865N/A # not handled for now
4865N/A continue
4974N/A elif len(line) > 0 and len(f) > 0 and f[0].isspace():
4865N/A # line continuation aggregated into 'line'
4974N/A line += f[1:]
4865N/A
4865N/A elif f.startswith("objectClasses") or f.startswith("attributeTypes"):
4865N/A if len(line) > 0:
4865N/A lines.append(line)
4865N/A # populate the OID <-> Names dictionary
4865N/A self._getOID(line)
4974N/A line = f[:-1]
4974N/A line = f
4865N/A if len(line) > 0:
4974N/A # parsing the last line
4974N/A self._getOID(line)
4865N/A lines.append(line)
4974N/A f=open('/tmp/lines.ldif','w')
4974N/A f.write('\n'.join(lines))
4974N/A f.close()
4865N/A
4865N/Aif __name__ == '__main__':
4865N/A """get example schema.ldif file with :
4974N/A ldapsearch -b 'cn=schema' -Dcn=directory\ manager -s base -wpassword objectclass=* objectClasses attributeTypes > /tmp/schema.ldif
4865N/A """
4865N/A objectClassesFileName='/tmp/schema.ldif'
4865N/A f = open(objectClassesFileName)
4865N/A fc = f.readlines()
4865N/A f.close()
4865N/A oidDict = OIDDict()
4974N/A oidDict.parseSchema(''.join(fc))
4974N/A print '[ Objectclasses dictionary ]'.center(80, '-')
4974N/A for k,v in oidDict.objDict.items():
4974N/A print "%s\t%s"%(k,v)
4974N/A print '[ AttributeTypes dictionary ]'.center(80, '-')
4974N/A for k,v in oidDict.attrDict.items():
4865N/A print "%s\t%s"%(k,v)
4865N/A print '[ must ]'.center(80, '-')
4865N/A for k,v in oidDict.must.items():
4865N/A print "%s\t%s"%(k,v)
4865N/A print '[ may ]'.center(80, '-')
4865N/A for k,v in oidDict.may.items():
4865N/A print "%s\t%s"%(k,v)
4865N/A print '[ sup ]'.center(80, '-')
4865N/A for k,v in oidDict.sup.items():
4865N/A print "%s\t%s"%(k,v)
4865N/A for cn in ['rFC822LocalPart','inetOrgPerson','top','doMain','2.5.6.7','BLAH']:
4865N/A print cn.center(80, '-')
4865N/A try:
4865N/A print 'SUP'.center(40,'.')
4865N/A print 'SUP',oidDict.getSup(cn)
4865N/A print 'HIERARCHY',oidDict.getHierarchy(cn)
4865N/A print 'MUST'.center(40,'.')
4865N/A print 'MUST',oidDict.getMust(cn)
4865N/A print 'MAY'.center(40,'.')
4865N/A print 'MAY',oidDict.getMay(cn)
4865N/A except Exception, e:
4865N/A print e.message
4974N/A print '[ all must ]'.center(80,'-')
4974N/A mustSize = 0
4974N/A for m in oidDict.allmust:
4974N/A mustSize += len(m)
4974N/A print 'got %s MUSTs size = %sKb' % (len(oidDict.allmust),mustSize/1024.0)
4974N/A print oidDict.allmust
4974N/A print '[ all may ]'.center(80,'-')
4974N/A maySize = 0
4974N/A for m in oidDict.allmay:
4974N/A maySize += len(m)
4974N/A print 'got %s MAYs size = %sKb' % (len(oidDict.allmay),maySize/1024.0)
4974N/A print oidDict.allmay