diff --git a/bin/dm-update-user-from-aps-db b/bin/dm-update-user-from-aps-db
new file mode 100755
index 0000000000000000000000000000000000000000..415a875f624197ecd44b5e01e3e5a9b92442cb12
--- /dev/null
+++ b/bin/dm-update-user-from-aps-db
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Run command
+
+if [ -z $DM_ROOT_DIR ]; then
+    cd `dirname $0` && myDir=`pwd`
+    setupFile=$myDir/../setup.sh
+    if [ ! -f $setupFile ]; then
+        echo "Cannot find setup file: $setupFile"
+        exit 1
+    fi
+    source $setupFile > /dev/null
+fi
+source dm_command_setup.sh
+
+eval "$DM_ROOT_DIR/src/python/dm/aps_user_db/cli/updateUserFromApsDbCli.py $DM_COMMAND_ARGS"
+
+
diff --git a/bin/dm-update-users-from-aps-db b/bin/dm-update-users-from-aps-db
new file mode 100755
index 0000000000000000000000000000000000000000..8856b653c42a6176ce642866590b49f85140c1e6
--- /dev/null
+++ b/bin/dm-update-users-from-aps-db
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Run command
+
+if [ -z $DM_ROOT_DIR ]; then
+    cd `dirname $0` && myDir=`pwd`
+    setupFile=$myDir/../setup.sh
+    if [ ! -f $setupFile ]; then
+        echo "Cannot find setup file: $setupFile"
+        exit 1
+    fi
+    source $setupFile > /dev/null
+fi
+source dm_command_setup.sh
+
+eval "$DM_ROOT_DIR/src/python/dm/aps_user_db/cli/updateUsersFromApsDbCli.py $DM_COMMAND_ARGS"
+
+
diff --git a/src/python/dm/aps_user_db/cli/updateUserFromApsDbCli.py b/src/python/dm/aps_user_db/cli/updateUserFromApsDbCli.py
index 130333f68bd437eac6b547ca456f90811d8da30d..c23b42808a8d42309cbe3e9e1dd4fdeee61a2023 100755
--- a/src/python/dm/aps_user_db/cli/updateUserFromApsDbCli.py
+++ b/src/python/dm/aps_user_db/cli/updateUserFromApsDbCli.py
@@ -1,44 +1,62 @@
 #!/usr/bin/env python
 
+import os
 from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.exceptions.objectNotFound import ObjectNotFound
+from dm.common.exceptions.invalidArgument import InvalidArgument
 from dm.common.cli.dmCli import DmCli
 from dm.common.utility.ldapUserManager import LdapUserManager
+from dm.common.utility.configurationManager import ConfigurationManager
 from dm.aps_user_db.api.apsUserDbApi import ApsUserDbApi
 
 class UpdateUserFromApsDbCli(DmCli):
     def __init__(self):
         DmCli.__init__(self)
         self.addOption('', '--badge', dest='badge', help='User badge number.')
+        self.addOption('', '--config-file', dest='configFile', help='Utility configuration file.')
 
     def checkArgs(self):
         if self.options.badge is None:
             raise InvalidRequest('Badge number must be provided.')
+        configFile = self.options.configFile
+        if configFile is None:
+            raise InvalidRequest('Config file must be provided.')
+        if not os.path.exists(configFile):
+            raise InvalidArgument('Invalid config file: %s.', configFile)
 
     def getBadge(self):
         return self.options.badge
 
     def runCommand(self):
         self.parseArgs(usage="""
-    dm-update-user-from-aps-db --badge=BADGE
+    dm-update-user-from-aps-db --badge=BADGE --config-file=CONFIGFILE
 
 Description:
     Updates user in DM LDAP and database using information from APS DB. 
         """)
+        ConfigurationManager.getInstance().setConfigFile(self.options.configFile)
         self.checkArgs()
         apsUserDbApi = ApsUserDbApi()
