Using the Generic File Driver for importing Photos

User photos are used more and more by diverse systems and in many systems you can upload and change the photo yourself today.

Many users do this and as many don't. Depending on company policies some are not allowed to do it at all.

After using a variety of tools to import photos I once again had the task of doing this for a customer and thought I would do a try with the brilliant and free Generic File Driver that Stefaan Van Cauwenberge has written.

There are a couple of reasons for using this driver. First of all it's free and distributed under the MPL (Mozilla Public License) 2.0. But the really good reasons are that it is frequently updated and has a lot of nice features.

It also runs fine using the remote loader, you have to edit it manually if you run it on a windows remote loader though, more on that later.

Adding a photo from file to a user my first problem was how to connect it to the correct user. With the Generic File Driver there are a few built in attributes we can use. In this case we will utilize the attributes "filePath" and "fileName" that gives the complete path to the file and the file name. So just by naming the picture file to something like a CN or WorkforceID or any other unique attribute will solve that problem.

Another issue is to transform the file to something that eDirectory likes to store in the "photo" attribute and that can not only be synchronized to other systems but also displayed correctly.

That is done by an ecma script called "readImage" that is included by the standard NOVLLIBAJC-JS that has been around since IDM 3.6 at least.

The picture files are normal jpg and they need to be of a decent size since we will not do any formatting here.

To the driver setup. Begin with downloading Generic File Driver if you don't already have it and set it up as stated in the read-me.

I called my driver "User Photo Import". Open up the properties and go to the Driver Properties in Driver Configuration, there we remove all fields and write "photo" so we only have one attribute. For Object Class Name we keep User. Subscriber will not be used so we jump to the Publisher Options tab.

Here we want to change the Source folder for files to the folder we want to read the photos from, we also need to specify the Temporary work folder and these folders needs to be created if they don't exist. Later when a photo is read and processed it will automatically be moved to the work folder as a backup.

Regular expression for matching files will be (?i).*\.jpg since we are using jpg and not csv files. File reader strategy will also be CSVFileReader.

Next we add our ecma script file NOVLLIBAJC-JS under the ECMAScript tab. It will usually be in your library folder so it will look something like this:
NOVLLIBAJC-JS.Library.driverset.Identity Vault.

That completes the configuration of the driver, now we need to add a rule and change the filter.

Make sure we synchronize the User on the Publisher side, you can remove all default attributes and add just photo as notify on the publisher side.

Input Transform Policy Set
Create a new policy, I called mine "Import User Photo", in that policy you need to crate a rule like this one. In my case I match the file name with CN of the users since that is unique in my case.
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE policy PUBLIC "policy-builder-dtd" "C:\NetIQ\idm\apps\Designer\plugins\com.novell.idm.policybuilder_4.0.0.201509291552\DTD\dirxmlscript4.5.1.dtd"><policy>
<description>Read the user CN from the filename and update the user photo</description>
<if-class-name mode="nocase" op="equal">User</if-class-name>
<if-op-attr name="photo" op="available"/>
<do-set-local-variable name="varName" scope="policy">
<token-replace-all regex="\.jpg" replace-with="">
<token-op-attr name="fileName"/>
<do-set-local-variable name="varFilePath" scope="policy">
<token-op-attr name="filePath"/>
<do-set-local-variable name="varUser" scope="policy">
<token-query class-name="User">
<arg-match-attr name="CN">
<arg-value type="string">
<token-local-variable name="varName"/>
<token-text xml:space="preserve">CN</token-text>
<do-set-dest-attr-value direct="true" name="photo">
<token-xpath expression="$varUser/@src-dn"/>
<arg-value type="octet">
<token-xpath expression="es:readImage($varFilePath)"/>

I think it is quite self explained when you see it imported in designer but here is what it does:

First we read the name of the file into a variable without the trailing.jpg then we read in the filepath into another variable. This is just to make the code easier to read.

After that we query for the user that has that cn we got from the filename.

When we got the users dn we update the photo attribute directly so we don't have to mess with filters, associations etc.

Finally we veto off the event.

Remote loader on windows
This is what I do:

Add a new driver to the remote loader and at the dialog where you are supposed to choose the class just pick any java class.

When the configuration is done you edit the .txt file and change the class manually there.

You also need to edit the registry and paste in the class name there too.

The classname is:

The registry entry is something like:

depending on what you called the remote driver instance.

You obviously need to copy the correct jar file to the remote loader folder but that is outlined in the setup documentation.



How To-Best Practice
Comment List
  • This gives me the idea to include a 'raw data' reader (and writer) in the Generic File Driver. This would avoid the ecmascript policy (although not that complicated). Downside would be that the foto is in all your events, cluttering up your trace level 3. Setting is-sensitive in the input transformation could solve that.
  • This gives me the idea to include a 'raw data' reader (and writer) in the Generic File Driver. This would avoid the ecmascript policy (although not that complicated). Downside would be that the foto is in all your events, cluttering up your trace level 3. Setting is-sensitive in the input transformation could solve that.
  • That would be really cool and a great enhancement.
    I think photos are what most have as raw data that need to come from files or get written to file for that matter. But of cause there are other types of raw data as well.

    What could be done is to have a unique naming scheme for the files as "useridentifier-attribute.raw" that way it would be easy for the driver to know what to do as well as it would be fairly easy for the person/process that places or reads the files.
    But I'm sure you already got some idea on how to solve this :-)