locked
OpenLDAP XMA - How to sort the object classes in an ordered list RRS feed

  • General discussion

  •   ILM Knowledge Bit

    The OpenLDAP XMA that is available for download from sourceforge gives you a very robust Extensible Management Agent, allowing ILM (and FIM) to interact with many types of LDAP-compliant directory servers.

    One problem with the XMA as published is the fact that LDAP servers don't implement a way to make sure that multi-valued attributes are sent in a specific order. One victim of this is are the object classes of an object: as soon as an object instantiates multiple object classes, the LDAP server will give you a list of these classes, but you are never sure in which order you will receive them. This is problematic because ILM is rather picky on the definition of object classes for your objects.

    One solution to this problem is to adapt the source code of the OpenLDAP XMA. The OpenLDAPUtils.cs source code file contains a rountine called OutPutEntryToDSML that is responsible for formatting the entry that is sent to the intermediary file to be read by ILM. By modifying this function you can make sure that object classes are always sent to the DSML file in an ordered list.

    Replace the code for the existing OutputEntryToDSML function with the following code:

      private static void OutPutEntryToDsml(SearchResultEntry entry, string changeType, ArrayList binaries, ref XmlWriter w)
        {
          // Write the DSML output
          w.WriteStartElement("searchResultEntry");
          // write the DN to the result string
          w.WriteAttributeString("dn", entry.DistinguishedName.ToString());
    
          w.WriteStartElement("attr");
          w.WriteAttributeString("name", "changetype");
          w.WriteStartElement("value");
          w.WriteValue(changeType);
          w.WriteEndElement(); //value
          w.WriteEndElement(); //attr
    
    
          #region Supplied Attributes
          ///
          /// Supplied Attributes
          /// 
    
          // Write the attribute names and values to the result string
          foreach (DirectoryAttribute da in entry.Attributes.Values)
          {
            //
            // Only output the attribute if it is defined in the MA schema
            //
            //if (!m_attributesList.Contains(da.Name))
            //{
            //  continue;         
            //}
    
            // write the attribute Name to XML
            w.WriteStartElement("attr");
            w.WriteAttributeString("name", da.Name);
    
            #region OrderedObjectClasses - modified to make sure objectclasses are always in the same order
            //Objectclasses are are special case.
            //To aid with mapping objectclasses
            //on import, we need to write objectclass values
            //to the file in a consistent order.
            //The easiest way to do this is alphabetically.
            //Assumptions: objectClass values will never be binary or span lines
            if (da.Name.ToLower() == "objectclass")
            {
              SortedList orderedValues = new SortedList();
              foreach (string val in da.GetValues(typeof(string)))
              {
                orderedValues.Add(val.ToString(), val.ToString());
    
              }
              for (int i = 0; i < orderedValues.Count; i++)
              {
                w.WriteStartElement("value");
                w.WriteValue(orderedValues.GetByIndex(i).ToString());
                w.WriteEndElement(); // value
              }
            } //if name == "objectclass"
            else
            {
              foreach (string val in da.GetValues(typeof(string)))
              {
                // If the attribute is marked as Binary in the MA schema, then base64 encode it
                if (binaries.Contains(da.Name))
                {
                  w.WriteStartElement("value");
                  w.WriteAttributeString("xsi", "type", null, "xsd:base64Binary");
                  w.WriteBase64(Encoding.Unicode.GetBytes(val), 0, Encoding.Unicode.GetByteCount(val));
                  w.WriteEndElement(); // value
                }
                // If the attribute spans lines, then base64 encode it
                else if (val.IndexOf("\n") > 0 || val.IndexOf("\r") > 0)
                {
                  w.WriteStartElement("value");
                  w.WriteAttributeString("xsi", "type", null, "xsd:base64Binary");
                  w.WriteBase64(Encoding.Unicode.GetBytes(val), 0, Encoding.Unicode.GetByteCount(val));
                  w.WriteEndElement(); // value
                }
                else
                {
                  w.WriteStartElement("value");
                  w.WriteValue(val);
                  w.WriteEndElement(); // value
                }
    
              } //foreach (string val in da.GetValues(typeof(string)))
    
            } //else
    
            // Close the attr XML element
            w.WriteEndElement(); // attr
    
          } //foreach (DirectoryAttribute da in entry.Attributes.Values 
            #endregion // OrderedObjectClasses - modified to make sure objectclasses are always in the same order
          #endregion
    
          // Close the searchResultEntry XML element
          w.WriteEndElement(); // searchResultEntry
        } //OutPutEntryToDSML
    

    By implementing the code presented above and recompiling the XMA your object classes will now be presented to ILM in a fixed order. Also please note that this code works with the OpenLDAP XMA version 1.1 - the newer 1.2b1 package utilizes newer code that requires the presented code to be updated.

      Go to the ILM Knowledge Bit Collection

    • Edited by Paul Loonen Tuesday, November 9, 2010 2:06 PM
    Thursday, November 4, 2010 11:29 AM