-        badgeNumber = self.getBadge()
-        username = 'd%s' % badgeNumber
-        apsUser = apsUserDbApi.getApsUserByBadgeNumber(badgeNumber)
-        print 'APS User Info: ', apsUser.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
-        ldapUserManager = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000)
-        ldapUser = ldapUserManager.getUserInfo(username)
-        print 'Old LDAP User Info: ', ldapUser
-        attrDict = {}
-        attrDict['gecos'] = apsUser['name']
-        attrDict['userPassword'] = apsUser['passwordHashValue']
-        ldapUserManager.modifyUserInfo(username, attrDict)
-        ldapUser = ldapUserManager.getUserInfo(username)
-        print 'New LDAP User Info: ', ldapUser
+        badge = self.getBadge()
+        username = 'd%s' % badge
+        apsUser = apsUserDbApi.getApsUserByBadgeNumber(badge)
+        #print 'APS User Info: ', apsUser.getDisplayString(self.getDisplayKeys(), self.getDisplayFormat())
+        print 'APS User Info: ', apsUser
+        print 
+        ldapUserManager = LdapUserManager.createInstance()
+        try:
+            self.logger.debug('Modifying LDAP user with badge %s: %s' % (badge, apsUser['name']))
+            ldapUser = ldapUserManager.getUserInfo(username)
+            print 'LDAP User Info (before update): ', ldapUser
+            print 'LDAP User Password Hash (before update): ', ldapUserManager.decodePasswordHash(ldapUser.getUserPassword())
+            print
+            ldapUserManager.modifyUserInfo(username, apsUser)
+            ldapUser = ldapUserManager.getUserInfo(username)
+        except ObjectNotFound, ex:
+            self.logger.debug('User with badge %s does not exist, creating it' % (badge))
+            ldapUser = ldapUserManager.createUserInfo(username, apsUser)
+        print 'LDAP User Info (after update): ', ldapUser
+        print 'LDAP User Password Hash (after update): ', ldapUserManager.decodePasswordHash(ldapUser.getUserPassword())
 
 #######################################################################
 # Run command.
diff --git a/src/python/dm/aps_user_db/cli/updateUsersFromApsDbCli.py b/src/python/dm/aps_user_db/cli/updateUsersFromApsDbCli.py
index 8b13a52746dfa7de0ebd198fe15ab70b1bdda38f..8da0baef1f613d88c7f33cea2f5ec48bb2a7325f 100755
--- a/src/python/dm/aps_user_db/cli/updateUsersFromApsDbCli.py
+++ b/src/python/dm/aps_user_db/cli/updateUsersFromApsDbCli.py
@@ -1,8 +1,12 @@
 #!/usr/bin/env python
 
 import datetime
+import os
 from dm.common.exceptions.invalidRequest import InvalidRequest
+from dm.common.exceptions.invalidArgument import InvalidArgument
+from dm.common.exceptions.objectAlreadyExists import ObjectAlreadyExists
 from dm.common.cli.dmCli import DmCli
+from dm.common.db.api.userDbApi import UserDbApi 
 from dm.common.utility.configurationManager import ConfigurationManager
 from dm.common.utility.ldapUserManager import LdapUserManager
 from dm.aps_user_db.api.apsUserDbApi import ApsUserDbApi
@@ -11,39 +15,83 @@ from dm.ds_web_service.api.dsRestApiFactory import DsRestApiFactory
 class UpdateUsersFromApsDbCli(DmCli):
     def __init__(self):
         DmCli.__init__(self)
+        self.addOption('', '--config-file', dest='configFile', help='Utility configuration file.')
+        self.addOption('', '--without-dm-db', dest='withoutDmDb', action='store_true', default=False, help='Do not use DM DB for synchronizing user information.')
+        self.addOption('', '--use-dm-rest-api', dest='useDmRestApi', action='store_true', default=False, help='Use DM REST API for accessing user information. This option does not have any effect if --without-dm-db is set.')
+
+    def checkArgs(self):
+        configFile = self.options.configFile
+        if configFile is None:
+            raise InvalidRequest('Config file must be provided.')
+        if not os.path.exists(configFile):
+            raise InvalidArgument('Invalid config file: %s.', configFile)
 
     def runCommand(self):
         self.parseArgs(usage="""
-    dm-update-users-from-aps-db 
+    dm-update-users-from-aps-db --config-file=CONFIGFILE
+        [--without-dm-db]
+        [--use-dm-rest-api]
 
 Description:
-    Updates all users in DM LDAP and database using information from APS DB. 
+    Updates all users in DM LDAP and database using information from APS DB. This command by default uses DM DB to determine whether or not user needs to be created or updated. If the --without-dm-db flag is set, DM DB will not be used nor it will be updated.
         """)
-        ConfigurationManager.getInstance().setConfigFile('/home/oxygen/SVESELI/Work/DM/etc/dm.conf')
+        self.checkArgs()
+        ConfigurationManager.getInstance().setConfigFile(self.options.configFile)
         self.logger.debug('Starting sync process')
         apsUserDbApi = ApsUserDbApi()
-        userRestApi = DsRestApiFactory.getUserRestApi()
+        ldapUserManager = LdapUserManager.createInstance()
+
+        # Get DM user API
+        dmUserApi = None
+        if not self.options.withoutDmDb:
+            try:
+                if self.options.useDmRestApi:
+                    self.logger.debug('Using DM REST API')
+                    dmUserApi = DsRestApiFactory.getUserRestApi()
+                else:
+                    self.logger.debug('Using DM DB API')
+                    dmUserApi = UserDbApi()
+            except Exception, ex:
+                self.logger.error('Cannot use DM DB: %s' % ex)
 
         self.logger.debug('Retrieving APS users')
         apsUsers = apsUserDbApi.getApsUsers()
         self.logger.debug('Number of APS Users: %s' % len(apsUsers))
-        self.logger.debug('Retrieving DM users')
-        dmUsers = userRestApi.getUsers()
-        self.logger.debug('Number of DM Users: %s' % len(dmUsers))
-        dmUserBadgeMap = {}
-        for dmUser in dmUsers:
-            badge = dmUser.get('badge')
-            if badge: 
-                dmUserBadgeMap[badge] = dmUser
-        self.logger.debug('Number of DM Users with badge: %s' % len(dmUserBadgeMap))
+
+        # Retrieve DM users from DB if we got DM user API
+        dmUserMap = {}
+        if dmUserApi:
+            self.logger.debug('Retrieving DM users from DB')
+            try:
+                nDmUsersWithBadge = 0
+                dmUsers = dmUserApi.getUsers()
+                self.logger.debug('Number of DM Users: %s' % len(dmUsers))
+                for dmUser in dmUsers:
+                    username = dmUser.get('username')
+                    if dmUser.get('badge'):
+                        nDmUsersWithBadge += 1
+                    dmUserMap[username] = dmUser
+                self.logger.debug('Number of DM Users with badge: %s' % nDmUsersWithBadge)
+            except Exception, ex:
+                self.logger.error('Error retrieving users from DM DB: %s' % ex)
+                dmUserApi = None
+
+        # We cannot use DM user API, retrieve users from LDAP
+        if not dmUserApi:
+            self.logger.debug('Retrieving DM users using LDAP client')
+            dmUserMap = ldapUserManager.getUserInfoMapByUid()
+            self.logger.debug('Number of DM LDAP Users: %s' % len(dmUserMap))
 
         nCreatedUsers = 0
         nUpdatedUsers = 0
+        nErrors = 0
         for apsUser in apsUsers:
             apsLastChangeDate = apsUser.get('lastChangeDate')
 
+            # DM DB attributes
             badge = apsUser['badgeNumber']
             username = 'd%s' % badge
+
             firstName = apsUser.get('firstName')
             middleName = apsUser.get('middleName')
             lastName = apsUser.get('lastName')
@@ -54,43 +102,98 @@ Description:
             description = None
             password = None
 
-            dmUser = dmUserBadgeMap.get(badge)
+            # LDAP attributes
+            ldapModAttrDict = {}
+            ldapModAttrDict['gecos'] = apsUser['name']
+            ldapModAttrDict['userPassword'] = apsUser['passwordHashValue']
+
+            dmUser = dmUserMap.get(username)
             if not dmUser:
-                self.logger.debug('Creating user with badge %s: %s' % (badge, apsUser['name']))
+                # We must create user in LDAP/DM DB
+                try:
+                    try:
+                        self.logger.debug('Creating LDAP user with badge %s: %s' % (badge, apsUser['name']))
+                        ldapUser = ldapUserManager.createUserInfo(username, apsUser)
+                    except ObjectAlreadyExists, ex:
+                        # LDAP user already exists, simply update it.
+                        self.logger.debug('LDAP user with badge %s already exists, attempting to modify it' % (badge))
+                        ldapUserManager.modifyUserInfo(username, ldapModAttrDict)
+                except Exception, ex:
+                    self.logger.error('LDAP problem caught while creating user with badge %s: %s' % (badge, str(ex)))
+                    nErrors += 1
+                    continue
 