All replies

  • This is great! Any chance you could get it ito the code on sourceforge? IMO it should work this way by default.
    http://www.wapshere.com/missmiis
    Friday, November 5, 2010 6:53 AM
  • Paul,

    I use the version 1.1 from the "OpenLDAP MA" of sourceforge.net.

    But in this source code I cannot find a file called "OpenLDAPUtils.cs". Where do I get this?

     

    best regards

    Michael

    Monday, November 8, 2010 11:56 AM
  • Michael,

    I don't remember whether you get the source code if you install the msi. If not, please access the source code here. You'll find the entire source tree unpacked, including the OpenLDAPUtils.cs file you're looking for.

    Paul.


    Paul Loonen (Avanade) | MCM: Directory 2008 | MVP: ILM
    Monday, November 8, 2010 1:14 PM
  • Paul,

    thank you for pointing me into the right direction. I had an old version and therefore I could not find the source file.

    I downloaded the new version and added your new function but the compiler is complaining. The signature of your function has four parameters and the deprecated one has only three. So I receive four errors.

    Is it safe to drop the parameter "binaries" if my agent does not have any "binary" attributes?

     

    best regards

    Michael

    Monday, November 8, 2010 5:03 PM
  • Michael,

    In version 1.1 of the OpenLDAP XMA, you would have the binaries parameter in the function call. I think that you are using the 1.2b1 package that was released a couple of days ago, and that has moved this to a global variable (m_binaries).

    I'll check what the further differences are to this piece of code and post an update when done. For now, if you want to use this code snippet you will need to use it with version 1.1 of the XMA. As Carol suggests, it may be worthwhile to contact the author of the XMA to have this added to published package ...

    Paul.


    Paul Loonen (Avanade) | MCM: Directory 2008 | MVP: ILM
    Tuesday, November 9, 2010 2:01 PM
  • Michael,

    In version 1.1 of the OpenLDAP XMA, you would have the binaries parameter in the function call. I think that you are using the 1.2b1 package that was released a couple of days ago, and that has moved this to a global variable (m_binaries).

    I'll check what the further differences are to this piece of code and post an update when done. For now, if you want to use this code snippet you will need to use it with version 1.1 of the XMA. As Carol suggests, it may be worthwhile to contact the author of the XMA to have this added to published package ...

    Paul.


    Paul Loonen (Avanade) | MCM: Directory 2008 | MVP: ILM


    Hi Paul,

     

    I'm looking into implementing your suggested change, to sort the objectclasses, but we're also using the V1.2b1 version (from source), instead of the V1.1 version.

     

    So, I've been looking at the V1.2b1 source, and it looks like all we would have to do is to change the code that you posted to use "m_binaries" instead of "binaries" to make the code that you posted compatible with the V1.2b1 source?

     

    Other than the section that you added to sort the objectclasses attributes, the rest of the posted code looks the same as the original V1.2b1 code?

     

    Thanks,

    Jim

    Tuesday, May 24, 2011 12:31 PM
  • has this code been updated to the new version yet?
    Friday, June 3, 2011 7:36 PM
  • has this code been updated to the new version yet?


    Hi,

     

    The latest on Sourceforge was 1.2b1 from October 2010.  Note that that 1.2b1 msi is a 64bit installer, i.e., it won't run on a 32-bit system.

     

    In any event, the source from the 1.2b1 version doesn't have the changes for the objectclass sort order.  Also, note that from the threads I've posted recently, we initially tried the 1.1 version, but had problems with that, mainly that it'd end up with duplicates in the CS on import, so what I had to do was to extract the source from the V1.2b1 MSI manually (we're running ILM on 32-bit Win2K3), and then build the DLL ourselves.

     

    Jim 

    Tuesday, June 7, 2011 2:30 AM
  • Jim:

     

    I should have been clearer. I wanted to know specifically for "object classes in an ordered list". Has that code been updated to the newer version 1.2b1.

     

    Thanks,

    Dan

    Tuesday, June 7, 2011 11:27 PM
  • Jim:

     

    I should have been clearer. I wanted to know specifically for "object classes in an ordered list". Has that code been updated to the newer version 1.2b1.

     

    Thanks,

    Dan

    Hi,

    I thought that I did mention that (1st sentence in my 2nd paragraph):

     

    "In any event, the source from the 1.2b1 version doesn't have the changes for the objectclass sort order. "

     

    Jim

    Wednesday, June 8, 2011 11:15 AM
  • "that this code works with the OpenLDAP XMA version 1.1 - the newer 1.2b1 package utilizes newer code that requires the presented code to be updated."

    anyone have updated version of the code that is suitable for 1.2b1 package ?
    Monday, December 5, 2011 12:03 PM
  • Hi Paul,

    Thanks for sharing this code. I am using OpenLDAP XMA version 1.2b1 and I have made the following changes in order for your code above to work with 1.2b1:

    1. remove the Bold text from the following line:                

                  private static void OutPutEntryToDsml(SearchResultEntry entry, string changeType, ArrayList binaries, ref XmlWriter w)

    end result: 

              private void OutPutEntryToDsml(SearchResultEntry entry, string changeType, ref XmlWriter w)

    2. Find and change the Bold text on the following line:

                 if (binaries.Contains(da.Name))

    To:

                if (m_binaries.Contains(da.Name))

    That is all there is to it.

    I have also made some changes to this source code to comply with FIM Delta import and other tasks… Will post it soon.


    Hailemichael


    Friday, January 11, 2013 6:41 PM
  • Hailemichel,

    Have you posted your Delta Import changes somewhere?  If so where can I find them?

    Thanks...

    Eric


    UF, Dept of Medicine

    Monday, February 18, 2013 3:15 PM