-                userRestApi.addUser(username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
-                nCreatedUsers += 1
+                if dmUserApi:
+                    try:
+                        self.logger.debug('Creating DM DB user with badge %s: %s' % (badge, apsUser['name']))
+                        dmUserApi.addUser(username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
+                        nCreatedUsers += 1
+                    except Exception, ex:
+                        self.logger.error('DM DB problem caught while creating user with badge %s: %s' % (badge, str(ex)))
+                        nErrors += 1
+                        continue
             else:
-                dmLastUpdate = dmUser.get('lastUpdate')
-                if dmLastUpdate:
-                    # need to convert DM last update time to datetime object
-                    # datetime cannot handle time zone at the moment
-                    timeZonePos = dmLastUpdate.rfind('-')
-                    dmLastUpdate = dmLastUpdate[0:timeZonePos]
-                    dmLastUpdate = datetime.datetime.strptime(dmLastUpdate, '%Y-%m-%d %H:%M:%S')
-                if not dmLastUpdate or dmLastUpdate < apsLastChangeDate:
-                    id = dmUser.get('id')
-                    self.logger.debug('Modifying user with badge %s: %s (DM id: %s)' % (badge, apsUser['name'], id))
-                    print apsUser
-                    userRestApi.updateUser(id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
-                    nUpdatedUsers += 1
+                # User already exists, simply update it.
+
+                if dmUserApi:
+                    # We have DM DB API
+                    dmLastUpdate = str(dmUser.get('lastUpdate'))
+                    if dmLastUpdate:
+                        # need to convert DM last update time to datetime object
+                        # datetime cannot handle time zone at the moment
+                        timeZonePos = dmLastUpdate.rfind('-')
+                        dmLastUpdate = dmLastUpdate[0:timeZonePos]
+                        dmLastUpdate = datetime.datetime.strptime(dmLastUpdate, '%Y-%m-%d %H:%M:%S')
+                    if not dmLastUpdate or dmLastUpdate < apsLastChangeDate:
+                        # User needs update
+                        try:
+                            self.logger.debug('Modifying LDAP user with badge %s, username %s' % (badge, username))
+                            ldapUserManager.modifyUserInfo(username, ldapModAttrDict)
+                        except Exception, ex:
+                            self.logger.error('LDAP problem caught while modifying user with badge %s: %s' % (badge, str(ex)))
+                            nErrors += 1
+                            continue
+
+                        try:
+                            id = dmUser.get('id')
+                            self.logger.debug('Modifying DM DB user with badge %s: %s (DM id: %s)' % (badge, apsUser['name'], id))
+                            dmUserApi.updateUser(id, username, firstName, lastName, middleName, email, badge, globusUsername, description, password, isLocalUser, lastUpdate)
+                            nUpdatedUsers += 1
+                        except Exception, ex:
+                            self.logger.error('DM DB problem caught while modifying user with badge %s: %s' % (badge, str(ex)))
+                            nErrors += 1
+                            continue
+                    else:
+                        # User is up to date
+                        continue
                 else:
-                    # User is up to date
-                    pass
-           
+                    # No DM DB API
+                    apsPasswordHash = apsUser['passwordHashValue']
+                    dmPasswordHash = ldapUserManager.decodePasswordHash(dmUser['userAttrs']['userPassword'][0])
+                    if apsPasswordHash != dmPasswordHash:
+                        # User needs update
+                        try:
+                            self.logger.debug('Modifying LDAP user with badge %s, username %s' % (badge, username))
+                            self.logger.debug('APS password hash: %s, DM password hash: %s' % (apsPasswordHash, dmPasswordHash))
+                            self.logger.debug('Encoded DM password hash: %s' % (dmUser['userAttrs']['userPassword'][0]))
+                            ldapUserManager.modifyUserInfo(username, ldapModAttrDict)
+                            nUpdatedUsers += 1
+                        except Exception, ex:
+                            self.logger.error('LDAP problem caught while modifying user with badge %s: %s' % (badge, str(ex)))
+                            nErrors += 1
+                            continue
+                    else:       
+                        # User is up to date
+                        continue
+
         self.logger.debug('Number of new DM users: %s' % (nCreatedUsers))
         self.logger.debug('Number of updated DM users: %s' % (nUpdatedUsers))
+        self.logger.debug('Number of update errors: %s' % (nErrors))
         self.logger.debug('Completed sync process')
 
-        #ldapUserManager = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000)
-        #ldapUser = ldapUserManager.getUserInfo(username)
-        #print 'Old LDAP User Info: ', ldapUser
-        #attrDict = {}
-        #attrDict['gecos'] = apsUser['name']
-        #attrDict['userPassword'] = apsUser['passwordHashValue']
-        #ldapUserManager.modifyUserInfo(username, attrDict)
-        #ldapUser = ldapUserManager.getUserInfo(username)
-        #print 'New LDAP User Info: ', ldapUser
+        print('Number of new DM users: %s' % (nCreatedUsers))
+        print('Number of updated DM users: %s' % (nUpdatedUsers))
+        print('Number of update errors: %s' % (nErrors))
 
 #######################################################################
 # Run command.
diff --git a/src/python/dm/aps_user_db/impl/apsUserDbManager.py b/src/python/dm/aps_user_db/impl/apsUserDbManager.py
index 1f7d169456ab5727fb1c8f0a393b4bc8ad710c14..191319fa313e937071f945dba315af0d0795b711 100755
--- a/src/python/dm/aps_user_db/impl/apsUserDbManager.py
+++ b/src/python/dm/aps_user_db/impl/apsUserDbManager.py
@@ -24,7 +24,13 @@ class ApsUserDbManager:
     DB_CONNECTION_LOGGING_FLAG = False
 
     CONFIG_SECTION_NAME = 'ApsUserDbManager'
-    CONFIG_OPTION_NAME_LIST = [ 'dbHost', 'dbPort', 'dbUser', 'dbPasswordFile', 'dbName', 'dbSchema'  ]
+    DB_KEY = 'db'
+    DB_USER_KEY = 'dbuser'
+    DB_HOST_KEY = 'dbhost'
+    DB_PORT_KEY = 'dbport'
+    DB_NAME_KEY = 'dbname'
+    DB_SCHEMA_KEY = 'dbschema'
+    DB_PASSWORD_FILE_KEY = 'dbpasswordfile'
 
     # Singleton.
     __lock = threading.RLock()
@@ -39,6 +45,25 @@ class ApsUserDbManager:
             mgr = ex
         return mgr 
 
+    def __configure(self):
+        cm = ConfigurationManager.getInstance()
+        self.logger.debug('Configuring APS User DB Manager')
+        self.db = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_KEY)
+        self.logger.debug('Using APS DB: %s' % self.db)
+        self.dbUser = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_USER_KEY)
+        self.logger.debug('Using APS DB user: %s' % self.dbUser)
+        self.dbHost = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_HOST_KEY)
+        self.logger.debug('Using APS DB host: %s' % self.dbHost)
+        self.dbPort = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_PORT_KEY)
+        self.logger.debug('Using APS DB port: %s' % self.dbPort)
+        self.dbName = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_NAME_KEY)
+        self.logger.debug('Using APS DB name: %s' % self.dbName)
+        self.dbSchema = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_SCHEMA_KEY)
+        self.logger.debug('Using APS DB schema: %s' % self.dbSchema)
+        self.dbPasswordFile = cm.getConfigOption(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.DB_PASSWORD_FILE_KEY)
+        self.logger.debug('Using APS DB password file: %s' % self.dbPasswordFile)
+        self.dbPassword = open(self.dbPasswordFile, 'r').readline().strip()
+
     def __init__(self):
         ApsUserDbManager.__lock.acquire()
         try:
@@ -47,34 +72,17 @@ class ApsUserDbManager:
             ApsUserDbManager.__instance = self
             self.lock = threading.RLock()
             self.logger = LoggingManager.getInstance().getLogger(self.__class__.__name__)
-            cm = ConfigurationManager.getInstance()
-            #cm.setOptionsFromConfigFile(ApsUserDbManager.CONFIG_SECTION_NAME, ApsUserDbManager.CONFIG_OPTION_NAME_LIST)
-
-            #dbUser = cm.getDbUser()
-            #self.logger.debug('Using DB user: %s' % dbUser)
-            #dbSchema = cm.getDbSchema()
-            #dbPasswordFile = cm.getDbPasswordFile()
-            #self.logger.debug('Using DB password file: %s' % dbPasswordFile)
-            #dbPassword = open(dbPasswordFile, 'r').readline().strip()
-            #dbPort = cm.getDbPort()
-            #dbHost = cm.getDbHost()
-            #db = cm.getDb()
-            db = "oracle"
-            dbPort = 1527
-            dbHost = "ra.aps.anl.gov"
-            dbName = "aps1"
-            dbSchema = "DCC"
-            dbUser = "glob_conn"
-            dbPassword = "ur2ytkownicy2u"
-            engineUrl = '%s://%s:%s@%s:%s/%s' % (db, dbUser, dbPassword, dbHost, dbPort, dbName)
-            self.logger.debug('Using engine URL: %s' % engineUrl)
+            self.__configure()
+
+            engineUrl = '%s://%s:%s@%s:%s/%s' % (self.db, self.dbUser, self.dbPassword, self.dbHost, self.dbPort, self.dbName)
+            #self.logger.debug('Using engine URL: %s' % engineUrl)
             self.engine = sqlalchemy.create_engine(engineUrl, 
                 pool_size=ApsUserDbManager.DB_CONNECTION_POOL_SIZE, 
                 max_overflow=ApsUserDbManager.DB_CONNECTION_POOL_MAX_OVERFLOW, 
                 pool_recycle=ApsUserDbManager.DB_CONNECTION_POOL_RECYCYLE_TIME, 
                 echo=ApsUserDbManager.DB_CONNECTION_LOGGING_FLAG, 
                 pool_timeout=ApsUserDbManager.DB_CONNECTION_POOL_TIMEOUT)
-            self.metadata = sqlalchemy.MetaData(engineUrl, schema=dbSchema)
+            self.metadata = sqlalchemy.MetaData(engineUrl, schema=self.dbSchema)
 
             self.logger.debug('Mapping DB tables')
             for (dbTableName, (dbEntityClass, dbRelationDict)) in apsUserDbEntityMap.APS_USER_DB_ENTITY_MAP.items():
diff --git a/src/python/dm/common/objects/apsUserInfo.py b/src/python/dm/common/objects/apsUserInfo.py
index 832288759fb74a176bafc2b03f44ac877c0222d2..e5dbc2f863bee9d99c6aeecfd5a864a299b34fed 100755
--- a/src/python/dm/common/objects/apsUserInfo.py
+++ b/src/python/dm/common/objects/apsUserInfo.py
@@ -4,7 +4,7 @@ from dmObject import DmObject
 
 class ApsUserInfo(DmObject):
 
-    DEFAULT_KEY_LIST = [ 'id', 'badgeNumber', 'firstName', 'middleName', 'lastName', 'email' ]
+    DEFAULT_KEY_LIST = [ 'id', 'badgeNumber', 'firstName', 'middleName', 'lastName', 'email', 'passwordHashValue' ]
 
     def __init__(self, dict):
         DmObject.__init__(self, dict)
diff --git a/src/python/dm/common/objects/ldapUserInfo.py b/src/python/dm/common/objects/ldapUserInfo.py
index e9be08a8e86babfff1658684ab4bea0d1ab6fb30..de890773f80e558f15453d5fac1da4cb031ce2bc 100755
--- a/src/python/dm/common/objects/ldapUserInfo.py
+++ b/src/python/dm/common/objects/ldapUserInfo.py
@@ -9,3 +9,5 @@ class LdapUserInfo(DmObject):
     def __init__(self, dict):
         DmObject.__init__(self, dict)
 
+    def getUserPassword(self):
+        return self['userAttrs']['userPassword'][0]
diff --git a/src/python/dm/common/utility/ldapUserManager.py b/src/python/dm/common/utility/ldapUserManager.py
index 8f1e53aacb4f3241be4ce2f18fa419b518d110ca..bbaa5246706432bea7841301af4f1f3e6367b96a 100755
--- a/src/python/dm/common/utility/ldapUserManager.py
+++ b/src/python/dm/common/utility/ldapUserManager.py
@@ -25,6 +25,14 @@ from ldapClient import LdapClient
 
 class LdapUserManager(LdapClient):
 
+    CONFIG_SECTION_NAME = 'LdapUserManager'
+    SERVER_URL_KEY = 'serverurl'
+    ADMIN_DN_KEY = 'admindn'
+    ADMIN_PASSWORD_FILE_KEY = 'adminpasswordfile'
+    USER_DN_FORMAT_KEY = 'userdnformat'
+    GROUP_DN_FORMAT_KEY = 'groupdnformat'
+    MIN_GID_NUMBER_KEY = 'mingidnumber'
+
     def __init__(self, serverUrl, adminDn, adminPasswordFile, userDnFormat, groupDnFormat, minGidNumber=None):
         LdapClient.__init__(self, serverUrl, adminDn, adminPasswordFile)
         self.userDnFormat = userDnFormat
@@ -35,9 +43,29 @@ class LdapUserManager(LdapClient):
         self.groupBaseDn = ','.join(groupDnFormat.split(',')[1:])
         self.getLogger().debug('Group base DN: %s' % self.groupBaseDn)
 
+    @classmethod
+    def createInstance(cls):
+        cm = ConfigurationManager.getInstance()
+        logger = cls.getLogger()
+        logger.debug('Creating LDAP User Manager instance')
+        serverUrl = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.SERVER_URL_KEY)
+        logger.debug('Using server URL: %s' % serverUrl)
+        adminDn = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.ADMIN_DN_KEY)
+        logger.debug('Using admin DN: %s' % adminDn)
+        adminPasswordFile = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.ADMIN_PASSWORD_FILE_KEY)
+        logger.debug('Using admin password file: %s' % adminPasswordFile)
+        userDnFormat = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.USER_DN_FORMAT_KEY)
+        logger.debug('Using user DN format: %s' % userDnFormat)
+        groupDnFormat = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.GROUP_DN_FORMAT_KEY)
+        logger.debug('Using group DN format: %s' % groupDnFormat)
+        minGidNumber = cm.getConfigOption(LdapUserManager.CONFIG_SECTION_NAME, LdapUserManager.MIN_GID_NUMBER_KEY)
+        logger.debug('Using min GID number: %s' % minGidNumber)
+        return LdapUserManager(serverUrl, adminDn, adminPasswordFile, userDnFormat, groupDnFormat, minGidNumber)
+
     @classmethod
     def decodePasswordHash(cls, b64EncodedString):
-        decodedString = b64EncodedString.replace('{SHA}','')
+        beginEncoding = b64EncodedString.find('}')
+        decodedString = b64EncodedString[beginEncoding+1:]
         decodedString = b16encode(b64decode(decodedString)).upper()
         return decodedString
         
@@ -51,10 +79,41 @@ class LdapUserManager(LdapClient):
         """ Get user info. """
         userDn = self.userDnFormat % str(username)
         ldapClient = self.getLdapClient()
-        resultList = ldapClient.search_s(userDn, ldap.SCOPE_BASE)
+        resultList = ldapClient.search_s(userDn, ldap.SCOPE_BASE, attrlist=['*','createTimeStamp','modifyTimestamp'])
         userTuple = resultList[0]
         return LdapUserInfo({'userDn' : userTuple[0], 'userAttrs' : userTuple[1]})
 
+    @LdapClient.executeLdapCall
+    def getUserInfos(self):
+        """ Get user infos. """
+        baseDnPos = self.userDnFormat.find(',')
+        baseDn = self.userDnFormat[baseDnPos+1:]
+        searchFilter = self.userDnFormat[0:baseDnPos] % '*'
+        ldapClient = self.getLdapClient()
+        resultList = ldapClient.search_s(baseDn, ldap.SCOPE_SUBTREE, searchFilter, attrlist=['*','createTimeStamp','modifyTimestamp'])
+        userList = []
+        for result in resultList:
+            userDn = result[0]
+            userAttrs = result[1]
+            userList.append(LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs}))
+        return userList
+
+    @LdapClient.executeLdapCall
+    def getUserInfoMapByUid(self):
+        """ Get user infos. """
+        baseDnPos = self.userDnFormat.find(',')
+        baseDn = self.userDnFormat[baseDnPos+1:]
+        searchFilter = self.userDnFormat[0:baseDnPos] % '*'
+        ldapClient = self.getLdapClient()
+        resultList = ldapClient.search_s(baseDn, ldap.SCOPE_SUBTREE, searchFilter)
+        userMap = {}
+        for result in resultList:
+            userDn = result[0]
+            userAttrs = result[1]
+            uid = userAttrs['uid'][0]
+            userMap[uid] = LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs})
+        return userMap
+
     @LdapClient.executeLdapCall
     def modifyUserInfo(self, username, attrDict):
         """ Modify user. """
@@ -64,21 +123,36 @@ class LdapUserManager(LdapClient):
         userDn = ldapUserInfo.get('userDn')
         userAttrs = ldapUserInfo.get('userAttrs')
         userAttrs2 = copy.copy(userAttrs)
-        for name,value in attrDict.items():
-            ldapName = name
-            ldapValue = value
-            if name == 'passwordHashValue':
-                ldapName = 'userPassword'
-                ldapValue = self.encodePasswordHash(value)
-            if not userAttrs2.has_key(ldapName):
-                raise InvalidArgument('No such attribute: %s' % ldapName)
-
-            if type(ldapValue) == types.ListType:
-                userAttrs2[ldapName] = ldapValue
+
+        middleName = attrDict.get('middleName', '')
+        fullName = '%s, %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', ''))
+        if middleName:
+            fullName = '%s %s' % (fullName, middleName)
+
+        if attrDict.has_key('name'):
+            userAttrs2['cn'] = [attrDict.get('name')]
+            userAttrs2['revcn'] = ['%s %s' % (attrDict.get('lastName'), attrDict.get('firstName'))]
+            userAttrs2['sn'] = [attrDict.get('lastName')]
+            userAttrs2['givenName'] = [attrDict.get('firstName')]
+            userAttrs2['gecos'] = [attrDict.get('name')]
+        for key in ['loginShell', 'allowed-host', 'homeDirectory', 'home7Directory', 'gidNumber' ]:
+            if attrDict.has_key(key):
+                userAttrs2[key] = [attrDict.get(key)]
+        if attrDict.has_key('grp'):
+            userAttrs2['o'] = [attrDict.get('grp')]
+        if attrDict.has_key('inactive'):
+            if attrDict.get('inactive', 'N') == 'Y':
+                userAttrs2['inetUserStatus'] = ['inactive']
             else:
-                userAttrs2[ldapName] = [str(ldapValue)]
+                userAttrs2['inetUserStatus'] = ['active']
+        passwordHash = attrDict.get('userPassword')
+        if not passwordHash:
+            passwordHash = attrDict.get('passwordHashValue')
+        if passwordHash:
+            userAttrs2['userPassword'] = [self.encodePasswordHash(passwordHash)]
+            logger.debug('Encoded password entry: %s' % passwordHash)
+        logger.debug('Modifying user %s with attrs %s' % (username, userAttrs2))
 
-        logger.debug('Modifying user %s attrs %s' % (username, userAttrs2))
         userLdif = ldap.modlist.modifyModlist(userAttrs, userAttrs2)
         ldapClient.modify_s(userDn, userLdif)
         return LdapUserInfo({'userDn' : userDn, 'userAttrs' : userAttrs2})
@@ -93,9 +167,9 @@ class LdapUserManager(LdapClient):
             raise ObjectAlreadyExists('User %s already exists.' % username)
         except ObjectNotFound, ex:
             pass
-        middleName = attrDict.get('middleName', '') 
+        middleName = attrDict.get('middleName') 
         fullName = '%s, %s' % (attrDict.get('lastName', ''), attrDict.get('firstName', ''))
-        if len(middleName):
+        if middleName:
             fullName = '%s %s' % (fullName, middleName)
         badgeNumber = attrDict.get('badgeNumber')
         uid = 'd%s' % badgeNumber
@@ -113,7 +187,10 @@ class LdapUserManager(LdapClient):
         userAttrs['homeDirectory'] = ['/data']
         userAttrs['home7Directory'] = ['/data']
         userAttrs['o'] = [attrDict.get('grp')]
-        userAttrs['inetUserStatus'] = ['active']
+        if attrDict.get('inactive', 'N') == 'Y':
+            userAttrs['inetUserStatus'] = ['inactive']
+        else:
+            userAttrs['inetUserStatus'] = ['active']
         userAttrs['gidNumber'] = ['66001']
         userAttrs['gecos'] = [attrDict.get('name', fullName)]
         userAttrs['sn'] = [attrDict.get('lastName', '')]
@@ -285,22 +362,37 @@ class LdapUserManager(LdapClient):
 
 if __name__ == '__main__':
     utility = LdapUserManager('ldaps://dmid-vm.xray.aps.anl.gov:636', 'uid=dmadmin,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', '/tmp/ldapPassword', userDnFormat='uid=%s,ou=DM,ou=People,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', groupDnFormat='cn=%s,ou=DM,ou=Group,o=aps.anl.gov,dc=aps,dc=anl,dc=gov', minGidNumber=66000)
-    print utility.getGroupInfo(u's1id-test03')
+    #print utility.getGroupInfo(u's1id-test03')
     user = utility.getUserInfo(u'd225159')
     print user
+    print user.getUserPassword()
+    print utility.decodePasswordHash(user.getUserPassword())
+    userMap = utility.getUserInfoMapByUid()
+    print 'N entries: ', len(userMap)
+    print userMap['d225159']
+    #for user in userList:
+    #    print user
+
     utility.modifyUserInfo(u'd225159', {'homeDirectory' : '/data/'})
     user = utility.getUserInfo(u'd225159')
     print user
-    user = utility.getUserInfo(u'd65114')
-    print user
+    #user = utility.getUserInfo(u'd65114')
+    #print user
 
-    passwordHash = LdapUserManager.decodePasswordHash(user['userAttrs']['userPassword'][0])
-    print passwordHash
+    #passwordHash = LdapUserManager.decodePasswordHash(user['userAttrs']['userPassword'][0])
+    #print passwordHash
 
-    attrDict = {'badgeNumber' : '000001', 'name' : 'Test, User 1.', 'firstName' : 'User', 'middleName' : '1.', 'lastName' : 'Test', 'passwordHashValue' : '84673F4A8774846B1C096511C7F6B1329CEE5CCC', 'inactive' : 'N', 'grp' : 'XSD-TEST', 'lastChangeDate' : '2015-02-03 15:52:15', 'email' : 'UTEST1@APS.ANL.GOV', 'isUserNotAnlEmployee' : 'N' }
-    user = utility.createUserInfo(u'd000001', attrDict)
-    user = utility.getUserInfo(u'd000001')
-    print user
+    #print 'Creating user d000001'
+    #user = utility.getUserInfo(u'd000001')
+    #print user
+    #attrDict = {'badgeNumber' : '000001', 'name' : 'Test, User 1.', 'firstName' : 'User', 'middleName' : '1.', 'lastName' : 'Test', 'passwordHashValue' : '84673F4A8774846B1C096511C7F6B1329CEE5CCC', 'inactive' : 'N', 'grp' : 'XSD-TEST', 'lastChangeDate' : '2015-02-03 15:52:15', 'email' : 'UTEST1@APS.ANL.GOV', 'isUserNotAnlEmployee' : 'N' }
+    #try:
+    #    user = utility.createUserInfo(u'd000001', attrDict)
+    #except ObjectAlreadyExists, ex:
+    #    print 'User d000001 already exists, will modify it'
+    #    user = utility.updateUserInfo(u'd000001', attrDict)
+
+    #print user
 
     #print LdapUserManager.encodePasswordHash(passwordHash)